转载请注明出处 https://github.com/baiiu
使用RecyclerView时,调用smoothScrollToPostion()方法滑动到指定位置,但是条目很多时滑动的很慢,本篇文章就是实现RecyclerView的快速滑动。
先介绍如何实现,然后再介绍原理。
1. 实现代码
- 创建FastScrollLinearLayoutManager,继承LinearLayoutManager
- 复写smoothScrollToPosition()方法,主要复写LinearSmoothScroller中方法
代码如下,解释全在注释中:
- 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
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 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
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
从复写的两个方法可以看出,都是为了提高滑动速度。一种是直接修改速度,另外一种是通过减少距离来减少所需时间,间接提高滑动速度。
这两种方法都可以,看自己所需。接下来就讲讲实现的原理。这块我只是梳理的大致的流程,不过至此你已经可以实现快速滑动了。
2. RecyclerView 滑动过程梳理
1.调用RecyclerView.smoothScrollToPosition(position)时
- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
2.LinearLayoutManager中
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
3.LayoutManager中
- 1
- 2
- 3
- 4
- 5
- 6
- 1
- 2
- 3
- 4
- 5
- 6
4.SmoothScroller中
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
5.ViewFlinger中,这是实现滑动的重点,省略了很多代码逻辑
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
6.SmoothScroller中
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
7.Action中
- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
8.ViewFlinger中开始滚动
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
这块粗略的按照流程说了一下滚动过程,涉及的类比较多,最终通过Scroller来进行滚动。
使用Demo
public class FastScrollFragment extends Fragment implements View.OnClickListener {
private RecyclerView recyclerView;
private SimpleTextAdapter mAdapter;
private int mVisibleCount;
@Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_fastscroll, container, false);
recyclerView = (RecyclerView) view.findViewById(R.id.recyclerView);
LinearLayoutManager linearLayoutManager = new FastScrollLinearLayoutManager(getContext());
recyclerView.setLayoutManager(linearLayoutManager);
mAdapter = new SimpleTextAdapter(getContext(), 500);
recyclerView.setAdapter(mAdapter);
recyclerView.getViewTreeObserver()
.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override public void onGlobalLayout() {
recyclerView.getViewTreeObserver()
.removeGlobalOnLayoutListener(this);
LinearLayoutManager linearLayoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
mVisibleCount = linearLayoutManager.findLastVisibleItemPosition()
- linearLayoutManager.findFirstVisibleItemPosition() + 1;
LogUtil.d("显示这么多个: " + mVisibleCount);
}
});
recyclerView.addItemDecoration(
new RecyclerViewDivider(getContext(), LinearLayoutManager.VERTICAL, 20, Color.BLUE));
view.findViewById(R.id.fast_top)
.setOnClickListener(this);
view.findViewById(R.id.fast_top_zhihuway)
.setOnClickListener(this);
view.findViewById(R.id.fast_end)
.setOnClickListener(this);
return view;
}
@Override public void onClick(View v) {
switch (v.getId()) {
case R.id.fast_top_zhihuway:
/*
仿知乎,先直接到一个位置,然后再滑动到顶部
*/
LinearLayoutManager linearLayoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
int firstVisibleItemPosition = linearLayoutManager.findFirstVisibleItemPosition();
if (firstVisibleItemPosition > mVisibleCount) {
recyclerView.scrollToPosition(mVisibleCount);
}
recyclerView.smoothScrollToPosition(0);
break;
/*
这两个都是在LinearSmoothScroller里缩短了单位时间距离以达到减少时间,快速滑动
*/
case R.id.fast_top:
recyclerView.smoothScrollToPosition(10000);
break;
case R.id.fast_end:
recyclerView.smoothScrollToPosition(0);
break;
}
}
}
结语:
本篇文章实现了RecyclerView的快速滚动,但需要注意一个问题:如果你的Item比较复杂,滚动起来会卡顿。 这个在看源码时的一个注释里面有提到,后来实践时确实也发现。不得不说微信朋友圈滑动起来的真的快,它用的是ListView,貌似开启了FastEnable属性。
同时也可以仿照知乎,先使用RecyclerView.scrollToPosition(position)直接滑动到某一个位置后再使用smoothScrollToPosition(0)滑动到顶部。这块在RecyclerView里的Action类中jumpTo()的注释里有提到,如果很远的话可以先到一个位置后再滑动。
这两种滑动到顶部的方式都实现了一个小Demo。测试代码在GitHub上 FastScrollFragment 。
另外在自己写的小项目上也用上了 ZhihuDaily,可以查看这两个Demo来具体了解。
原文地址:http://blog.csdn.net/u014099894/article/details/51855129