布局优化主要分为三部分,代码优化、绘制层级优化与动态加载View,分别对应着include、merge、ViewStib
1 include
include 标签主要用来实现代码复用,当布局文件太复杂或者存在某些布局文件可以复用的时候就可以使用include
例如编写一个个人信息页面如下
1.jpg
对应的着布局文件activity_main。
<?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"
>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="25sp"
android:background="@color/colorAccent"
android:text="姓名"/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="25sp"
android:layout_marginTop="10dp"
android:background="@color/colorAccent"
android:text="电话"/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="25sp"
android:layout_marginTop="10dp"
android:background="@color/colorAccent"
android:text="邮箱"/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
当我们发现其他页面也会用到类似的布局时候就可以将这部分布局单独定义在另一个xml布局文件中,然后在需要引入这类布局的地方调用include标签。
首先将这部分布局提取到 info_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">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="25sp"
android:background="@color/colorAccent"
android:text="姓名"/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="25sp"
android:layout_marginTop="10dp"
android:background="@color/colorAccent"
android:text="电话"/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="25sp"
android:layout_marginTop="10dp"
android:background="@color/colorAccent"
android:text="邮箱"/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
之后再activity_main.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"
>
<include
layout="@layout/info" />
</LinearLayout>
运行后得到同样的界面
1.jpg
2 merge
使用include引入布局存在一个弊端,就是会引入一层布局嵌套,由于我们在定义info.xml布局文件时候,将所有的控件放到了LinearLayout中,之后在activity_main布局文件的LinearLayout中将info布局作为一个子View引入,因此info.xml文件中的LinearLayout是一个多余的View层,为了避免引入这层嵌套就可以使用merge来代替LinearLayout,修改info.xml布局文件
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="25sp"
android:background="@color/colorAccent"
android:text="姓名"/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="25sp"
android:layout_marginTop="10dp"
android:background="@color/colorAccent"
android:text="电话"/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textSize="25sp"
android:layout_marginTop="10dp"
android:background="@color/colorAccent"
android:text="邮箱"/>
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</merge>
在运行程序,会得到通样的界面,但是merge中的这些View就被作为activity.xml文件中的LinearLayout内部的子View引入,避免了一层布局嵌套。
3 ViewStub
ViewStub是一个继承自View的控件,当使用布局加载器加载一套xml布局的时候就会创建对应View标签的实例对象(如TextView,Button),ViewStub是一个没有大小,没有绘制功能,资源消耗很少的View,它可以与一套布局文件形成对应关系,当程序最初运行时候首先加载ViewStub,当用到ViewStub对应布局时再去加载这套布局,这就增加了很多的灵活性,并且可以延迟加载一些不必要的控件。
这里使用ViewStub来对应info.xml的这套布局。
activity_main.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"
>
<Button
android:id="@+id/load_view_stub"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="显示ViewStub布局"
android:textSize="25sp"/>
<ViewStub
android:id="@+id/view_stub"
android:layout="@layout/info"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
ViewStub的layout标签就是对应的布局,注意这里的info.xml不能使用merge标签。因此加载的布局会引入一层布局嵌套。
这里添加一个按钮来控制ViewStub显示info布局。为Button添加点击事件,获取到ViewStub对象,然后调用inflate()将info的布局显示出来。
public class MainActivity extends AppCompatActivity {
Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button=findViewById(R.id.load_view_stub);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ViewStub stub=findViewById(R.id.view_stub);
stub.inflate();
}
});
}
}
程序运行后如图,这里没有显示info布局
2.jpg
点击显示ViewStub按钮后显示info布局。
3.jpg
网友评论