自定义可折叠展开的LinearLayout

文章记录了自定义可简单折叠展开的LinearLayout,仅支持竖直方向,可通过对宽度操作实现水平方向。实现思路是继承LinearLayout并重写onMeasure控制高度。还定义了几个属性,使用方式与系统LinearLayout相同,支持折叠展开需添加控制图标。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本篇文章记录一下自定义的可以简单进行折叠展开的LinearLayout,只支持竖直方向,如果需要水平方向的,对宽度进行操作即可。测试效果时,包含的子View是个TextView,也可以是其他的子View。下面是效果图:
这里写图片描述

实现的思路是继承LinearLayout,并重写onMeasure动态的控制高度以达到效果,代码如下:

package cn.znh.expandlinearlayout;

import android.content.Context;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;

/**
 * @author:zhaonh
 * @time 2018/8/27 20:32
 * <p>
 * 可以折叠展开的LinearLayout
 */
public class ExpandLinearLayout extends LinearLayout {

    /**
     * 折叠按钮图标
     */
    private ImageView mExpandBtn;

    /**
     * 是否折叠的临界高度
     */
    private int mLimitHeight = 100;

    /**
     * 是否展开了
     */
    private boolean mIsExpand = false;

    /**
     * 是否支持展开折叠功能
     */
    private boolean mSupportExpand = true;

    public ExpandLinearLayout(Context context) {
        super(context);
        init();
    }

    public ExpandLinearLayout(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public ExpandLinearLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    /**
     * 初始化
     */
    public void init() {
        setOrientation(VERTICAL);
    }

    /**
     * 重写onMeasure动态控制控件的高度
     *
     * @param widthMeasureSpec
     * @param heightMeasureSpec
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        //获取自身的测量高度
        int measureHeight = getMeasuredHeight();

        //设置折叠按钮是否显示
        setExpandBtnVisiable(measureHeight <= mLimitHeight ? View.GONE : View.VISIBLE);

        //如果不支持折叠或者需要展开或者高度不到折叠高度,就保持默认测量
        if (!mSupportExpand || mIsExpand || measureHeight <= mLimitHeight) {
            return;
        }

        //重新设置高度测量参数
        heightMeasureSpec = MeasureSpec.makeMeasureSpec(mLimitHeight, MeasureSpec.EXACTLY);

        //重新测量
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    /**
     * 绑定展开折叠按钮图标
     *
     * @param view
     * @param expandRes
     * @param foldRes
     */
    public void bindExpandButton(ImageView view, final int expandRes, final int foldRes) {
        mExpandBtn = view;
        if (view == null) {
            return;
        }
        view.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                setIsExpand(!mIsExpand);
                mExpandBtn.setImageResource(mIsExpand ? expandRes : foldRes);
            }
        });
        setExpandBtnVisiable(GONE);
    }

    /**
     * 获取临界折叠高度
     *
     * @return
     */
    public int getLimitHeight() {
        return mLimitHeight;
    }

    /**
     * 设置临界折叠高度
     *
     * @param limitHeight
     */
    public void setLimitHeight(int limitHeight) {
        this.mLimitHeight = limitHeight;
    }

    /**
     * 获取是否展开了
     *
     * @return
     */
    public boolean isIsExpand() {
        return mIsExpand;
    }

    /**
     * 设置是否展开
     *
     * @param isExpand
     */
    public void setIsExpand(boolean isExpand) {
        this.mIsExpand = isExpand;
        requestLayout();
    }

    /**
     * 获取当前是否支持折叠展开功能
     *
     * @return
     */
    public boolean isSupportExpand() {
        return mSupportExpand;
    }

    /**
     * 设置折叠还是展开
     *
     * @param supportExpand
     */
    public void setSupportExpand(boolean supportExpand) {
        this.mSupportExpand = supportExpand;
        setExpandBtnVisiable(GONE);
    }

    /**
     * 设置折叠图标是否显示
     *
     * @param visiable
     */
    private void setExpandBtnVisiable(int visiable) {
        if (mExpandBtn != null) {
            if (!mSupportExpand) {
                mExpandBtn.setVisibility(GONE);
            } else {
                mExpandBtn.setVisibility(visiable);
            }
        }
    }
}

