Android技巧之ViewStub的使用
程序员文章站
2022-03-20 13:10:02
...
小提示:使用AndroidStudio3.1.2版查看View树
最顶部菜单栏Tools –> Layout Inspector,在弹出的窗口选择设备单击“OK”即可。
一、使用include加载布局
MainActivity的布局文件如下所示:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
tools:context=".MainActivity">
<!--填充布局,不带merge-->
<include
android:id="@+id/hear_include_1"
layout="@layout/hear_1_layout" />
</LinearLayout>
1.1 未使用merge的情况
hear_1_layout.xml的源码如下所示:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#f00">
<TextView
android:id="@+id/tv_1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:gravity="center"
android:padding="5dp"
android:text="头标题1"
android:textColor="@android:color/black"
android:textSize="24sp" />
</FrameLayout>
1.2 使用merge的情况
此处将MainActivity布局文件中include标签的属性layout的值改为hear_2_layout
hear_2_layout.xml的源码如下所示:
<?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="wrap_content"
android:background="#0f0"
>
<TextView
android:id="@+id/tv_2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:padding="5dp"
android:text="头标题2"
android:textColor="@android:color/black"
android:textSize="24sp" />
</merge>
结论:
(1) 未使用merge时:include标签加载布局的时候,其所加载的布局根View所有的属性参数都是有效的
(2) 使用merge时:include标签加载布局的时候,实质就是将merge中的子View添加至include标签的父View下,所以merge标签的布局属性是无效的
二、使用ViewStub
MainActivity的布局文件如下所示:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
tools:context=".MainActivity">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<!--填充布局,不带merge-->
<include
android:id="@+id/hear_include_1"
layout="@layout/hear_1_layout" />
<!--填充布局,带merge-->
<include
android:id="@+id/hear_include_2"
layout="@layout/hear_2_layout" />
<TextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#00f"
android:text="Hello World!"
android:textColor="@android:color/black"
android:textSize="24sp" />
<!--
填充布局,不带merge。inflateId指定的id是layout中
所加载布局的根View的Id。
注意:不管layout中所加载的布局的根View是否添加过id,
inflateId所指定的id都是layout所加载布局的根View的id
-->
<ViewStub
android:id="@+id/vs_1"
android:layout_width="match_parent"
android:layout_height="150dp"
android:background="#ff0"
android:inflatedId="@+id/vs_hear_1"
android:layout="@layout/hear_1_layout" />
<!--填充布局,带merge。这样使用将会报错-->
<!--<ViewStub
android:id="@+id/vs_2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#ff0"
android:inflatedId="@+id/vs_hear_2"
android:layout="@layout/hear_2_layout" />-->
</LinearLayout>
</ScrollView>
</LinearLayout>
MainActivity.java的源码如下所示:
package org.chromium.chrome.browser.viewstubdemo;
import android.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewStub;
import android.widget.LinearLayout;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private ViewStub vs1;
private String TAG = "MainActivity_layout";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView tv = (TextView) findViewById(R.id.tv);
vs1 = (ViewStub) findViewById(R.id.vs_1);
tv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//vs1.inflate();此方法只能执行一次,第二次执行就会报错
//报错如下:java.lang.IllegalStateException:
// ViewStub must have a non-null ViewGroup viewParent
//vs1.inflate();
vs1.setVisibility(View.VISIBLE);
View fl_1 = MainActivity.this.findViewById(R.id.fl);
//layout is null
Log.e(TAG, "layout is " + fl_1);
View fl_2 = MainActivity.this.findViewById(R.id.vs_hear_1);
//layout is android.widget.FrameLayout{5aa6820 V.E...... ......ID 0,0-0,0 #7f070096 app:id/vs_hear_1}
Log.e(TAG, "layout is " + fl_2);
//layout is wrap_content
int height = fl_2.getLayoutParams().height;
if (height== ViewGroup.LayoutParams.WRAP_CONTENT) {
Log.e(TAG, "layout is wrap_content");
} else if (height == ViewGroup.LayoutParams.MATCH_PARENT) {
Log.e(TAG, "layout is match_parent");
} else {
Log.e(TAG, "layout is " + height);
}
}
});
}
}
结论:
(1) 当ViewStub的layout属性使用非merge标签为根标签的布局文件时能够正常加载
(2) 当ViewStub的layout属性使用merge标签为根标签的布局文件时不能正常加载,会报如下错误:
上一篇: Nginx+SmokePing 实践