merge标签可以降低UI层级
1.<merge />只可以作为xml layout的根节点。
2.当需要inflate的xml layout本身是由merge作为根节点的话,需要将被导入的xml layout置于viewGroup中,同时需要设置attachToRoot为True。
一个布局可以重复利用,可以抽成一个view,这个view继承的viewgroup是其xml的跟布局,这样xml的根布局就可以用merge替代,
// 继承RelativeLayout
public class RadioPalyerHistoryView extends RelativeLayout {
public RadioPalyerHistoryView(@NonNull Context context) {
this(context, null);
}
public RadioPalyerHistoryView(@NonNull Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public RadioPalyerHistoryView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mContext = context;
// 必须attachToRoot为true
View view = LayoutInflater.from(context).inflate(R.layout.radio_palyer_history_right_layout, this, true);
// 跟布局是merge标签,在跟布局设置的padding不管用了,代码设置
setPadding(CommonUtils.dip2px(context,12),CommonUtils.dip2px(context,10),CommonUtils.dip2px(context,12),CommonUtils.dip2px(context,10));
}
其跟布局先用RelativeLayout,这样方便写布局看下子view的布局位置,等写好布局了,用merge替换
<?xml version="1.0" encoding="utf-8"?>
<!-- 跟布局是RelativeLayout-->
<merge xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:tools="http://schemas.android.com/tools">
<TextView
android:id="@+id/tv_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@color/black_27292B"
android:textSize="15sp"
tools:text="何以小 第二集"
android:ellipsize="end"
android:singleLine="true"/>
<TextView
android:id="@+id/tv_progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="13sp"
android:textColor="@color/black_989A9B"
android:layout_marginTop="5dp"
tools:text="听至10%"
android:layout_below="@id/tv_title"/>
<TextView
android:id="@+id/tv_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="13sp"
android:textColor="@color/black_989A9B"
android:layout_marginTop="5dp"
tools:text="4个小时前"
android:layout_below="@id/tv_title"
android:layout_toRightOf="@id/tv_progress"
android:layout_marginLeft="7dp"/>
</merge>
优点:减少布局层级;缺点:跟布局merge不能设置padding(设置的padding不起作用),可以把设置在跟布局的padding设置到代码;不可以设置固定值的宽高,例如:
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="280dp"
android:paddingLeft="12dp"
android:paddingRight="12dp"
android:paddingTop="10dp"
android:paddingBottom="10dp">
layout_height="280dp"和:paddingLeft="12dp"这些都不会起作用,需要在代码中设置;
原因是:在在LayoutInflater的inflate方法中,
public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot) {
synchronized (mConstructorArgs) {
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "inflate");
final Context inflaterContext = mContext;
final AttributeSet attrs = Xml.asAttributeSet(parser);
Context lastContext = (Context) mConstructorArgs[0];
mConstructorArgs[0] = inflaterContext;
View result = root;
try {
// 省略
...
// merge标签必须有root,attachToRoot为true
if (TAG_MERGE.equals(name)) {
if (root == null || !attachToRoot) {
throw new InflateException("<merge /> can be used only with a valid "
+ "ViewGroup root and attachToRoot=true");
}
rInflate(parser, root, inflaterContext, attrs, false);
} else {
...
} catch (XmlPullParserException e) {
...
return result;
}
}
void rInflate(XmlPullParser parser, View parent, Context context,
AttributeSet attrs, boolean finishInflate) throws XmlPullParserException, IOException {
final int depth = parser.getDepth();
int type;
boolean pendingRequestFocus = false;
while (((type = parser.next()) != XmlPullParser.END_TAG ||
parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {
if (type != XmlPullParser.START_TAG) {
continue;
}
final String name = parser.getName();
if (TAG_REQUEST_FOCUS.equals(name)) {
pendingRequestFocus = true;
consumeChildElements(parser);
} else if (TAG_TAG.equals(name)) {
parseViewTag(parser, parent, attrs);
} else if (TAG_INCLUDE.equals(name)) {
if (parser.getDepth() == 0) {
throw new InflateException("<include /> cannot be the root element");
}
parseInclude(parser, context, parent, attrs);
} else if (TAG_MERGE.equals(name)) {
throw new InflateException("<merge /> must be the root element");
} else {
//。 没有用merge标签的宽高属性,padding属性,直接addview到parent中
final View view = createViewFromTag(parent, name, context, attrs);
final ViewGroup viewGroup = (ViewGroup) parent;
final ViewGroup.LayoutParams params = viewGroup.generateLayoutParams(attrs);
rInflateChildren(parser, view, attrs, true);
viewGroup.addView(view, params);
}
}
if (pendingRequestFocus) {
parent.restoreDefaultFocus();
}
if (finishInflate) {
parent.onFinishInflate();
}
}
网友评论