RecyclerView滚动指定条目并在页面中居中
内容提要
本次的需求是通过指定position来控制条目滚动,并且要滚动到指定到中间的位置。
下面先上图,看看是不是你要
如下介绍主要的步骤
带着问题去做需求是一个很不错的方式:
1.我们要滚动条目?怎么滚动呢?
2.滚动到指定的position是很容易,但是条目并没有到指定准确的位置,怎么办呢?
上面的两个问题解决了,我们的需求就完成了。
下面先解决第一个问题
这个很简单了,我就一笔带过好了啊。
recyclerView.scrollToPosition(trim);
你没看错就是这个方法。(手动滑稽)
然后是第二个问题
上图中的标号请无视。
这里要计算了,首先我们要先确定条目的位置,其次是将该条目移动到中间的位置。
将条目1,移动到箭头所在位置。
view1.getX();获取view1的x坐标(黄色到第一个蓝色的距离),获取view的宽度的一半(蓝色到绿色的距离),然后在获取外层view的宽度(我这是直接填充的屏幕宽度,黄色到第二个蓝色的距离),然后计算出view1需要移动的x距离。如下:
recyclerView.smoothScrollBy(changeX - (width - childWidth), 0);
计算看着比较简单,但是实际却需要做很多限制。以下注意事项:
1.首先RecyclerView的条目是要复用的,所以实际的view数目是屏幕上显示的,再多缓存一个或者两个view(可以通过getChildCount()方法获取数量),所以计算RecyclerView条目的时候要注意不要取到屏幕外的view,会造成空指针。
2.其次就是要注意position是否大于了缓存的view数目,如果大于我们就取最大的view角标;并且我们还要区分前后滚动,因为如果大于缓存的view数向后滚动就是就是取最大的view角标,如果小于缓存的view数向后滚动的话就直接取position作为角标的view了。
上面写的有点难懂,下面直接上代码,
if (trim > recyclerView.getChildCount() - 1) { if (oldInt > trim) { childAt =
recyclerView.getChildAt(0); } else { childAt =
recyclerView.getChildAt(recyclerView.getChildCount() -1); } } else { if (oldInt
> trim) { childAt = recyclerView.getChildAt(0); } else { childAt =
recyclerView.getChildAt(trim); } }
结合代码看会比较容易。
遗留的问题
基本上处理好上面两个问题就可以达到我们的需求了,但是这里还有一个遗留的问题,就是关于界面显示的view数目和RecycledViewPool中view数目的关系。这里我是实验发现一般都会缓存一个view。所以在上面调用getChildAt()减去了1的,防止越界出现获取到空view的情况。
放出关键的代码部分,如果需要可以去文末下载demo
final int width = rect.right / 2; //角标数,不能大于页面最大的数目 final Integer trim =
Integer.parseInt(ed.getText().toString().trim());
recyclerView.scrollToPosition(trim); mHandler.postDelayed(new Runnable() {
@Override public void run() { if (trim > recyclerView.getChildCount() - 1) { if
(oldInt > trim) { childAt = recyclerView.getChildAt(0); } else { childAt =
recyclerView.getChildAt(recyclerView.getChildCount() -1); } } else { if (oldInt
> trim) { childAt = recyclerView.getChildAt(0); } else { childAt =
recyclerView.getChildAt(trim); } } changeX = (int) childAt.getX(); childWidth =
childAt.getMeasuredWidth() /2; Log.d("x", changeX + "--" +
recyclerView.getChildCount()); recyclerView.smoothScrollBy(changeX - (width -
childWidth),0); } }, 50); mHandler.postDelayed(new Runnable() { @Override public
void run() { oldInt = trim; } }, 100);
finish
虽然需求看着很简单,但是涉及到的知识点还是很好,应该了解一下。
下载demo点这里 <https://download.csdn.net/download/shayubuhuifei/10578796>
热门工具 换一换