我们通常编写Android布局的时候会遇到许多布局上面的问题,比如:同一布局在很多地方使用,编写了很多重复的布局代码;页面太复杂造成的布局嵌套;有些布局一开始不显示,有条件时候才会显示,但又得提前写好。 这些问题都多少在一定程度上占用内存,影响性能。所以下面的布局三剑客()正是解决这些问题的方法:
一、标签,解决布局复用
1、解释
标签,主要解决布局页面太复杂,代码太多的问题。 使用表示当前主布局包含标签中的布局,把一些常用的布局比如标题栏部分独立出来,再在需要的地方通过R.layout.XX引用。
2、使用例子:
创建一个layout_include.xml布局文件,只放一个TextView
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:background="@android:color/holo_orange_light"
android:layout_height="wrap_content">
<TextView
android:gravity="center_vertical"
android:id="@+id/inlcude_textview"
android:layout_width="match_parent"
android:layout_height="50dp" />
</FrameLayout>
然后想引用的activity中使用 可以设置id属性重写引入主布局的布局id
<?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:orientation="vertical"
tools:context=".MainActivity">
<!--include标签引用布局-->
<include
android:id="@+id/include_layout"
layout="@layout/layout_include"/>
</LinearLayout>
布局是这样引入,初始化控件的时候这么做,可以先创建根布局的对象,然后再初始化里面的控件:
FrameLayout include_layout = findViewById(R.id.include_layout);
TextView include_textview = viewSame.findViewById(R.id.include_textview);
include_textview.setText("这就是include标签引入布局里面的textview");
3、重写根布局的布局属性
(如果要使用 标记来替换布局属性,您必须同时替换 android:layout_height 和 android:layout_width 才能让其他布局属性生效。)
除了重写id之外,我们还可以重写宽高、边距和可见性(visibility)这些布局属性。但是一定要注意,单单重写android:layout_height或者android:layout_width是不行,必须两个同时重写才起作用。包括边距也是这样,如果我们想给一个include进来的布局添加右边距的话的完整写法是这样的:
<include
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_marginEnd="40dp"
android:id="@+id/include_layout"
layout="@layout/layout_include"/>
二、标签,减少层级
1、解释
标签虽然解决了布局重用的问题,但一个布局中使用太多的话就会带来布局嵌套的问题,例如主布局的根布局和的根布局都是LinearLayout,这样中间就多了一个层级,解决这种问题的办法就是使用标签。
标签有一个很重要的特点就是它在页面加载时候不需要绘制,等于说它把布局中的控件等搬过来就走了,不会占用内存空间,因此也就不会增加布局层级了,所以给它设置id也是不起作用的。
2、使用例子
创建layout_merge.xml布局文件,根节点使用merge标签
<?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">
<TextView
android:id="@+id/merge1"
android:text="我是merge中的TextView1"
android:background="@android:color/holo_green_light"
android:gravity="center"
android:layout_width="wrap_content"
android:layout_height="40dp" />
<TextView
android:layout_toEndOf="@+id/tv_merge1"
android:id="@+id/merge2"
android:text="我是merge中的TextView2"
android:background="@android:color/holo_blue_light"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="40dp" />
</merge>
在MainActivity中引入,顺便在引入布局下面另加入一个textview
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<include
android:id="@+id/include_merge"
layout="@layout/layout_merge"/>
<TextView
android:text="我不是merge中的布局"
android:layout_below="@+id/merge1"
android:background="@android:color/holo_purple"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="40dp"/>
</RelativeLayout>
运行之后你会发现MainActivity中新加的textview就在引入布局的下面,在设置android:layout_below属性时候需要把id设置为引入布局中任意控件的id而不是@=id/include_merge这个id,这个id等于说是merge布局的id,但是由于merge引用的布局是不绘制的,所以id也是不起作用的,如果使用了这个,merge引用布局的部分就相当于不存在,MainActivity中下面的布局就会覆盖这个引入布局。
三、标签,提高显示速度
1、解释
页面中有些布局在初始化时没必要显示,但是又不得不事先在布局文件中写好,虽然设置成了invisible或gone,但是在初始化时还是会加载,这在一定程度上会影响页面加载速度。 这时就可以使用ViewStub了,这是一个不可见的、大小为0的视图,具有懒加载的功能,存在于视图层级中,不会影响页面初始化加载速度。
如果要加载 ViewStub 指定的布局,可通过调用 setVisibility(View.VISIBLE) 将其设置为可见,或调用 inflate()。 只能inflate一次,用完以后就会置为空,后期不能再次使用,重新开启应用或者杀死进程可再次使用。类似显示隐藏按钮这种功能是不能实现的。
2、使用例子
可参考 Android官方文档之视图加载延迟
|