天天看點

RecyclerView滾動指定條目并在頁面中居中

RecyclerView滾動指定條目并在頁面中居中

内容提要

本次的需求是通過指定position來控制條目滾動,并且要滾動到指定到中間的位置。

下面先上圖,看看是不是你要

RecyclerView滾動指定條目并在頁面中居中

如下介紹主要的步驟

帶着問題去做需求是一個很不錯的方式:

1.我們要滾動條目?怎麼滾動呢?

2.滾動到指定的position是很容易,但是條目并沒有到指定準确的位置,怎麼辦呢?

上面的兩個問題解決了,我們的需求就完成了。

下面先解決第一個問題

這個很簡單了,我就一筆帶過好了啊。

recyclerView.scrollToPosition(trim);
           

你沒看錯就是這個方法。(手動滑稽)

然後是第二個問題

RecyclerView滾動指定條目并在頁面中居中
上圖中的标号請無視。
           

這裡要計算了,首先我們要先确定條目的位置,其次是将該條目移動到中間的位置。

将條目1,移動到箭頭所在位置。

view1.getX();擷取view1的x坐标(黃色到第一個藍色的距離),擷取view的寬度的一半(藍色到綠色的距離),然後在擷取外層view的寬度(我這是直接填充的螢幕寬度,黃色到第二個藍色的距離),然後計算出view1需要移動的x距離。如下:

recyclerView.smoothScrollBy(changeX - (width - childWidth), );
           

計算看着比較簡單,但是實際卻需要做很多限制。以下注意事項:

1.首先RecyclerView的條目是要複用的,是以實際的view數目是螢幕上顯示的,再多緩存一個或者兩個view(可以通過getChildCount()方法擷取數量),是以計算RecyclerView條目的時候要注意不要取到螢幕外的view,會造成空指針。

2.其次就是要注意position是否大于了緩存的view數目,如果大于我們就取最大的view角标;并且我們還要區分前後滾動,因為如果大于緩存的view數向後滾動就是就是取最大的view角标,如果小于緩存的view數向後滾動的話就直接取position作為角标的view了。

上面寫的有點難懂,下面直接上代碼,

if (trim > recyclerView.getChildCount() - ) {
                            if (oldInt > trim) {
                                childAt = recyclerView.getChildAt();

                            } else {

                                childAt = recyclerView.getChildAt(recyclerView.getChildCount() - );
                            }
                        } else {
                            if (oldInt > trim) {
                                childAt = recyclerView.getChildAt();
                            } else {
                                childAt = recyclerView.getChildAt(trim);
                            }
                        }
           

結合代碼看會比較容易。

遺留的問題

基本上處理好上面兩個問題就可以達到我們的需求了,但是這裡還有一個遺留的問題,就是關于界面顯示的view數目和RecycledViewPool中view數目的關系。這裡我是實驗發現一般都會緩存一個view。是以在上面調用getChildAt()減去了1的,防止越界出現擷取到空view的情況。

放出關鍵的代碼部分,如果需要可以去文末下載下傳demo

final int width = rect.right / ;
                //角标數,不能大于頁面最大的數目
                final Integer trim = Integer.parseInt(ed.getText().toString().trim());

                recyclerView.scrollToPosition(trim);
                mHandler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        if (trim > recyclerView.getChildCount() - ) {
                            if (oldInt > trim) {
                                childAt = recyclerView.getChildAt();

                            } else {

                                childAt = recyclerView.getChildAt(recyclerView.getChildCount() - );
                            }
                        } else {
                            if (oldInt > trim) {
                                childAt = recyclerView.getChildAt();
                            } else {
                                childAt = recyclerView.getChildAt(trim);
                            }
                        }
                        changeX = (int) childAt.getX();
                        childWidth = childAt.getMeasuredWidth() / ;

                        Log.d("x", changeX + "--" + recyclerView.getChildCount());
                        recyclerView.smoothScrollBy(changeX - (width - childWidth), );
                    }
                }, );

                mHandler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        oldInt = trim;

                    }
                }, );
           

finish

雖然需求看着很簡單,但是涉及到的知識點還是很好,應該了解一下。

下載下傳demo點這裡

繼續閱讀