• Android案例手册 - 仅一个文件的展开收缩LinearLayout


    往期文章分享

    👉关于作者

    众所周知,人生是一个漫长的流程,不断克服困难,不断反思前进的过程。在这个过程中会产生很多对于人生的质疑和思考,于是我决定将自己的思考,经验和故事全部分享出来,以此寻找共鸣 !!!
    专注于Android/Unity和各种游戏开发技巧,以及各种资源分享(网站、工具、素材、源码、游戏等)
    有什么需要欢迎私我,交流群让学习不再孤单

    在这里插入图片描述

    本文约10千字,新手阅读需要7分钟,复习需要3分钟收藏随时查阅不再迷路

    👉实践过程

    Hello,大家好,小空这两天又开始造Android方面的文章啦,哈哈,总是在Android和Unity中来回横跳。

    前两天我们刚讲解了LinearLayout,那么今天我们自定义一个可展开收缩的LinearLayout。

    仅一个文件(Java版或Kotlin版),随时复制随时用。
    先看效果图
    在这里插入图片描述

    默认展示两个子item,当点击“显示更多”的时候展开所有的子View,当点击“收起内容”的时候除了前两个其他的都隐藏。

    😜使用

    我们先来看看使用方式:

    <cn.phototocartoonstudy.ExpandableLinearLayout
        android:id="@+id/idExpandableLinearLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">
     
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="4dp"
            android:text="芝麻粒儿" />
     
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="4dp"
            android:text="https://juejin.cn/user/4265760844943479" />
     
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="4dp"
            android:text="CSDN" />
     
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="4dp"
            android:text="https://zhima.blog.csdn.net/" />
     
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="4dp"
            android:text="Android/Unity技术" />
    cn.phototocartoonstudy.ExpandableLinearLayout>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

    直接布局中用即可,或者动态代码添加:

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_framelayout);
        ExpandableLinearLayout idExpandableLinearLayout=findViewById(R.id.idExpandableLinearLayout);
        for (int i = 0; i < 4; i++) {
            TextView  txtViewTip = new TextView(this);
            txtViewTip.setText("芝麻粒儿添加更多内容"+i);
            LinearLayout.LayoutParams layoutParamsBottomTxt = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
            txtViewTip.setLayoutParams(layoutParamsBottomTxt);
            idExpandableLinearLayout.addView(txtViewTip);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    😜实现

    说完了使用,我们就来说说实现,前面学完LinearLayout后知道该控件使用了wrap_content,如果子View使用隐藏GONE的形式,则高度自动变化,页面布局中和该控件对其的其他控件也会自动变化。

    所以,当子View的个数小于设置的默认个数,则不用添加底部,如果子View个数大于默认显示个数,则在最后动态添加一个View,当点击展开和隐藏的时候,其他多余的控件进行GONE和VISIBLE的控制即可。

    我们再为控件增加点其他方法:

    1. 修改当隐藏的时候默认展示的条目

    2. 可修改展开和收起的控件文本

    3. 可修改展开和收起控件的字体大小和颜色

    4. 其他功能自己看着加吧

    public void outUseMethodChangeDefaultItemCount(int intDefaultItemCount) {
        this.intDefaultItemCount = intDefaultItemCount;
    }
    public void outUseMethodChangeExpandText(String strExpandText) {
        this.strExpandText = strExpandText;
    }
    public void outUseMethodChangeHideText(String strHideText) {
        this.strHideText = strHideText;
    }
    public void outUseMethodChangeExpandHideTextSize(float fontTextSize) {
        this.fontTextSize = fontTextSize;
    }
    public void outUseMethodChangeExpandHideTextColor(@ColorInt int intTextColor) {
        this.intTextColor = intTextColor;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    Java版

    /**
     * Created by akitaka on 2022-08-11.
     *
     * @author akitaka
     * @filename ExpandableLinearLayout
     */
    
    public class JavaExpandableLinearLayout extends LinearLayout implements View.OnClickListener {
    
        private TextView txtViewTip;
        /**
         * 是否是展开状态,默认是隐藏
         */
        private boolean isExpand = false;
        private boolean boolHasBottom = false;
    
        private int intDefaultItemCount = 2;
        /**
         * 待展开显示的文字
         */
        private String strExpandText = "显示更多";
        /**
         * 待隐藏显示的文字
         */
        private String strHideText = "收起内容";
        private float fontTextSize;
        private int intTextColor;
    
        public void outUseMethodChangeDefaultItemCount(int intDefaultItemCount) {
            this.intDefaultItemCount = intDefaultItemCount;
        }
    
        public void outUseMethodChangeExpandText(String strExpandText) {
            this.strExpandText = strExpandText;
        }
    
        public void outUseMethodChangeHideText(String strHideText) {
            this.strHideText = strHideText;
        }
        public void outUseMethodChangeExpandHideTextSize(float fontTextSize) {
            this.fontTextSize = fontTextSize;
        }
        public void outUseMethodChangeExpandHideTextColor(@ColorInt int intTextColor) {
            this.intTextColor = intTextColor;
        }
        public JavaExpandableLinearLayout(Context context) {
            this(context, null);
        }
    
        public JavaExpandableLinearLayout(Context context, AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public JavaExpandableLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            //设置垂直方向
            setOrientation(VERTICAL);
        }
    
        @Override
        public void setOrientation(int orientation) {
            if (LinearLayout.HORIZONTAL == orientation) {
                throw new IllegalArgumentException("ExpandableLinearLayout只支持垂直布局");
            }
            super.setOrientation(orientation);
        }
    
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            int childCount = getChildCount();
            justToAddBottom(childCount);
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    
    
        /**
         * 判断是否要添加底部
         */
        private void justToAddBottom(int childCount) {
            if (childCount > intDefaultItemCount && !boolHasBottom) {
                boolHasBottom = true;
                //要使用默认底部,并且还没有底部
                LinearLayout linearLayoutBottom = new LinearLayout(getContext());
                LinearLayout.LayoutParams layoutParamsBottom = new LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
                linearLayoutBottom.setLayoutParams(layoutParamsBottom);
                linearLayoutBottom.setGravity(Gravity.CENTER);
                txtViewTip = new TextView(getContext());
                txtViewTip.setText("展开更多");
                txtViewTip.setTextSize(fontTextSize);
                txtViewTip.setTextColor(intTextColor);
                LinearLayout.LayoutParams layoutParamsBottomTxt = new LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
                txtViewTip.setLayoutParams(layoutParamsBottomTxt);
                //设置个边距
                layoutParamsBottomTxt.setMargins(0, 10, 0, 10);
                linearLayoutBottom.addView(txtViewTip);
                linearLayoutBottom.setOnClickListener(this);
                //添加底部
                addView(linearLayoutBottom);
                hide();
                Log.e("TAG", "justToAddBottom: zou l zhe ");
            }
        }
    
        /**
         * 刷新UI
         */
        private void refreshView(View view) {
            int childCount = getChildCount();
            if (childCount > intDefaultItemCount) {
                if (childCount - intDefaultItemCount == 1) {
                    //刚超过默认,判断是否要添加底部
                    justToAddBottom(childCount);
                }
                //大于默认数目的先隐藏
                view.setVisibility(GONE);
            }
        }
    
        /**
         * 展开
         */
        private void expand() {
            for (int i = intDefaultItemCount; i < getChildCount(); i++) {
                //从默认显示条目位置以下的都显示出来
                View view = getChildAt(i);
                view.setVisibility(VISIBLE);
            }
        }
    
        /**
         * 收起
         */
        private void hide() {
            int endIndex = getChildCount() - 1;
            for (int i = intDefaultItemCount; i < endIndex; i++) {
                //从默认显示条目位置以下的都隐藏
                View view = getChildAt(i);
                view.setVisibility(GONE);
            }
        }
    
        @Override
        public void onClick(View v) {
            outUseMethodToggle();
        }
    
        /**
         * 外部也可调用 展开或关闭
         */
        public void outUseMethodToggle() {
            if (isExpand) {
                hide();
                txtViewTip.setText(strExpandText);
            } else {
                expand();
                txtViewTip.setText(strHideText);
            }
            isExpand = !isExpand;
        }
    
        /**
         * 外部可随时添加子view
         */
        public void outUseMethodAddItem(View view) {
            int childCount = getChildCount();
            //插在底部之前
            addView(view, childCount - 1);
            refreshView(view);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171

    Kotlin版

    /**
     * Created by akitaka on 2022-08-11.
     * @author akitaka
     * @filename KotlinExpandableLinearLayout
     */
    class KotlinExpandableLinearLayout :LinearLayout, View.OnClickListener {
        private var txtViewTip: TextView? = null
        constructor(context: Context?) :this(context,null)
        constructor(context: Context?, attrs: AttributeSet?) :this(context,attrs,0)
        constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
        init {
            //设置垂直方向
            orientation = VERTICAL
        }
        /**
         * 是否是展开状态,默认是隐藏
         */
        private var isExpand = false
    
        private var intDefaultItemCount = 2
        private var boolHasBottom = false
    
        /**
         * 待展开显示的文字
         */
        private var strExpandText = "显示更多"
    
        /**
         * 待隐藏显示的文字
         */
        private var strHideText = "收起内容"
        private var fontTextSize = 0f
        private var intTextColor = 0
    
        fun outUseMethodChangeDefaultItemCount(intDefaultItemCount: Int) {
            this.intDefaultItemCount = intDefaultItemCount
        }
    
        fun outUseMethodChangeExpandText(strExpandText: String) {
            this.strExpandText = strExpandText
        }
    
        fun outUseMethodChangeHideText(strHideText: String) {
            this.strHideText = strHideText
        }
    
        fun outUseMethodChangeExpandHideTextSize(fontTextSize: Float) {
            this.fontTextSize = fontTextSize
        }
    
        fun outUseMethodChangeExpandHideTextColor(@ColorInt intTextColor: Int) {
            this.intTextColor = intTextColor
        }
    
        override fun setOrientation(orientation: Int) {
            require(HORIZONTAL != orientation) { "ExpandableLinearLayout只支持垂直布局" }
            super.setOrientation(orientation)
        }
    
    
        override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
            val childCount = childCount
            justToAddBottom(childCount)
            super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        }
    
    
        /**
         * 判断是否要添加底部
         */
        private fun justToAddBottom(childCount: Int) {
            if (childCount > intDefaultItemCount && !boolHasBottom) {
                boolHasBottom = true
                //要使用默认底部,并且还没有底部
                val linearLayoutBottom = LinearLayout(context)
                val layoutParamsBottom = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)
                linearLayoutBottom.layoutParams = layoutParamsBottom
                linearLayoutBottom.gravity = Gravity.CENTER
                txtViewTip = TextView(context)
                txtViewTip!!.text = "展开更多"
                txtViewTip!!.textSize = fontTextSize
                txtViewTip!!.setTextColor(intTextColor)
                val layoutParamsBottomTxt = LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)
                txtViewTip!!.layoutParams = layoutParamsBottomTxt
                //设置个边距
                layoutParamsBottomTxt.setMargins(0, 10, 0, 10)
                linearLayoutBottom.addView(txtViewTip)
                linearLayoutBottom.setOnClickListener(this)
                //添加底部
                addView(linearLayoutBottom)
                hide()
            }
        }
    
        /**
         * 刷新UI
         */
        private fun refreshView(view: View) {
            val childCount = childCount
            if (childCount > intDefaultItemCount) {
                if (childCount - intDefaultItemCount == 1) {
                    //刚超过默认,判断是否要添加底部
                    justToAddBottom(childCount)
                }
                //大于默认数目的先隐藏
                view.setVisibility(GONE)
            }
        }
    
        /**
         * 展开
         */
        private fun expand() {
            for (i in intDefaultItemCount until childCount) {
                //从默认显示条目位置以下的都显示出来
                val view: View = getChildAt(i)
                view.setVisibility(VISIBLE)
            }
        }
    
        /**
         * 收起
         */
        private fun hide() {
            val endIndex = childCount - 1
            for (i in intDefaultItemCount until endIndex) {
                //从默认显示条目位置以下的都隐藏
                val view: View = getChildAt(i)
                view.setVisibility(GONE)
            }
        }
    
        override fun onClick(v: View?) {
            outUseMethodToggle()
        }
    
        /**
         * 外部也可调用 展开或关闭
         */
        fun outUseMethodToggle() {
            if (isExpand) {
                hide()
                txtViewTip!!.text = strExpandText
            } else {
                expand()
                txtViewTip!!.text = strHideText
            }
            isExpand = !isExpand
        }
    
        /**
         * 外部可随时添加子view
         */
        fun outUseMethodAddItem(view: View) {
            val childCount = childCount
            //插在底部之前
            addView(view, childCount - 1)
            refreshView(view)
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160

    👉其他

    📢作者:小空和小芝中的小空
    📢转载说明-务必注明来源:https://zhima.blog.csdn.net/
    📢这位道友请留步☁️,我观你气度不凡,谈吐间隐隐有王者霸气💚,日后定有一番大作为📝!!!旁边有点赞👍收藏🌟今日传你,点了吧,未来你成功☀️,我分文不取,若不成功⚡️,也好回来找我。

    温馨提示点击下方卡片获取更多意想不到的资源。
    空名先生

  • 相关阅读:
    美团前端一面必会手写面试题汇总
    Arrays.asList
    RK3588-EDGE Ubuntu搭建HTTP服务器
    Spring Boot面试题汇总,含答案
    央行副行长:比特币是加密资产,是一种投资工具或替代性投资 2021-04-20
    【SLAM-建图】Ubuntu18.04安装cartographer记录
    java最优建树算法
    【考研】数据结构——线索二叉树
    Elasticsearch(二)kibana数据检索
    Mocha Pro 2024 v11.0.1 Mac版摄像机反求跟踪插件更新:优化AE/PR/OFX/达芬奇工作流程
  • 原文地址:https://blog.csdn.net/qq_27489007/article/details/126846271