CoordinatorLayout实现自定义头条卡住的解决方案

废话不多说,直接上代码,xml布局如下:


【CoordinatorLayout实现自定义头条卡住的解决方案】效果图如下:

CoordinatorLayout实现自定义头条卡住的解决方案
文章图片
展开状态.jpg
CoordinatorLayout实现自定义头条卡住的解决方案
文章图片
收起状态.jpg
需要针对RecyclerView添加滚动监听器,当RecyclerView停下来的时候判定它距离屏幕顶部的高度,然后让appBarLayout执行展开或者收起,这样就能够规避掉RecyclerView和CoordinatorLayout组合发生抖动之后卡住不动的问题,具体代码如下:
// 添加顶部滑动监听器 if (appBarOffsetListener == null) { appBarOffsetListener = new AppBarLayout.OnOffsetChangedListener() { @Override public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) { if (llTitleContent != null && tvTitle != null) { if (verticalOffset <= -llTitleContent.getHeight() / 2) { tvTitle.setText("互动课程详情"); } else { tvTitle.setText(""); } } } }; } // 头条发生拖动时,需要变换主标题 appBarLayout.addOnOffsetChangedListener(appBarOffsetListener); // 设置内容滚动监听器 if (scrollListener == null) { scrollListener = new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); // 如果当前处于空闲状态,那么可以执行判定操作 if (newState == RecyclerView.SCROLL_STATE_IDLE && rvContentList != null) { int[] location = new int[2]; rvContentList.getLocationInWindow(location); // 两个标题栏的高度(一级标题和二级标题的高度) 加上 状态栏的高度就是recyclerView距离屏幕顶部可能到达最近的距离 float minY = titleHeight * 2 + statusHeight; // 如果当前recyclerView距离最高位置小于5个像素,那么认为应该关闭,否则打开 if (location[1] - minY <= 5) { if (appBarLayout != null) { appBarLayout.setExpanded(false, true); } } // 否则打开整体布局 else if (appBarLayout != null) { appBarLayout.setExpanded(true, true); } } } }; } // 添加滚动监听器,防止卡顿的发生 rvContentList.addOnScrollListener(scrollListener);

下面这个FlingBehavior 主要用于解决RecyclerView滑动之后,第一次点击发生失效的问题
import android.content.Context; import android.support.design.widget.AppBarLayout; import android.support.design.widget.CoordinatorLayout; import android.support.v4.view.ViewCompat; import android.support.v7.widget.RecyclerView; import android.util.AttributeSet; import android.view.View; /** * 用于解决CoordinatorLayout与RecyclerView之间发生的点击问题 */ public class FlingBehavior extends AppBarLayout.Behavior {public FlingBehavior() { }public FlingBehavior(Context context, AttributeSet attrs) { super(context, attrs); }@Override public void onNestedScroll(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int type) { super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, type); stopNestedScrollIfNeeded(dyUnconsumed, child, target, type); }@Override public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, AppBarLayout child, View target, int dx, int dy, int[] consumed, int type) { super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed, type); stopNestedScrollIfNeeded(dy, child, target, type); }private void stopNestedScrollIfNeeded(int dy, AppBarLayout child, View target, int type) { if (type == ViewCompat.TYPE_NON_TOUCH) { final int currOffset = getTopAndBottomOffset(); if ((dy < 0 && currOffset == 0) || (dy > 0 && currOffset == -child.getTotalScrollRange())) { ViewCompat.stopNestedScroll(target, ViewCompat.TYPE_NON_TOUCH); } } } }

    推荐阅读