当RecyclerView适合屏幕时,不要折叠工具栏

我使用Android Design Library创建了一个应用程序,带有工具栏和TabLayout。
实际上有2个选项卡,都有2个RecyclerView,滚动时会自动折叠工具栏。

我的问题是:当RecyclerView具有少量项目并且完全适合屏幕时(如在TAB 2中),我可以禁用工具栏折叠吗?

我见过很多像CheeseSquare这样的例子,由Google员工制作,问题仍然存在:即使RecyclerView只有1个项目,工具栏也会隐藏在滚动上。

在此处输入图像描述

我想我可以找出是否在屏幕上显示RecyclerView的第一项,如果是,则禁用工具栏折叠。 前者易于实现,后者又如何呢?

这是我的布局:

        

最终解决方案 (感谢MichałZ。)

关闭/打开工具栏滚动的方法:

 public void turnOffToolbarScrolling() { Toolbar mToolbar = (Toolbar) findViewById(R.id.toolbar); AppBarLayout appBarLayout = (AppBarLayout) findViewById(R.id.appbar_layout); //turn off scrolling AppBarLayout.LayoutParams toolbarLayoutParams = (AppBarLayout.LayoutParams) mToolbar.getLayoutParams(); toolbarLayoutParams.setScrollFlags(0); mToolbar.setLayoutParams(toolbarLayoutParams); CoordinatorLayout.LayoutParams appBarLayoutParams = (CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams(); appBarLayoutParams.setBehavior(null); appBarLayout.setLayoutParams(appBarLayoutParams); } public void turnOnToolbarScrolling() { Toolbar mToolbar = (Toolbar) findViewById(R.id.toolbar); AppBarLayout appBarLayout = (AppBarLayout) findViewById(R.id.appbar_layout); //turn on scrolling AppBarLayout.LayoutParams toolbarLayoutParams = (AppBarLayout.LayoutParams) mToolbar.getLayoutParams(); toolbarLayoutParams.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL | AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS); mToolbar.setLayoutParams(toolbarLayoutParams); CoordinatorLayout.LayoutParams appBarLayoutParams = (CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams(); appBarLayoutParams.setBehavior(new AppBarLayout.Behavior()); appBarLayout.setLayoutParams(appBarLayoutParams); } 

找出我的片段中是否可以看到RecyclerView的最后一项。
如果是,请禁用滚动:

 public void updateToolbarBehaviour(){ if (mLayoutManager.findLastCompletelyVisibleItemPosition() == items.size()-1) { ((MainActivity) getActivity()).turnOffToolbarScrolling(); } else { ((MainActivity)getActivity()).turnOnToolbarScrolling(); } } 

您可以检查RecyclerView的最后一项是否可见。 如果不是,则使用此方法以编程方式关闭滚动:

  //turn off scrolling AppBarLayout.LayoutParams toolbarLayoutParams = (AppBarLayout.LayoutParams) mToolbar.getLayoutParams(); toolbarLayoutParams.setScrollFlags(0); mToolbar.setLayoutParams(toolbarLayoutParams); CoordinatorLayout.LayoutParams appBarLayoutParams = (CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams(); appBarLayoutParams.setBehavior(null); appBarLayout.setLayoutParams(appBarLayoutParams); 

RecyclerView现在(从版本23.2开始)支持wrap_content 。 只需使用wrap_content作为高度。

我采取了稍微不同的方法来解决这个问题。

我创建了一个自定义的AppBarBehavior,它根据单元格禁用它自己。

 public class CustomAppBarBehavior extends AppBarLayout.Behavior { private RecyclerView recyclerView; private boolean enabled; public CustomAppBarBehavior() { } public CustomAppBarBehavior(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean onInterceptTouchEvent(CoordinatorLayout parent, AppBarLayout child, MotionEvent ev) { updatedEnabled(); return enabled && super.onInterceptTouchEvent(parent, child, ev); } @Override public boolean onStartNestedScroll(CoordinatorLayout parent, AppBarLayout child, View directTargetChild, View target, int nestedScrollAxes) { return enabled && super.onStartNestedScroll(parent, child, directTargetChild, target, nestedScrollAxes); } @Override public boolean onNestedFling(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target, float velocityX, float velocityY, boolean consumed) { return enabled && super.onNestedFling(coordinatorLayout, child, target, velocityX, velocityY, consumed); } private void updatedEnabled() { enabled = false; if(recyclerView != null) { RecyclerView.Adapter adapter = recyclerView.getAdapter(); if (adapter != null) { int count = adapter.getItemCount(); RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager(); if (layoutManager != null) { int lastItem = 0; if (layoutManager instanceof LinearLayoutManager) { LinearLayoutManager linearLayoutManager = (LinearLayoutManager) layoutManager; lastItem = Math.abs(linearLayoutManager.findLastCompletelyVisibleItemPosition()); } else if (layoutManager instanceof StaggeredGridLayoutManager) { StaggeredGridLayoutManager staggeredGridLayoutManager = (StaggeredGridLayoutManager) layoutManager; int[] lastItems = staggeredGridLayoutManager.findLastCompletelyVisibleItemPositions(new int[staggeredGridLayoutManager.getSpanCount()]); lastItem = Math.abs(lastItems[lastItems.length - 1]); } enabled = lastItem < count - 1; } } } } public void setRecyclerView(RecyclerView recyclerView) { this.recyclerView = recyclerView; } } 

然后在应用栏布局上设置自定义行为

 appBarBehavior = new CustomAppBarBehavior(); CoordinatorLayout.LayoutParams appBarLayoutParams = (CoordinatorLayout.LayoutParams) appBarLayout.getLayoutParams(); appBarLayoutParams.setBehavior(appBarBehavior); appBarLayout.setLayoutParams(appBarLayoutParams); 

最后页面更改视图寻呼机更新了RecyclerView的行为

 private ViewPager.OnPageChangeListener pageChangeListener = new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageSelected(final int position) { appBarLayout.setExpanded(true, true); appBarLayout.post(new Runnable() { @Override public void run() { appBarBehavior.setRecyclerView(childFragments.get(position).getRecyclerView()); } }); } @Override public void onPageScrollStateChanged(int state) { } }; 

这应该适用于更改数据集。

更改适配器中的数据后添加此代码:

 recyclerView.afterMeasured { val isTurnedOff = recyclerView.turnOffNestedScrollingIfEnoughItems() if (isTurnedOff) appBarLayout.setExpanded(true) } 

这是function:

 inline fun  T.afterMeasured(crossinline action: T.() -> Unit) { viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener { override fun onGlobalLayout() { viewTreeObserver.removeOnGlobalLayoutListener(this) action() } }) } fun RecyclerView.turnOffNestedScrollingIfEnoughItems(): Boolean { val lm = (layoutManager as LinearLayoutManager) val count = if (lm.itemCount <= 0) 0 else lm.itemCount - 1 val isFirstVisible = lm.findFirstCompletelyVisibleItemPosition() == 0 val isLastItemVisible = lm.findLastCompletelyVisibleItemPosition() == count isNestedScrollingEnabled = !(isLastItemVisible && isFirstVisible) return isNestedScrollingEnabled.not() } 
 //turn off scrolling AppBarLayout.LayoutParams toolbarLayoutParams = (AppBarLayout.LayoutParams) mToolbar.getLayoutParams(); toolbarLayoutParams.setScrollFlags(0); mToolbar.setLayoutParams(toolbarLayoutParams); 

只需删除滚动

 app:layout_scrollFlags="scroll|enterAlways" 

所以它应该是

 app:layout_scrollFlags="enterAlways"