RecyclerView笔记

1.嵌套在ScrollView的滑动冲突

1
2
3
4
//方式一:
recyclerView.setNestedScrollingEnabled(false);
//方式二:
重写LayoutManager的canScrollVertical,return false。

以上两种方式都是禁止RecyclerView滑动,这是非常愚蠢的做法。RecyclerView不能滑动的话,它的复用机制完全失效,一次性加载所有item,跟一个ScrollView一次加载所有item没什么区别。

忠告:ScrollView与RecyclerView尽量不要嵌套使用。

2.刷新Item中的ProgressBar

  • RecyclerView的ItemAnimator默认设置了DefaultItemAnimator,查看里面的源码可以发现局部刷新某Item是有些动画的,其中就有改变Alpha值的动画。所以刷新ProgressBar时会出现闪烁现象,因此要去掉或者自己实现ItemAnimator。
1
recyclerView.setItemAnimator(null);

3.滑到最底部

  • 这种场景默认方向是Vertical,你也可以改成Horizontal,原理一样的。
  • 判断是否到底部:
1
2
3
4
5
6
7
8
9
10
public static boolean isSlideToBottom(RecyclerView recyclerView) {
if (recyclerView == null) {
return false;
}
if (recyclerView.computeVerticalScrollExtent() + recyclerView.computeVerticalScrollOffset()
>= recyclerView.computeVerticalScrollRange()) {
return true;
}
return false;
}
  • 滑到最底部:
1
2
3
if (isSlideToBottom(recyclerView)) {
recyclerView.smoothScrollToPosition(offset);
}

offset是系统常量。

4.记录和恢复滑动的状态

参考Activtiy的onSaveInstanceState与onRestoreInstanceState,查看RecyclerView的这两个方法。

以下为26.1.0版本源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
protected Parcelable onSaveInstanceState() {
SavedState state = new SavedState(super.onSaveInstanceState());
if (mPendingSavedState != null) {
state.copyFrom(mPendingSavedState);
} else if (mLayout != null) {
state.mLayoutState = mLayout.onSaveInstanceState();
} else {
state.mLayoutState = null;
}
return state;
}
protected void onRestoreInstanceState(Parcelable state) {
if (!(state instanceof SavedState)) {
super.onRestoreInstanceState(state);
return;
}
mPendingSavedState = (SavedState) state;
super.onRestoreInstanceState(mPendingSavedState.getSuperState());
if (mLayout != null && mPendingSavedState.mLayoutState != null) {
mLayout.onRestoreInstanceState(mPendingSavedState.mLayoutState);
}
}

最重要的变量就是mLayout,它就是LayoutManager。LayoutManager顾名思义,就是管理布局状态的,所以保存布局状态当然要使用它了。

获取状态和保存状态:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
Parcelable state = mLayout.onSaveInstanceState();
if (state != null) {
mLayout.onRestoreInstanceState(state);
} else {
//null处理
mRecyclerView.smoothScrollToPosition(0);
}
//smoothScrollToPosition源码
public void smoothScrollToPosition(int position) {
if (mLayoutFrozen) {
return;
}
if (mLayout == null) {
Log.e(TAG, "Cannot smooth scroll without a LayoutManager set. "
+ "Call setLayoutManager with a non-null argument.");
return;
}
mLayout.smoothScrollToPosition(this, mState, position);
}