大家好,在前段时间我写过用ScrollView实现了自定义滚轮,但是在循环的效果不是特别好。(这次文章底部附上了Demo。O(∩_∩)O~)
最后感谢黑马飞马同学给的意见。
对啊。我们的RecyclerView 是只会加载界面当前显示的Item,然后不管数量再多,也只是在复用相同的View而已。这样我们上面的问题不就解决了。因为比如我们建立一千组一万组数据,我不需要考虑要重新滚回中间,问题1和2就解决了。问题3因为RecyclerView 的特性,也被解决了。是一个很理想的循环滚动的滚轮。
于是就使用RecycleViewer来进行相关的开发。正式起航。
RecyclerView.OnScrollListener
,复写里面的
@Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); switch (newState) { case RecyclerView.SCROLL_STATE_IDLE: ..... ..... ..... break; } }复制代码
当state变为了RecyclerView.SCROLL_STATE_IDLE
就说明了RecyclerView已经停止了。
方法还是一样,通过当前获取到的滚到的Y值,然后除以每项的Item的高度,就能知道当前顶部是处于第几项,然后求余数就知道了当前顶部那项有多少是显示的。在上文我们ScrollView 中,我们使用的是getScrollY()
方法来获取的,我本来在
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
super.onScrollStateChanged(recyclerView, newState);
switch (newState) {
case RecyclerView.SCROLL_STATE_IDLE:
recyclerView.getScrollY();
break;
}
}复制代码
所以我在onScrollStateChanged
方法中通过getScrollY()
方法去获取,多么Easy,哈哈,结果这次是我Too young Too simple,获取到的值一直为0。WTF!!然后就只能通过其他方式来获取滚动的距离。
获取滚动的距离:
public int getScollYDistance(RecyclerView recyclerView) {
LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
int position = layoutManager.findFirstVisibleItemPosition();
View firstVisiableChildView = layoutManager.findViewByPosition(position);
int itemHeight = firstVisiableChildView.getHeight();
return (position) * itemHeight - firstVisiableChildView.getTop();
}复制代码
我想这个大家应该看得懂吧。我画个图解释一下就可以了:
我来大致解释下:如上图所示,我们现在一个Item是100的高度,那我们现在滑到了第二个的20的位置,那是不是一共滑动了120的距离。因为我们当前获取到该手机界面上显示的第一个的position是1,说明position为0的已经被滑出去了。外加这个当前界面的显示的position为1的item有部分被滑出去,所以我们获取它的getTop值为-20,所以是不是正好是当前界面显示的第一个Item的position,乘以itemHeight,减去这个item 的getTop的值。(1 * 100 - (-20) = 120)
好的,我们已经解决了滚动距离的问题。那现在就是我们要让他滚动到一定距离,自动调整自己的位置,来正好显示某个Item项,而不会出现某个Item在界面上显示一半。
滚动后调整距离让RecyclerView 滚到特定的position位置:
我简单介绍,就只分二种情况来谈下(正好滑到一个标准的距离,让Item正好完全显示这种情况我就去除了):
这时候很简单,大家说获取到第一个Item的Position
值,然后调用RecyclerView.smoothScrollToPosition(Position)
,跳到这个positionItem就可以了么。没错。这个是可以。但是调用这个方法,在接下去的第二种情况下就出现问题了。
这时候大家也知道,应该是让当前的屏幕内获取到的first Item 滚动出界面,所以大家一想就说获取第一个Item的Position值,然后调用RecyclerView.smoothScrollToPosition(Position + 1)
不就可以了么。。完美!!。但是结果是不会滚动,原来这个方法当我们的Position + 1
已经出现在屏幕上了。不管是不是第一个,不管处于屏幕的哪个位置,这个RecyclerView就不会滚动。我忍不住又一句 WHF!!。那应该怎么处理呢。
RecyclerView.ScrollBy方法
其实很简单。我直接抛弃了RecyclerView.smoothScrollToPosition
方法,我们看到了,其实我们是不是可以通过判断,第一个Item有没有滚出一半的ItemHeight的距离在外面。无非是二种情况(假设一个ItemHeight为100):
所以代码如下:
private void smoothMoveToPosition(int n, RecyclerView mRecyclerView, LinearLayoutManager mLinearLayoutManager) {
int firstItem = mLinearLayoutManager.findFirstVisibleItemPosition();
if (firstItem == n) {
int top = mRecyclerView.getChildAt(n - firstItem + 1).getTop();
mRecyclerView.smoothScrollBy(0, -(itemHeight - top));
} else {
int top = mRecyclerView.getChildAt(n - firstItem).getTop();
mRecyclerView.smoothScrollBy(0, top);
}
}复制代码
SO EASY..妈妈再也不用担心我的学习了。步步高打火机,哪里不会点哪里