AppBarLayout + RecycleView 滑动后,item 在一段时间内无法点击的问题

复现

今天开发过程中偶然发现了这个问题。

仔细观察重现条件:

1. 快速滑动 RecycleView 后,立即去点击 item 往往没有反应,第二次点击或者等待片刻后点击可以生效。

2. 缓慢滑动后,立即点击 item,发现大多数情况下是有反应的。

猜测

由上述现象猜测,bug 的发生可能与滑动有关,快速滑动后,recycleview 可能还处于某种滑动状态,而这种状态因为列表已经滑动到尽头而不可见。

尝试

继续尝试发现单独使用 RecycleView,或者在 AppLayoutBar 中不使用 CollapsingToolbarLayout 无此 bug。

定位

那么应该是和 NestScroll 相关了,重写 AppBarLayout.Behavior 打印 log,发现在快速滑动到顶部和底部之后,AppBarLayout 在一段时间内还处于 Fling 状态,那么我们想办法把这段无效的 Fling 干掉就好了。

解决

最后翻找 google 的时候发现这是 google 在修复上个版本嵌套滑动的时候引进来的新 bug。。。

@Keep
public class FixAppBarLayoutBehavior extends AppBarLayout.Behavior {

    public FixAppBarLayoutBehavior() {
        super();
    }

    public FixAppBarLayoutBehavior(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);
            }
        }
    }
}
最后在 AppBarLayout 中使用这个 behavior
好的,下面是Kotlin实现的BRVAH和RecyclerView实现无限循环滚动和可点击item的代码: 1. 首先在build.gradle中添加BRVAH依赖: ``` implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:3.0.4' ``` 2. 在布局文件中添加RecyclerView: ``` <androidx.recyclerview.widget.RecyclerView android:id="@+id/recyclerView" android:layout_width="match_parent" android:layout_height="match_parent" /> ``` 3. 在Activity或Fragment中初始化RecyclerView: ``` val recyclerView = findViewById<RecyclerView>(R.id.recyclerView) val layoutManager = LinearLayoutManager(this) layoutManager.orientation = LinearLayoutManager.HORIZONTAL // 设置为横向滚动 recyclerView.layoutManager = layoutManager ``` 4. 创建Adapter并继承BaseQuickAdapter: ``` class MyAdapter(data: List<String>?) : BaseQuickAdapter<String, BaseViewHolder>(R.layout.item_layout, data) { override fun convert(holder: BaseViewHolder, item: String) { // 设置item的显示内容 holder.setText(R.id.tvItemName, item) } } ``` 5. 创建数据源并初始化Adapter: ``` val dataList = listOf("item1", "item2", "item3", "item4", "item5") val myAdapter = MyAdapter(dataList) recyclerView.adapter = myAdapter ``` 6. 实现无限循环滚动: ``` recyclerView.post { val layoutManager = recyclerView.layoutManager as LinearLayoutManager val firstItem = layoutManager.findFirstVisibleItemPosition() val lastItem = layoutManager.findLastVisibleItemPosition() val itemCount = layoutManager.itemCount // 如果当前第一个可见item是第0个item,则将RecyclerView滚动到最后一个item的位置 if (firstItem == 0) { recyclerView.scrollToPosition(itemCount - 1) } // 如果当前最后一个可见item是最后一个item,则将RecyclerView滚动到第一个item的位置 else if (lastItem == itemCount - 1) { recyclerView.scrollToPosition(0) } } ``` 7. 实现可点击item: ``` myAdapter.setOnItemClickListener { adapter, view, position -> // 处理item点击事件 } ``` 以上就是BRVAH和RecyclerView实现无限循环滚动和可点击item的Kotlin代码。
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值