天天看點

RecyclerView GridView模式同一行,使其高度平齊,自動适應高度最大item

抓住人生中的一分一秒,勝過虛度中的一月一年!
小做個動圖開篇引題
RecyclerView GridView模式同一行,使其高度平齊,自動适應高度最大item

先看一下效果圖

RecyclerView GridView模式同一行,使其高度平齊,自動适應高度最大item

前言

在開發中,産品會給你絞盡腦汁設計出類似上述UI,細心的小夥伴發現其中的奧秘沒有,實際上是相同行,高等相等,自适應最多字數文本内容,每行有每行的最大高度,高度不同!也許大家剛看此樣式,so easy~,但要實際去開發,會發現這種樣式倒是不是很好處理,于是我在網上找了找,但是案例基本也不盡人意,一般都是計算item高度,不是很好操作,下面給大家講解一下倆種實作方案,大家接着往下看。

實作思路

下面給大家介紹倆種實作思路,第一種為網上正常思路計算高度,第二種是轉換思維方式實作方案

注:大家說可能會想到高度給match_parent,wrap_content,這些均實作不了,每個item給固定高度,這樣也不行,此問題衍生到了item高度問題

1、第一種思路

首先回顧一下我們要實作的内容,gradView清單,同一行高度相同,自适應文本最大内容,隻限于同一行,說到這裡,我們會想到計算同一行每個item高度,選其中最高的那一個maxHeigh,然後将同一行每個item高度都設定成maxHeigh,每行計算每行的,下面給大家分解一下實作方案

首先需要頁面繪制完畢,此時才可以擷取到所有子view的高度,需要在onLayout執行

第一步擷取子view有多少個,擷取grieView一行有多少個numColumns,将每一行子view放到一起來計算出最高的高度,方法如下

private void setHeights() {
        ListAdapter adapter = getAdapter();

        if(adapter != null) {
            for(int i = 0; i < getChildCount(); i+=numColumns) {
                // Determine the maximum height for this row
                int maxHeight = 0;
                for(int j = i; j < i+numColumns; j++) {
                    View view = getChildAt(j);
                    if(view != null && view.getHeight() > maxHeight) {
                        maxHeight = view.getHeight();
                    }
                }
            }
        }
    }

再次講解一下,numColumns為一行有幾個,i+=numColumns為一次增加一行的數量,然後再周遊每一行子view,擷取最大高度maxHeight高度,
           

第一步完畢,此時輸出的是每一行最大高度maxHeight高度,下一步我們要用這個高度來設定每一行每個item的高度

private void setHeights() {
        ListAdapter adapter = getAdapter();

        if(adapter != null) {
            for(int i = 0; i < getChildCount(); i+=numColumns) {
                // Determine the maximum height for this row
                int maxHeight = 0;
                for(int j = i; j < i+numColumns; j++) {
                    View view = getChildAt(j);
                    if(view != null && view.getHeight() > maxHeight) {
                        maxHeight = view.getHeight();
                    }
                }
                //Log.d(TAG, "Max height for row #" + i/numColumns + ": " + maxHeight);

                // Set max height for each element in this row
                if(maxHeight > 0) {
                    for(int j = i; j < i+numColumns; j++) {
                        View view = getChildAt(j);
                        if(view != null && view.getHeight() != maxHeight) {
                            view.setMinimumHeight(maxHeight);
                        }
                    }
                }
            }
        }
    }
再次講解一下,和第一步周遊每一行view方式相同,擷取到每個子view将高度指派給每個子view
           

依次類推,核心計算規則就是上述展示這樣,這樣雖然能實作,但是存在問題,項目demo中也有這種樣式展示案例,

參考連結,但實際實作了此效果,但不理想,存在問題,有興趣的小夥伴可以研究一下,下面給大家介紹第二種實作思路

2、第二種思路

我們再來回顧一下我們要實作的内容,gradView清單,同一行高度相同,自适應文本最大内容,隻限于同一行,第一種思路已經講解了如何用高度來計算來實作高度等齊效果,下邊我要帶大家換一種思維方式來實作,不去計算高度,完全和計算高度不沾邊的一種思路,思路明确其實很簡單,我們去想,一行中我們要取最大textView的高度,第一種思路是計算出這個高度給其他view,那我們也可以将内容複制給其他TextView,這樣也實作了高度統一了,但是有人會說,這樣豈不是一行内容都一樣了,那我們可以這樣,放倆個TextView,一個正常顯示,一個占位隐藏,so ~恍然大悟了沒有,也就是每一行的view都展示一個文本最長的内容,用占位隐藏來顯示,同一行高度每個item都有最大高度的TextView,那每行高度就實作了等齊了,明白了這種思路是不是感覺很簡單,但是涉及到一個計算規則問題,下面給大家講解一下如何來拆分每行最大文本内容

一個adapter本身有一個List集合,我們再拷貝出來一個,每一行放文本最大字數的List,清單展示的時候依次指派即可

public void changeSpanCount(int spanCount) {
        String str = "";
        mListCopy.clear();
        for (int i = 0; i < mList.size(); i++) {
            if (mList.get(i).getBytes().length > str.getBytes().length) {
                str = mList.get(i);
            }

            if (i % spanCount >= spanCount - 1 || i == mList.size() - 1) {
                for (int z = 0; z < spanCount; z++) {
                    mListCopy.add(str);
                }
                str = "";
            }
        }
思路拆分一下:周遊真是集合中的文本内容,比對出位元組最大的那個,指派給str,i % spanCount >= spanCount - 1,集合的下标與每行的行數取餘,如果等于每行的行數-1,那代表一行中最後一個,比如如果是 一行有3個,周遊從0開始,那便是0,1,2
2%3=3-1為每行最後一個,依次類推,往mListCopy集合中添加與行數相同數量 的  最大文本字數str,依次類推
i == mList.size() - 1的含義為集合末尾不夠整行的文本,這時候就需要處理不夠一行的情況,
i集合下标,從0開始,如果與集合數量-1相等,就是到了最後末尾的那一個
           

思路拆分一下:周遊真實集合中的文本内容,比對出位元組最大的那個,指派給str,i % spanCount >= spanCount - 1,

集合的下标與每行的行數取餘,如果等于每行的行數-1,那代表一行中最後一個,比如如果是 一行有3個,周遊從0開始,那便是0,1,2

2%3=3-1為每行最後一個,依次類推,往mListCopy集合中添加與行數相同數量 的 最大文本字數str,依次類推

i == mList.size() - 1的含義為集合末尾不夠整行的文本,這時候就需要處理不夠一行的情況,

i集合下标,從0開始,如果與集合數量-1相等,就是到了最後末尾的那一個

根據上述思路,将原集合List和ListCopy集合數量相等,指派給清單,List正常展示,ListCopy占位隐藏展示,便實作了上述效果

以上思路demo中都有實作案例,可移步到demo中詳細檢視
最後,祝大家創作愉快
CSDN位址:https://download.csdn.net/download/loocanp/81938415