RecyclerView快速滚动拇指高度对于大型数据集来说太小
我使用默认的RecyclerView
快速滚动,我按照本指南来支持它。
现在,问题在于拇指根据数据集的大小调整其高度。 对于100以上的大型物品,拇指变得非常小,几乎变得难以对拖动作出反应。
请有任何方法可以设置快速滚动拇指的最小高度。
这只是一个部分答案; 我错过了(至少)一个难题,但希望别人能够弄清楚。
一旦你将必要的属性添加到你的<RecyclerView>
标签中(正如在OP问题中链接的答案中所述),滚动条大拇指的大小/定位由LinearLayoutManager
的三个方法控制:
int computeVerticalScrollRange()
:滚动条轨道的大小。
int computeVerticalScrollExtent()
:滚动条的大小。
int computeVerticalScrollOffset()
:滚动条轨道顶部与滚动条拇指顶部之间的距离。
这些方法的单位是任意的; 只要所有三种方法共享相同的单位,就可以使用任何你喜欢的东西。 默认情况下, LinearLayoutManager
将使用两组单位之一:
mSmoothScrollbarEnabled == true
:根据RecyclerView
可见项目的像素大小使用单位。
mSmoothScrollbarEnabled == false
:根据RecyclerView
的适配器中可见项目的位置使用单位。
要自己控制滚动条的大小,你必须重写这些方法......但这里是我缺少的一部分: 在我所有的实验中, computeVerticalScrollExtent()
都不会被系统调用 。 这就是说,我们仍然可以在这里展示一些进展。
首先,我创建了一个简单的适配器,该适配器显示500个CardView
其中包含项目的位置。 我已经使用一些非常简单(但丑陋)的drawables快速滚动。 下面是滚动条的外观,只有一个默认的LinearLayoutManager
实现:
正如你发现的,有500个(小)项目,滚动条的拇指非常小,很难点击。 通过重写computeVerticalScrollRange()
来返回一个固定的常量,我们可以使滚动条显着变大......我基本上随机挑选了5000
,以显示主要变化:
当然,现在滚动条并不像你所期望的那样工作; 通过拖动列表来滚动列表,因为正常情况下拇指的移动比应该更多,并且通过拖动拇指来快速滚动列表会使列表移动得远远小于它应该的。
在我的设备上,随机选择范围5000
,如下所示重写computeVerticalScrollOffset()
,使滚动条的拇指完美移动,因为我通过拖动列表来滚动列表:
@Override
public int computeVerticalScrollRange(RecyclerView.State state) {
return 5000;
}
@Override
public int computeVerticalScrollOffset(RecyclerView.State state) {
return (int) (super.computeVerticalScrollOffset(state) / 23.5f);
}
但是,这仍然不能解决第二个问题:拖动拇指本身不能正确滚动列表。 正如我上面提到的,看起来在这里做的适当的事情是重写computeVerticalScrollExtent()
,但是系统从不调用这个方法。 我甚至重写它只是抛出一个异常,我的应用程序从不崩溃。
希望这至少有助于指出人们正确的方向来获得完整的解决方案。
PS:我在这个答案中包含的computeVerticalScrollRange()
和computeVerticalScrollOffset()
的实现是故意简单的(阅读:伪造)。 “真正的”实现将更加复杂; 默认的LinearLayoutManager
实现考虑了设备方向,列表中第一个和最后一个可见项目,两个方向离屏的项目数量,平滑滚动,各种布局标志等等。
我通过从android.support.v7.widget.FastScroller复制Fast Scroller类来解决此问题
然后我删除了从xml启用的快速滚动并使用下面的代码应用fastscroller
StateListDrawable verticalThumbDrawable = (StateListDrawable) getResources().getDrawable(R.drawable.fastscroll_sunnah);
Drawable verticalTrackDrawable = getResources().getDrawable(R.drawable.fastscroll_line_drawable);
StateListDrawable horizontalThumbDrawable = (StateListDrawable)getResources().getDrawable(R.drawable.fastscroll_sunnah);
Drawable horizontalTrackDrawable = getResources().getDrawable(R.drawable.fastscroll_line_drawable);
Resources resources = getContext().getResources();
new FastScroller(recyclerView, verticalThumbDrawable, verticalTrackDrawable,
horizontalThumbDrawable, horizontalTrackDrawable,
resources.getDimensionPixelSize(R.dimen.fastscroll_default_thickness),
resources.getDimensionPixelSize(R.dimen.fastscroll_minimum_range),
resources.getDimensionPixelOffset(R.dimen.fastscroll_margin));
在FastScroller类中,我扩展了defaultWidth
FastScroller(RecyclerView recyclerView, StateListDrawable verticalThumbDrawable,
Drawable verticalTrackDrawable, StateListDrawable horizontalThumbDrawable,
Drawable horizontalTrackDrawable, int defaultWidth, int scrollbarMinimumRange,
int margin) {
...
this.defaultWidth = defaultWidth;
...
然后我用这种方法更新了代码
void updateScrollPosition(int offsetX, int offsetY) {
...
mVerticalThumbHeight = Math.max(defaultWidth * 4, Math.min(verticalVisibleLength,
(verticalVisibleLength * verticalVisibleLength) / verticalContentLength));
...
...
mHorizontalThumbWidth = Math.max(defaultWidth * 4, Math.min(horizontalVisibleLength,
(horizontalVisibleLength * horizontalVisibleLength) / horizontalContentLength));
...
}
这可以确保拇指的最小高度/宽度是默认宽度的4倍
这是一个已知问题,于2017年8月开放:https://issuetracker.google.com/issues/64729576
还在等待关于如何通过快速滚动大量数据来管理RecyclerView
建议。 到目前为止,Google没有就此问题回复建议:(
纳比勒的答案与问题中提到的解决方法类似。 Nabil的答案复制FastScroller
类并修改它以确保最小的拇指大小,并且问题的解决方法扩展了FastScroller
(但必须保留在android.support.v7.widget
包中)以确保最小的拇指大小。
上一篇: RecyclerView fast scroll thumb height too small for large data set