一、用ViewPager+Fragment布局界面,Fragment里面使用recyclerView来进行布局,当RecycleView滑动到某个位置时,再切换到其他Fragment,然后再切换回来,RecycleView会自己跳到顶部。
解决办法:通过查找相关资料发现,
RecyclerView的 focusableOnTouchMode属性默认是true,所以ViewPager切换时recyclerView自动获得焦点就滚动到头部。
网上的解决方法1、将RecyclerView上面的控件的设置android:focusableInTouchMode="true",或者再加上 android:focusable="true"。
网上的解决方法2、在
scrollview第一个子控件里加上
android:focusable="true"
android:focusableInTouchMode="true"
网上的解决方法3、将recyclerView上面的控件的设置android:descendantFocusability="blocksDescendants"。
该属性是当一个view获取焦点时,定义viewGroup和其子控件两者之间的关系。
属性的值有三种:
beforeDescendants:viewgroup会优先其子类控件而获取到焦点
afterDescendants:viewgroup只有当其子类控件不需要获取焦点时才获取焦点
blocksDescendants:viewgroup会覆盖子类控件而直接获得焦点
以上几种方法,经过使用,并不能解决我项目中的问题,可能有些布局情况适用。后来经过摸索,查找资料,找到了
最终的解决方案:
1.
首先定义两个成员变量:
private int lastPosition = 0;//位置 private int lastOffset = 0;//偏移量
2.在 OnScrollListener,onScrollStateChanged()里添加:
rvHomeMain.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
View topView = layoutManager.getChildAt(0); //获取可视的第一个view
lastOffset = topView.getTop(); //获取与该view的顶部的偏移量
lastPosition = layoutManager.getPosition(topView); //得到该View的数组位置
}
});
3.当离开当前Fragment,再次回来的时候调用
@Override
public void onStart() {
super.onStart();
layoutManager.scrollToPositionWithOffset(lastPosition, lastOffset);
}
这样RecycleView就能恢复到离开时的位置。然后新的问题出现了,当回到原来的位置时,经过几秒钟之后,RecycleView又跳转到了顶部。
查看Fragment的生命周期:
切换回本身的Fragment会打印的方法:
11-29 14:33:55.820: D/AppListFragment(7649): onCreateView
11-29 14:33:55.825: D/AppListFragment(7649): onActivityCreated
11-29 14:33:55.825: D/AppListFragment(7649): onStart
11-29 14:33:55.825: D/AppListFragment(7649): onResume
RecycleView在设置数据的时候又获取到了焦点,解决办法,为Fragment布局中,为RecycleView的最外层控件设置ID,并在代码中得到控件,然后在Fragment的onActivityCreated中调用来夺得焦点(最好放到onActivityCreated最后面)
relativeLayout.setFocusableInTouchMode(true);
relativeLayout.setFocusable(true);
relativeLayout.requestFocus();
最后问题成功解决。
二、RecycleView判断是否滑动到底部
public static boolean isSlideToBottom(RecyclerView recyclerView) {
if (recyclerView == null) return false;
if (recyclerView.computeVerticalScrollExtent() + recyclerView.computeVerticalScrollOffset()
>= recyclerView.computeVerticalScrollRange())
return true;
return false;
}
三、RecycleView跳转至顶部
public static void MoveToPosition(LinearLayoutManager manager, RecyclerView mRecyclerView, int n) {
int firstItem = manager.findFirstVisibleItemPosition();
int lastItem = manager.findLastVisibleItemPosition();
if (n <= firstItem) {
mRecyclerView.scrollToPosition(n);
} else if (n <= lastItem) {
int top = mRecyclerView.getChildAt(n - firstItem).getTop();
mRecyclerView.scrollBy(0, top);
} else {
mRecyclerView.scrollToPosition(n);
}
}