ScrollView嵌套RecyclerView焦点冲突
这个bug,表现为点击RecyclerView中的item时,ScrollView会自动回滚。而且bug复现的时候,RecyclerView中的item的数据量比较多(一定时需要超过match_parent的高度)。不仅如此,点击item布局中的checkbox也会导致这种情况。所以在网上搜索问题描述,确定时焦点冲突的问题。
大佬一般选择直接手动解决即重写焦点分发的函数。菜鸡一枚,我通过查阅网上的帖子,发现一种比较简单的方法。即用NesetedScrollView去替换ScrollView ,NesetedScrollView是支持嵌套RecycletView的。
<android.support.v4.widget.NestedScrollView>
这里面包含RecyclerView就可以了
</android.support.v4.widget.NestedScrollView>
此外,会带来另一个问题。关于RecyclerView的滚动问题
public void smoothScrollToPosition(int position)
这个函数不起作用了。原因是NestedScrollView在负责滚动。所以RecyclerView的滚动交给了NestedScrollView,我们需要使用NestedScrollView的一些滚动函数。NestedScrollView中也有这个函数,只不过需要我们自己计算滚动量
public final void smoothScrollTo(int x, int y)
由于是垂直滚动,所以参数x可以直接写0。那么如何计算y,我们就需要获得我们点击的item到顶部的偏移量。通过
//y就是对应的偏移量
int y = (int)mRecyclerView.getChildAt(position).getY();
//就好了
mRecyclerView.smoothScrollTo(x, y)
之后,是一些小问题。
由于项目中,点击item,item会扩大,layout属性会改变。为了把item全部显示,所以我给偏移量y增加了layout的高度。
//height的值可以通过View类中的getHeight()函数获取
mRecyclerView.getChildAt(position).getHeight();
//tips:一般不要使用View的height属性直接获取。通过查阅源码,发现height的值除非是明确指出,一般是-1, -2这些值,代表着fill,match_parent和wrap_content。
此外,还不能同步执行,否则,item还是无法完全显示。必须使用NestedScrollView的post函数,把scroll操作卸载runnable里面才行,具体的原因,就不是很清楚了。我在研究一下。
总结
现在解决问题就好了,毕竟是前端bug,但是为了进步,后面时需要翻阅RecyclerView的源码的。现在不急。
这篇文章是对大佬的帖子的扩充。原文请参阅下方连接:
方案