本篇文章记录一下自定义的可以简单进行折叠展开的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);
}
}