Is it really intended that the Toolbar in a AppBarLayout is scrollable although the main container with the "appbar_scrolling_view_behavior" has not enough content
So, proper credit, this answer almost solved it for me https://stackoverflow.com/a/32923226/5050087. But since it was not showing the toolbar when you actually had an scrollable recyclerview and its last item was visible (it would not show the toolbar on the first scroll up), I decided to modify it and adapt it for an easier implementation and for dynamic adapters.
First, you must create a custom layout behavior for you appbar:
public class ToolbarBehavior extends AppBarLayout.Behavior{
private boolean scrollableRecyclerView = false;
private int count;
public ToolbarBehavior() {
}
public ToolbarBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onInterceptTouchEvent(CoordinatorLayout parent, AppBarLayout child, MotionEvent ev) {
return scrollableRecyclerView && super.onInterceptTouchEvent(parent, child, ev);
}
@Override
public boolean onStartNestedScroll(CoordinatorLayout parent, AppBarLayout child, View directTargetChild, View target, int nestedScrollAxes, int type) {
updatedScrollable(directTargetChild);
return scrollableRecyclerView && super.onStartNestedScroll(parent, child, directTargetChild, target, nestedScrollAxes, type);
}
@Override
public boolean onNestedFling(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target, float velocityX, float velocityY, boolean consumed) {
return scrollableRecyclerView && super.onNestedFling(coordinatorLayout, child, target, velocityX, velocityY, consumed);
}
private void updatedScrollable(View directTargetChild) {
if (directTargetChild instanceof RecyclerView) {
RecyclerView recyclerView = (RecyclerView) directTargetChild;
RecyclerView.Adapter adapter = recyclerView.getAdapter();
if (adapter != null) {
if (adapter.getItemCount()!= count) {
scrollableRecyclerView = false;
count = adapter.getItemCount();
RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
if (layoutManager != null) {
int lastVisibleItem = 0;
if (layoutManager instanceof LinearLayoutManager) {
LinearLayoutManager linearLayoutManager = (LinearLayoutManager) layoutManager;
lastVisibleItem = Math.abs(linearLayoutManager.findLastCompletelyVisibleItemPosition());
} else if (layoutManager instanceof StaggeredGridLayoutManager) {
StaggeredGridLayoutManager staggeredGridLayoutManager = (StaggeredGridLayoutManager) layoutManager;
int[] lastItems = staggeredGridLayoutManager.findLastCompletelyVisibleItemPositions(new int[staggeredGridLayoutManager.getSpanCount()]);
lastVisibleItem = Math.abs(lastItems[lastItems.length - 1]);
}
scrollableRecyclerView = lastVisibleItem < count - 1;
}
}
}
} else scrollableRecyclerView = true;
}
}
Then, you only need to define this behavior for you appbar in your layout file:
I haven't tested it for screen rotation so let me know if it works like this. I guess it should work as I don't think the count variable is saved when the rotation happens, but let me know if it doesn't.
This was the easiest and cleanest implementation for me, enjoy it.