CoordinatorLayout实现自定义头条卡住的解决方案
废话不多说,直接上代码,xml布局如下:
【CoordinatorLayout实现自定义头条卡住的解决方案】效果图如下:
文章图片
展开状态.jpg
文章图片
收起状态.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);
}
}
}
}
推荐阅读
- 关于QueryWrapper|关于QueryWrapper,实现MybatisPlus多表关联查询方式
- MybatisPlus使用queryWrapper如何实现复杂查询
- python学习之|python学习之 实现QQ自动发送消息
- 孩子不是实现父母欲望的工具——林哈夫
- SpringBoot调用公共模块的自定义注解失效的解决
- opencv|opencv C++模板匹配的简单实现
- Node.js中readline模块实现终端输入
- python自定义封装带颜色的logging模块
- java中如何实现重建二叉树
- 列出所有自定义的function和view