美文网首页
RecyclerView GridView模式同一行,使其高度平

RecyclerView GridView模式同一行,使其高度平

作者: 打酱油的日光灯 | 来源:发表于2022-02-23 00:00 被阅读0次

    抓住人生中的一分一秒,胜过虚度中的一月一年!

    小做个动图开篇引题


    懒洋洋.gif
    先看一下效果图
    Demo样式图.gif

    前言

    在开发中,产品会给你绞尽脑汁设计出类似上述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

    相关文章

      网友评论

          本文标题:RecyclerView GridView模式同一行,使其高度平

          本文链接:https://www.haomeiwen.com/subject/tacslrtx.html