在 RecyclerView 中快速滚动 [英] Snappy scrolling in RecyclerView
问题描述
我正在尝试将新的 RecyclerView
类用于我希望组件在滚动时捕捉到特定元素的场景(想到旧的 Android Gallery
作为具有中心锁定项目的此类列表的示例).
I am trying to use the new RecyclerView
class for a scenario where I want the component to snap to a specific element when scrolling (The old Android Gallery
comes to mind as an example of such a list with a center-locked item).
这是我目前采用的方法:
This is the approach that I am taking thus far:
我有一个接口,ISnappyLayoutManager
,它包含一个方法,getPositionForVelocity
,它计算视图应该在给定初始滑动速度的哪个位置结束滚动.>
I have an interface, ISnappyLayoutManager
, which contains a method, getPositionForVelocity
, which calculates at which position the view should end the scrolling given the initial fling velocity.
public interface ISnappyLayoutManager {
int getPositionForVelocity(int velocityX, int velocityY);
}
然后我有一个类,SnappyRecyclerView
,它子类化 RecyclerView
并覆盖它的 fling() 方法,以便将视图抛出正确的数量:
Then I have a class, SnappyRecyclerView
, which subclasses RecyclerView
and overrides its fling() method in such a manner as to fling the view the exact right amount:
public final class SnappyRecyclerView extends RecyclerView {
/** other methods deleted **/
@Override
public boolean fling(int velocityX, int velocityY) {
LayoutManager lm = getLayoutManager();
if (lm instanceof ISnappyLayoutManager) {
super.smoothScrollToPosition(((ISnappyLayoutManager) getLayoutManager())
.getPositionForVelocity(velocityX, velocityY));
}
return true;
}
}
出于多种原因,我对这种方法不太满意.首先,必须将其子类化以实现某种类型的滚动似乎与RecyclerView"的哲学背道而驰.其次,如果我只想使用默认的 LinearLayoutManager
,这会变得有些复杂,因为我必须弄乱它的内部结构以了解它的当前滚动状态并准确计算它滚动到的位置.最后,这甚至没有考虑到所有可能的滚动场景,就像您移动列表然后暂停然后抬起手指一样,没有发生 fling 事件(速度太低),因此列表保持在一半位置.这可能可以通过向 RecyclerView
添加滚动状态侦听器来解决,但这也感觉很麻烦.
I am not very happy with this approach for several reasons. First of all, it seems counter to the philosophy of the 'RecyclerView' to have to subclass it to implement a certain type of scrolling. Second, if I want to just use the default LinearLayoutManager
, this becomes somewhat complex as I have to mess around with its internals in order to understand its current scroll state and calculate out exactly where this scrolls to. Finally, this doesn't even take care of all the possible scroll scenarios, as if you move the list and then pause and then lift a finger, no fling event occurs (the velocity is too low) and so the list remains in a halfway position. This can possibly be taken care of by adding an on scroll state listener to the RecyclerView
, but that also feels very hacky.
我觉得我一定错过了什么.有没有更好的方法来做到这一点?
I feel like I must be missing something. Is there a better way to do this?
推荐答案
With LinearSnapHelper
,现在这很容易.
With LinearSnapHelper
, this is now very easy.
你需要做的就是:
SnapHelper helper = new LinearSnapHelper();
helper.attachToRecyclerView(recyclerView);
就是这么简单!请注意,从版本 24.2.0 开始,支持库中添加了 LinearSnapHelper
.
It's that simple! Note that LinearSnapHelper
was added in the Support Library starting from version 24.2.0.
这意味着您必须将此添加到您的应用模块的 build.gradle
Meaning you have to add this to your app module's build.gradle
compile "com.android.support:recyclerview-v7:24.2.0"
AndroidX LinearSnapHelper
这篇关于在 RecyclerView 中快速滚动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!