简单定义了几个属性:

  • mLimitHeight:是否折叠的临界高度
  • mSupportExpand:是否支持展开折叠功能
  • mIsExpand:是否展开了

具体的使用跟系统的LinearLayout使用方式完全一样(目前设置的只支持竖直方向),如果要支持折叠展开的功能需要根据自己的需求添加一个控制图标(ImageView,位置任意),下面是Demo中xml的布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="10dp">

    <cn.znh.expandlinearlayout.ExpandLinearLayout
        android:id="@+id/expand_linear_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <TextView
            android:id="@+id/tv_content"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

    </cn.znh.expandlinearlayout.ExpandLinearLayout>

    <ImageView
        android:id="@+id/iv_expand_icon"
        android:layout_width="30dp"
        android:layout_height="30dp"
        android:layout_gravity="center_horizontal"
        android:src="@drawable/up" />
</LinearLayout>

在Activity中的使用如下:

package cn.znh.expandlinearlayout;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ImageView;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    /**
     * 展开的文本内容
     */
    private TextView mTvContent;

    /**
     * 可折叠LinearLayout容器
     */
    private ExpandLinearLayout mExpandLinearLayout;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //测试文本
        // String content = "hlkasjdflsakjfdlskjflskjfdlsakjflskjfdlsakjdflsadjkflasjdkflasjfdklasjfd";
        String content = "hlkasjdflsakjfdlskjflskjfdlsakjflskjfdlsakjdflsadjkflasjdkflasjfdklasjfd" +
                "hlkasjdflsakjfdlskjflskjfdlsakjflskjfdlsakjdflsadjkflasjdkflasjfdklasjfd" +
                "hlkasjdflsakjfdlskjflskjfdlsakjflskjfdlsakjdflsadjkflasjdkflasjfdklasjfd" +
                "hlkasjdflsakjfdlskjflskjfdlsakjflskjfdlsakjdflsadjkflasjdkflasjfdklasjfd" +
                "hlkasjdflsakjfdlskjflskjfdlsakjflskjfdlsakjdflsadjkflasjdkflasjfdklasjfd" +
                "hlkasjdflsakjfdlskjflskjfdlsakjflskjfdlsakjdflsadjkflasjdkflasjfdklasjfd" +
                "hlkasjdflsakjfdlskjflskjfdlsakjflskjfdlsakjdflsadjkflasjdkflasjfdklasjfd" +
                "hlkasjdflsakjfdlskjflskjfdlsakjflskjfdlsakjdflsadjkflasjdkflasjfdklasjfd" +
                "hlkasjdflsakjfdlskjflskjfdlsakjflskjfdlsakjdflsadjkflasjdkflasjfdklasjfd" +
                "hlkasjdflsakjfdlskjflskjfdlsakjflskjfdlsakjdflsadjkflasjdkflasjfdklasjfd" +
                "hlkasjdflsakjfdlskjflskjfdlsakjflskjfdlsakjdflsadjkflasjdkflasjfdklasjfd" +
                "hlkasjdflsakjfdlskjflskjfdlsakjflskjfdlsakjdflsadjkflasjdkflasjfdklasjfd" +
                "hlkasjdflsakjfdlskjflskjfdlsakjflskjfdlsakjdflsadjkflasjdkflasjfdklasjfd" +
                "hlkasjdflsakjfdlskjflskjfdlsakjflskjfdlsakjdflsadjkflasjdkflasjfdklasjfd" +
                "hlkasjdflsakjfdlskjflskjfdlsakjflskjfdlsakjdflsadjkflasjdkflasjfdklasjfd" +
                "";

        //设置ExpandLinearLayout
        mExpandLinearLayout = findViewById(R.id.expand_linear_layout);
        mExpandLinearLayout.bindExpandButton((ImageView) findViewById(R.id.iv_expand_icon), R.drawable.down, R.drawable.up);
        mExpandLinearLayout.setLimitHeight(200);
        // mExpandLinearLayout.setSupportExpand(false);

        //设置文本内容
        mTvContent = findViewById(R.id.tv_content);
        mTvContent.setText(content);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值