RecyclerView GridView模式同一行,使其高度平齊,自動(dòng)適應(yīng)高度最大item

抓住人生中的一分一秒,勝過虛度中的一月一年!

小做個(gè)動(dòng)圖開篇引題


懶洋洋.gif
先看一下效果圖
Demo樣式圖.gif

前言

在開發(fā)中,產(chǎn)品會(huì)給你絞盡腦汁設(shè)計(jì)出類似上述UI,細(xì)心的小伙伴發(fā)現(xiàn)其中的奧秘沒有,實(shí)際上是相同行,高等相等,自適應(yīng)最多字?jǐn)?shù)文本內(nèi)容,每行有每行的最大高度,高度不同!也許大家剛看此樣式,so easy~,但要實(shí)際去開發(fā),會(huì)發(fā)現(xiàn)這種樣式倒是不是很好處理,于是我在網(wǎng)上找了找,但是案例基本也不盡人意,一般都是計(jì)算item高度,不是很好操作,下面給大家講解一下倆種實(shí)現(xiàn)方案,大家接著往下看。



實(shí)現(xiàn)思路

下面給大家介紹倆種實(shí)現(xiàn)思路,第一種為網(wǎng)上常規(guī)思路計(jì)算高度,第二種是轉(zhuǎn)換思維方式實(shí)現(xiàn)方案

注:大家說可能會(huì)想到高度給match_parent,wrap_content,這些均實(shí)現(xiàn)不了,每個(gè)item給固定高度,這樣也不行,此問題衍生到了item高度問題

1、第一種思路

首先回顧一下我們要實(shí)現(xiàn)的內(nèi)容,gradView列表,同一行高度相同,自適應(yīng)文本最大內(nèi)容,只限于同一行,說到這里,我們會(huì)想到計(jì)算同一行每個(gè)item高度,選其中最高的那一個(gè)maxHeigh,然后將同一行每個(gè)item高度都設(shè)置成maxHeigh,每行計(jì)算每行的,下面給大家分解一下實(shí)現(xiàn)方案

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

第一步獲取子view有多少個(gè),獲取grieView一行有多少個(gè)numColumns,將每一行子view放到一起來計(jì)算出最高的高度,方法如下

 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為一行有幾個(gè),i+=numColumns為一次增加一行的數(shù)量,然后再遍歷每一行子view,獲取最大高度maxHeight高度,

第一步完畢,此時(shí)輸出的是每一行最大高度maxHeight高度,下一步我們要用這個(gè)高度來設(shè)置每一行每個(gè)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方式相同,獲取到每個(gè)子view將高度賦值給每個(gè)子view

依次類推,核心計(jì)算規(guī)則就是上述展示這樣,這樣雖然能實(shí)現(xiàn),但是存在問題,項(xiàng)目demo中也有這種樣式展示案例,
參考鏈接,但實(shí)際實(shí)現(xiàn)了此效果,但不理想,存在問題,有興趣的小伙伴可以研究一下,下面給大家介紹第二種實(shí)現(xiàn)思路



2、第二種思路

我們再來回顧一下我們要實(shí)現(xiàn)的內(nèi)容,gradView列表,同一行高度相同,自適應(yīng)文本最大內(nèi)容,只限于同一行,第一種思路已經(jīng)講解了如何用高度來計(jì)算來實(shí)現(xiàn)高度等齊效果,下邊我要帶大家換一種思維方式來實(shí)現(xiàn),不去計(jì)算高度,完全和計(jì)算高度不沾邊的一種思路,思路明確其實(shí)很簡單,我們?nèi)ハ?,一行中我們要取最大textView的高度,第一種思路是計(jì)算出這個(gè)高度給其他view,那我們也可以將內(nèi)容復(fù)制給其他TextView,這樣也實(shí)現(xiàn)了高度統(tǒng)一了,但是有人會(huì)說,這樣豈不是一行內(nèi)容都一樣了,那我們可以這樣,放倆個(gè)TextView,一個(gè)正常顯示,一個(gè)占位隱藏,so ~恍然大悟了沒有,也就是每一行的view都展示一個(gè)文本最長的內(nèi)容,用占位隱藏來顯示,同一行高度每個(gè)item都有最大高度的TextView,那每行高度就實(shí)現(xiàn)了等齊了,明白了這種思路是不是感覺很簡單,但是涉及到一個(gè)計(jì)算規(guī)則問題,下面給大家講解一下如何來拆分每行最大文本內(nèi)容

一個(gè)adapter本身有一個(gè)List集合,我們再拷貝出來一個(gè),每一行放文本最大字?jǐn)?shù)的List,列表展示的時(shí)候依次賦值即可

 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 = "";
            }
        }
思路拆分一下:遍歷真是集合中的文本內(nèi)容,比對出字節(jié)最大的那個(gè),賦值給str,i % spanCount >= spanCount - 1,集合的下標(biāo)與每行的行數(shù)取余,如果等于每行的行數(shù)-1,那代表一行中最后一個(gè),比如如果是 一行有3個(gè),遍歷從0開始,那便是0,1,2
2%3=3-1為每行最后一個(gè),依次類推,往mListCopy集合中添加與行數(shù)相同數(shù)量 的  最大文本字?jǐn)?shù)str,依次類推
i == mList.size() - 1的含義為集合末尾不夠整行的文本,這時(shí)候就需要處理不夠一行的情況,
i集合下標(biāo),從0開始,如果與集合數(shù)量-1相等,就是到了最后末尾的那一個(gè)

思路拆分一下:遍歷真實(shí)集合中的文本內(nèi)容,比對出字節(jié)最大的那個(gè),賦值給str,i % spanCount >= spanCount - 1,
集合的下標(biāo)與每行的行數(shù)取余,如果等于每行的行數(shù)-1,那代表一行中最后一個(gè),比如如果是 一行有3個(gè),遍歷從0開始,那便是0,1,2
2%3=3-1為每行最后一個(gè),依次類推,往mListCopy集合中添加與行數(shù)相同數(shù)量 的 最大文本字?jǐn)?shù)str,依次類推
i == mList.size() - 1的含義為集合末尾不夠整行的文本,這時(shí)候就需要處理不夠一行的情況,
i集合下標(biāo),從0開始,如果與集合數(shù)量-1相等,就是到了最后末尾的那一個(gè)

根據(jù)上述思路,將原集合List和ListCopy集合數(shù)量相等,賦值給列表,List正常展示,ListCopy占位隱藏展示,便實(shí)現(xiàn)了上述效果

以上思路demo中都有實(shí)現(xiàn)案例,可移步到demo中詳細(xì)查看

最后,祝大家創(chuàng)作愉快

CSDN地址:https://download.csdn.net/download/loocanp/81938415

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容