Android 具有 gridlayout smoothScrollTo() 速度的 RecyclerView
Android RecyclerView with gridlayout smoothScrollTo() speed
我有一个带有 gridlayoutmanager 的 recyclerview。
如果我运行代码
recycler.smoothScrollTo(adapter.getItemCount())
回收器滚动到最后一个元素的速度非常快。我在 Whosebug 上尝试了一些解决方案来使滚动变慢,但都适用于 Linearlayoutmanager 而不是 Gridlayoutmanager。
有什么帮助吗?
我不能确定你的问题是什么。但我很幸运有一个非常简单的 GridLayoutManager recyclerview 演示,非常小的示例项目。我创建了一个 so
分支并添加了一个与您相同的按钮。
查找:https://github.com/Gryzor/GridToShowAds/compare/so?expand=1
.setOnClickListener { mainRecyclerView.smoothScrollToPosition(data.size) }
仅此一项就可以了。
查看源代码,这是一个非常简单的示例,用于不相关的东西,但恰好有一辆带网格布局的房车:)
更新
您真正想要的是控制 recyclerView 滚动的速度。好的
- 驱动滚动的不是 RecyclerView,实际上是
LayoutManager
。怎么会?
如果您查看 RV 的源代码...
public void smoothScrollToPosition(int position) {
...
mLayout.smoothScrollToPosition(this, mState, position);
}
所以它最终调用 mLayout
。这是什么?
@VisibleForTesting LayoutManager mLayout;
因此,您的 LayoutManager#smoothScroll... 方法已被使用。
现在为科学反编译GridLayoutManager:
@Override
public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state,
int position) {
LinearSmoothScroller linearSmoothScroller =
new LinearSmoothScroller(recyclerView.getContext());
linearSmoothScroller.setTargetPosition(position);
startSmoothScroll(linearSmoothScroller);
}
注意:这个方法实际上在LinearLayoutManager
中,因为GridLayoutManager
是一个子class,它不会覆盖方法
一个LinearSmoothScroller
!;虽然没有指定速度的参数...
看看:
public class LinearSmoothScroller extends RecyclerView.SmoothScroller {
private static final boolean DEBUG = false;
private static final float MILLISECONDS_PER_INCH = 25f;
private static final int TARGET_SEEK_SCROLL_DISTANCE_PX = 10000;
...
}
此 class 有一个 start()
方法,描述为:
* Starts a smooth scroll for the given target position.
谁叫这个?
mLayout.smoothScrollToPosition 方法在 startSmoothScroll(...)
调用结束时执行。
public void startSmoothScroll(SmoothScroller smoothScroller) {
Starts a smooth scroll using the provided {@link SmoothScroller}.
mSmoothScroller.start(mRecyclerView, this);
所以...代替所有这些,您的问题的答案是:
您需要通过子class创建 GridLayoutManager 的扩展,并在其中覆盖 smoothScrollToPosition
方法,以提供您自己的 Scroller 逻辑。
虽然线程要仔细,LayoutManager 并不是有史以来的 "simplest" classes,掌握它们可能相当复杂。
祝你好运! :)
我的简单工作解决方案目前仍在实施计时器,然后使用它。
final CountDownTimer scrollUp_timer = new CountDownTimer(50000, 30) {
@Override
public void onTick(long millisUntilFinished) {
if (layoutManager != null && layoutManager.findFirstVisibleItemPosition() != 0) searchRecyclerView.smoothScrollToPosition(layoutManager.findFirstVisibleItemPosition()-1);
}
@Override
public void onFinish() {
try{
}catch(Exception e){
// log
}
}
};
scrollUp.setOnDragListener(new View.OnDragListener() {
@Override
public boolean onDrag(View view, DragEvent dragEvent) {
layoutManager = ((GridLayoutManager)searchRecyclerView.getLayoutManager());
int action = dragEvent.getAction();
if (action == DragEvent.ACTION_DRAG_ENTERED) {
scrollUp_timer.start();
} else if (action == DragEvent.ACTION_DRAG_EXITED) {
searchRecyclerView.scrollBy(0,0);
scrollUp_timer.cancel();
}
return true;
}
});
我有一个带有 gridlayoutmanager 的 recyclerview。
如果我运行代码
recycler.smoothScrollTo(adapter.getItemCount())
回收器滚动到最后一个元素的速度非常快。我在 Whosebug 上尝试了一些解决方案来使滚动变慢,但都适用于 Linearlayoutmanager 而不是 Gridlayoutmanager。
有什么帮助吗?
我不能确定你的问题是什么。但我很幸运有一个非常简单的 GridLayoutManager recyclerview 演示,非常小的示例项目。我创建了一个 so
分支并添加了一个与您相同的按钮。
查找:https://github.com/Gryzor/GridToShowAds/compare/so?expand=1
.setOnClickListener { mainRecyclerView.smoothScrollToPosition(data.size) }
仅此一项就可以了。
查看源代码,这是一个非常简单的示例,用于不相关的东西,但恰好有一辆带网格布局的房车:)
更新
您真正想要的是控制 recyclerView 滚动的速度。好的
- 驱动滚动的不是 RecyclerView,实际上是
LayoutManager
。怎么会?
如果您查看 RV 的源代码...
public void smoothScrollToPosition(int position) {
...
mLayout.smoothScrollToPosition(this, mState, position);
}
所以它最终调用 mLayout
。这是什么?
@VisibleForTesting LayoutManager mLayout;
因此,您的 LayoutManager#smoothScroll... 方法已被使用。
现在为科学反编译GridLayoutManager:
@Override
public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state,
int position) {
LinearSmoothScroller linearSmoothScroller =
new LinearSmoothScroller(recyclerView.getContext());
linearSmoothScroller.setTargetPosition(position);
startSmoothScroll(linearSmoothScroller);
}
注意:这个方法实际上在LinearLayoutManager
中,因为GridLayoutManager
是一个子class,它不会覆盖方法
一个LinearSmoothScroller
!;虽然没有指定速度的参数...
看看:
public class LinearSmoothScroller extends RecyclerView.SmoothScroller {
private static final boolean DEBUG = false;
private static final float MILLISECONDS_PER_INCH = 25f;
private static final int TARGET_SEEK_SCROLL_DISTANCE_PX = 10000;
...
}
此 class 有一个 start()
方法,描述为:
* Starts a smooth scroll for the given target position.
谁叫这个?
mLayout.smoothScrollToPosition 方法在 startSmoothScroll(...)
调用结束时执行。
public void startSmoothScroll(SmoothScroller smoothScroller) {
Starts a smooth scroll using the provided {@link SmoothScroller}.
mSmoothScroller.start(mRecyclerView, this);
所以...代替所有这些,您的问题的答案是:
您需要通过子class创建 GridLayoutManager 的扩展,并在其中覆盖 smoothScrollToPosition
方法,以提供您自己的 Scroller 逻辑。
虽然线程要仔细,LayoutManager 并不是有史以来的 "simplest" classes,掌握它们可能相当复杂。
祝你好运! :)
我的简单工作解决方案目前仍在实施计时器,然后使用它。
final CountDownTimer scrollUp_timer = new CountDownTimer(50000, 30) {
@Override
public void onTick(long millisUntilFinished) {
if (layoutManager != null && layoutManager.findFirstVisibleItemPosition() != 0) searchRecyclerView.smoothScrollToPosition(layoutManager.findFirstVisibleItemPosition()-1);
}
@Override
public void onFinish() {
try{
}catch(Exception e){
// log
}
}
};
scrollUp.setOnDragListener(new View.OnDragListener() {
@Override
public boolean onDrag(View view, DragEvent dragEvent) {
layoutManager = ((GridLayoutManager)searchRecyclerView.getLayoutManager());
int action = dragEvent.getAction();
if (action == DragEvent.ACTION_DRAG_ENTERED) {
scrollUp_timer.start();
} else if (action == DragEvent.ACTION_DRAG_EXITED) {
searchRecyclerView.scrollBy(0,0);
scrollUp_timer.cancel();
}
return true;
}
});