处理这种情况的最佳方法可能是以某种方式计算基于每个项目大小的滚动条范围。这可能不实际或不理想。取而代之的是,下面是一个自定义RecyclerView的简单实现,您可以使用它来尝试获取所需内容。它会告诉你如何使用各种滚动方法来控制滚动条。它会根据显示的项目数量将拇指大小粘贴到初始大小。关键要记住的是滚动范围是任意的,但所有其他测量(范围,偏移量)必须使用相同的单位。
请参阅computeVerticalScrollRange()
的文档。
下面是结果的视频。
更新:的代码已被更新,以纠正一些问题:拇指的运动是干少和拇指现在在底部来休息的RecyclerView
滚动至底部。代码后面还有一些注意事项。
MyRecyclerView.java(更新)
public class MyRecyclerView extends RecyclerView {
// The size of the scroll bar thumb in our units.
private int mThumbHeight = UNDEFINED;
// Where the RecyclerView cuts off the views when the RecyclerView is scrolled to top.
// For example, if 1/4 of the view at position 9 is displayed at the bottom of the RecyclerView,
// mTopCutOff will equal 9.25. This value is used to compute the scroll offset.
private float mTopCutoff = UNDEFINED;
public MyRecyclerView(Context context) {
super(context);
}
public MyRecyclerView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public MyRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
/**
* Retrieves the size of the scroll bar thumb in our arbitrary units.
*
* @return Scroll bar thumb height
*/
@Override
public int computeVerticalScrollExtent() {
return (mThumbHeight == UNDEFINED) ? 0 : mThumbHeight;
}
/**
* Compute the offset of the scroll bar thumb in our scroll bar range.
*
* @return Offset in scroll bar range.
*/
@Override
public int computeVerticalScrollOffset() {
return (mTopCutoff == UNDEFINED) ? 0 : (int) ((getCutoff() - mTopCutoff) * ITEM_HEIGHT);
}
/**
* Computes the scroll bar range. It will simply be the number of items in the adapter
* multiplied by the given item height. The scroll extent size is also computed since it
* will not vary. Note: The RecyclerView must be positioned at the top or this method
* will throw an IllegalStateException.
*
* @return The scroll bar range
*/
@Override
public int computeVerticalScrollRange() {
if (mThumbHeight == UNDEFINED) {
LinearLayoutManager lm = (LinearLayoutManager) getLayoutManager();
int firstCompletePositionw = lm.findFirstCompletelyVisibleItemPosition();
if (firstCompletePositionw != RecyclerView.NO_POSITION) {
if (firstCompletePositionw != 0) {
throw (new IllegalStateException(ERROR_NOT_AT_TOP_OF_RANGE));
} else {
mTopCutoff = getCutoff();
mThumbHeight = (int) (mTopCutoff * ITEM_HEIGHT);
}
}
}
return getAdapter().getItemCount() * ITEM_HEIGHT;
}
/**
* Determine where the RecyclerVIew display cuts off the list of views. The range is
* zero through (getAdapter().getItemCount() - 1) inclusive.
*
* @return The position in the RecyclerView where the displayed views are cut off. If the
* bottom view is partially displayed, this will be a fractional number.
*/
private float getCutoff() {
LinearLayoutManager lm = (LinearLayoutManager) getLayoutManager();
int lastVisibleItemPosition = lm.findLastVisibleItemPosition();
if (lastVisibleItemPosition == RecyclerView.NO_POSITION) {
return 0f;
}
View view = lm.findViewByPosition(lastVisibleItemPosition);
float fractionOfView;
if (view.getBottom() < getHeight()) { // last visible position is fully visible
fractionOfView = 0f;
} else { // last view is cut off and partially displayed
fractionOfView = (float) (getHeight() - view.getTop())/(float) view.getHeight();
}
return lastVisibleItemPosition + fractionOfView;
}
private static final int ITEM_HEIGHT = 1000; // Arbitrary, make largish for smoother scrolling
private static final int UNDEFINED = -1;
private static final String ERROR_NOT_AT_TOP_OF_RANGE
= "RecyclerView must be positioned at the top of its range.";
}
告诫 下列问题可能需要根据实施加以解决。
示例代码仅适用于垂直滚动。示例代码还假定RecyclerView
的内容是静态的。支持RecyclerView
的数据的任何更新都可能导致滚动问题。如果在RecyclerView
的第一个全屏上显示的任何视图的高度发生任何更改,则滚动将关闭。下面的更改可能会工作正常。这是由于代码如何计算滚动偏移量。
要确定滚动偏移的基准值(变量mTopCutOff
),必须在第一次调用computeVerticalScrollRange()
时将RecyclerView滚动到顶部,以便可以测量视图;否则,代码将停止并显示“IllegalStateException”。如果完全滚动RecyclerView
,这对定位更改尤其麻烦。一个简单的方法就是禁止恢复滚动位置,所以它默认在方向改变的顶部。
(以下是可能不是最好的解决办法...)
var lm: LinearLayoutManager = object : LinearLayoutManager(this) {
override fun onRestoreInstanceState(state: Parcelable?) {
// Don't restore
}
}
我希望这有助于。 (顺便说一句,你的MCVE使这更容易。)
在我看来,问题是你有一个滚动视图里面的回收视图,你呢? – azizbekian
@azizbekian不,情况并非如此。 – FWeigl
你有恒定数量的行吗?如果它是可变的,我认为你不能管理它。鉴于房车的性质,你有刚刚被提取时的高度 – crgarridos