解决ViewPager切换时(如首页tab切换)页面自动跳到recyclerView的位置的BUG

作者: php 发布时间: 2019-08-02 浏览: 4590 次 编辑

ViewPager里面放了几个Fragment,
Fragment里要使用RecyclerView,但是在RecyclerView上面还有其他的东西,所以我把它们放在LinearLayout里面,再把LinearLayout放在ScrollView里面。这样便实现了我要的效果。
ViewPager可以正常地水平滑动切换,ScrollView也可以正常地垂直滑动

问题是:
不管是滑动切换ViewPager还是直接点击下面的按钮切换(就像微信),当切换动画结束,并且RecyclerView部分可见时,如果这时RecyclerView上边缘低于屏幕的上边缘,ScrollView就会跳动一下,使RecyclerView的上边缘就正好挨着屏幕上边缘。
切换过程中RecyclerView不可见时不会发生跳动。
切换过程中RecyclerView上边缘高于屏幕上边缘时,不会发生跳动。
其他原因导致的RecyclerView可见,如Activity的跳转,不会发生跳动。

解决方案:在Fragment跟布局的位置添加android:descendantFocusability="blocksDescendants"或设置成android:focusableInTouchMode="true"

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:descendantFocusability="blocksDescendants">    <android.support.v7.widget.RecyclerView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:overScrollMode="never"/></RelativeLayout>

分析:
这个问题应该是ViewPager在切换是RecyclerView获得了焦点,因为根据https://code.google.com/p/android/issues/detail?id=81854#c11(貌似需要科学上网),recyclerView的 focusableOnTouchMode属性默认是true,所以ViewPager切换时recyclerView自动获得焦点就滚动到头部,解决办法是在Fragment跟布局的位置添加android:descendantFocusability="blocksDescendants"或设置成android:focusableInTouchMode="true"
属性的值有三种:
beforeDescendants:viewgroup会优先其子类控件而获取到焦点
afterDescendants:viewgroup只有当其子类控件不需要获取焦点时才获取焦点
blocksDescendants:viewgroup会覆盖子类控件而直接获得焦点

引出相关的问题:
scrollview中如果嵌套有EditText也会导致页面自动滚动到EditText的位置
解决办法:
在scrollview嵌套的LinearLayout的标签上设置属性

                <ScrollView
                android:id="@+id/scrollView"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:fillViewport="true">
                      <LinearLayout
                        android:layout_width="match_parent"
                        android:layout_height="match_parent"
                        android:focusable="true"
                        android:focusableInTouchMode="true"
                        android:orientation="vertical">
                          。。。。。                       </LinearLayout>
                  </ScrollView>

注意点:
在EditText外层的布局中可能设置无效,需要设置在ScrollView的LinearLayout上