自定义ViewGroup结合merge标签减少嵌套
废话不多说,直奔主题
在开发中经常会继承LinearLayout、RelativeLayout、FrameLayout等系统自带的ViewGroup来实现自己的布局,先来看我之前的写法
首先看布局,拿LinearLayout 举例;文件名R.layout.tes
<?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="35dp"
android:orientation="horizontal">
<TextView
android:layout_width="80dp"
android:layout_height="match_parent"
android:gravity="center"
android:text="名称:"
android:textColor="@color/black" />
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:text="张三"
android:textColor="@color/black" />
</LinearLayout>
再来看看自定义View
public class MyLinearLayout extends LinearLayout {
public MyLinearLayout(Context context) {
this(context, null);
}
public MyLinearLayout(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public MyLinearLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
View view = LayoutInflater.from(context).inflate(R.layout.test, this);
//其他业务省略...
}
}
这样一看好像没什么问题啊,确实没问题;我们接着来看一下测试代码
val layout=MyLinearLayout(this)
XLogUtils.d("childCount数量+$layout.childCount")
通过断点可以看到,MyLinearLayout
只有一个child
是LinearLayout
,我想要的效果是MyLinearLayout
下面直接是两个TextView
,MyLinearLayout
的childLinearLayout
下面才是我XML里面的两个TextView
,我之前一直以为
LayoutInflater.from(context).inflate(R.layout.test, this)
这种写法不会再嵌套一层,在开发中偶然一个debug
发现了这个问题;虽然这种做法对现在的手机性能影响并不是很大,但是多多少少还是有一定影响,平时开发中就要注意,能优化的尽量还是优化一下。
解决办法就是用 < merge >标签
直接上代码
布局R.layout.test
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="35dp"
xmlns:tools="http://schemas.android.com/tools"
tools:parentTag="android.widget.LinearLayout"
android:orientation="horizontal">
<TextView
android:layout_width="80dp"
android:layout_height="match_parent"
android:gravity="center"
android:text="名称:"
android:textColor="@color/black" />
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:text="张三"
android:textColor="@color/black" />
</merge>
tools:parentTag="xxxx"
这里的gogle考虑到在Ide中可能不能直观的看到布局长啥样,这里我继承LinearLayout
就填写tools:parentTag="android.widget.LinearLayout"
;如果自定义RelativrLayot
的话这里就写RelativrLayot,保证java代码继承的ViewGroup和xml一致就Ok。
Java代码
import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import androidx.annotation.Nullable;
public class MyLinearLayout extends LinearLayout {
public MyLinearLayout(Context context) {
this(context, null);
}
public MyLinearLayout(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public MyLinearLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
View view = LayoutInflater.from(context).inflate(R.layout.test, this);
//XML中用merge会使设置的属性失效,所以在代码中在设置一次。
setOrientation(LinearLayout.HORIZONTAL);
setLayoutParams(
new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT
));
//设置背景、居中、边距等等........
//其他业务省略...
}
}
Java代码需要注意的就是XML中用merge
会使设置的属性失效,所以在代码中在设置一次。
然后我们在打断点试一下看下效果
这下layout
就是我们自定义的LinearLayout
,里面是两个TextView
了,少了一层嵌套;开发中的一个小细节,在此记录,有不对的地方欢迎留言指正。