RecyclerView滚动指定条目并在页面中居中

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点这里

评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值