一、用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);
}
}