一、scrollToPosition概述
在Android开发中,常常需要对ListView或者RecyclerView进行滚动控制。scrollToPosition就是一个控制滚动位置的控件。它可以让我们轻松的让ListView或者RecyclerView在指定的Item处停止滚动,从而实现定位到指定位置的操作。
二、scrollToPosition的使用方法
以使用RecyclerView为例,RecyclerView的scrollToPosition方法可以实现指定Item位置的滚动。下面是使用示例:
//获取RecyclerView实例
RecyclerView recyclerView = findViewById(R.id.recycler_view);
//设置LayoutManager
recyclerView.setLayoutManager(new LinearLayoutManager(this));
//设置adapter
MyAdapter adapter = new MyAdapter(data);
recyclerView.setAdapter(adapter);
//滚动到指定位置
recyclerView.scrollToPosition(position);
上述代码实现了RecyclerView在指定位置position
停止滚动的效果。其中,position
是指要滚动到的数据项的位置,从0开始计算。
三、scrollToPosition的原理
在RecyclerView的源码中,scrollToPosition的核心实现方法就是scrollToPositionInt。
void scrollToPositionInt(int position, int subposition, boolean immediate) {
LayoutManager lm = mLayout;
if (lm == null) {
Log.e(TAG, "Cannot scroll to position a LayoutManager set. " +
"Call setLayoutManager with a non-null argument.");
return;
}
lm.scrollToPosition(position);
if (immediate || !mIsAttached) {
// immediate cancel any current scroll animation
stopScroll();
}
if (mPostUpdatesOnAnimation && mEatRequestLayout == 0) {
if (lm != null && lm.isSmoothScrolling()) {
// if we are smooth scrolling, see if the list needs to redraw and intercept
if (subposition == RecyclerView.NO_POSITION) {
if (lm.getChildCount() == 0) {
dispatchLayout();
}
} else if (lm.findViewByPosition(subposition) == null) {
// we are scrolling to child that is not ready, we need to offset to something else
// run a layout, offset, then scroll again
Log.e(TAG, "scrollToPosition doesn't support stack from end. Ignoring");
} else {
lm.scrollToPosition(subposition);
}
mState.mTargetPosition = position;
mState.mTargetOffset = mOrientationHelper.getDecoratedStart(lm.getChildAt(0))
- mOrientationHelper.getStartAfterPadding();
mState.mTargetOffset -= mLayoutState.mScrollOffset;
return;
} else {
// no smooth scrolling -> no need for an extra layout step
dispatchLayout();
}
}
}
可以看出,scrollToPositionInt的基本实现原理就是调用LayoutManager的scrollToPosition方法进行滚动,然后判断是否需要对List重新布局(通过dispatchLayout()
方法实现)。
四、scrollToPosition的注意事项
- scrollToPosition实现滚动的精度不高,如果要实现更高精度的滑动操作,建议使用
smoothScrollToPosition
。 - 当RecyclerView或者ListView顶部留有固定的Header,需要滑动到Header下面的内容时,可能需要自己手动计算滚动距离,并使用
scrollBy
方法进行滚动。 - scrollToPosition只适用于已经布局完成的可见控件,如果想要滚动到非可见的区域或者滚动到未完成布局的位置,建议配合
Post
方法使用。
五、结语
scrollToPosition是一个非常实用的控件,可以对RecyclerView和ListView进行滚动位置的控制。但是,需要注意使用的精度问题,并且在需要滚动到非可见区域或者未完成布局的位置时,需要特别注意。