布局技巧
在Android開發(fā)過程中蔗蹋,我們會遇到很多的問題,隨著UI界面越來越多毯盈,布局的重復(fù)性、復(fù)雜度也隨之增加病袄,所幸的是搂赋,Android官方也給出了幾個對布局進(jìn)行優(yōu)化的方法,下面根據(jù)自己的理解對官方所介紹的方法進(jìn)行分享陪拘,有錯誤的地方希望大家進(jìn)行留言厂镇,相互交流。
輕量布局之ViewStub標(biāo)簽分析
ViewStub是一個輕量級View左刽,也是一個初始化不做任何事情的View,但是之后我們可以加載入一個布局文件酌媒,在慢加載時View中做占位符而已欠痴。比如我們根據(jù)條件在動態(tài)加載View或者某個布局時,最通常就是把可能用到的View都寫在布局上秒咨,然后可見性都設(shè)置為View.GONE 喇辽。之后在代碼中動態(tài)更改其可見性,雖然操作簡單雨席,但是耗費(fèi)資源菩咨,因?yàn)閂iew.GONE在inflate布局仍會inflate,仍會創(chuàng)建對象,會被實(shí)例化抽米,會被設(shè)置屬性特占。而我推薦做法是用android.view.ViewStub,它指定一個布局時會被inflate和實(shí)例化云茸,但是不占布局位置是目,占用資源少。當(dāng)ViewStub所指向的布局被設(shè)置為可見标捺,或者是調(diào)用了ViewStub.inflate()時懊纳,ViewStub所在的布局才會進(jìn)行inflate之后實(shí)例化,然后ViewStub的布局屬性傳給它所指定的布局亡容。當(dāng)然嗤疯,ViewStub的使用還是有缺點(diǎn)的,并不是任何時候都可以用闺兢。
ViewStub使用限制:
- ViewStub只能被inflate一次身弊,之后ViewStub對象就會被置為空,就從view層次上移除了列敲,也就是說它所指定的布局被inflate之后阱佛,就不能再通過ViewStub去控制這個布局了;
- ViewStub只能用來inflate一個布局文件戴而,而不能是某一個具體的View凑术,這時我們要做的是可以將View寫在一個布局中;
- ViewStub目前還不支持<merge/>標(biāo)簽所意。
考慮到以上ViewStub的特點(diǎn)淮逊,再結(jié)合我自身的開發(fā)過程中,可以考慮到使用的ViewStub時主要有以下的情形:
- 當(dāng)需要在運(yùn)行時不止一次的顯示和隱藏某一個布局時扶踊,ViewStub不可用泄鹏,因?yàn)樗荒軌騣nflate一次,之后就會被置為空秧耗。這時只能采用View的可見性來控制了备籽。
- 想要控制的是一個布局文件,而非View分井,ViewStub指定的是一個布局id车猬,而非一個View對象。
當(dāng)在使用ViewStub的布局屬性時尺锚,某些屬性是加在ViewStub上面珠闰,而不是加在實(shí)際的布局上面,這樣才會起作用瘫辩。而ViewStub的屬性在inflate之后會都傳給相應(yīng)的布局伏嗜。其中有個屬性android:inflatedId 指是的可以使用它來重寫包含布局文件的根元素的id坛悉。而在ViewStub上設(shè)定的layout_* 參數(shù)將會應(yīng)用到包含的布局文件的頂部。
重用布局之Include標(biāo)簽分析
我們在做項(xiàng)目過程中承绸,用得最多的標(biāo)簽應(yīng)該是include裸影,它是為了解決重復(fù)定義相同布局的問題。例如你有五個界面八酒,這五個界面頂部都有一個相同的一個返回按妞和一個文本控件空民,若在不使用include情況下你在每個界面都需要重新在xml里面寫相同的布局,這樣造成工作量重復(fù)羞迷。而當(dāng)我們使用了include標(biāo)簽界轩,就可以把多次使用的這個布局獨(dú)立成一個xml文件,之后在需要的地方通過include標(biāo)簽進(jìn)行引用衔瓮,自己不用再重復(fù)寫一遍浊猾。示例如下:
my_title_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:id="@+id/my_title_parent_id"
android:layout_height="wrap_content" >
<ImageButton
android:id="@+id/back_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher" />
<TextView
android:id="@+id/title_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="20dp"
android:layout_toRightOf="@+id/back_btn"
android:gravity="center"
android:text="我的title"
android:textSize="18sp" />
</RelativeLayout>
而在include布局文件中進(jìn)行設(shè)置:
<?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
android:id="@+id/my_title_ly"
android:layout_width="match_parent"
android:layout_height="wrap_content"
layout="@layout/my_title_layout" />
<!-- 代碼省略 -->
</LinearLayout>
注意事項(xiàng)
- 使用include最常見是找不到findViewById查找不到目標(biāo)控件,應(yīng)通過include的id來獲取目標(biāo)布 局中子控件,當(dāng)include指定了id热鞍,而你的layout也指定了id葫慎,則你的layout中的id會被覆蓋。這里來說薇宠,具體使用的id應(yīng)該是my_title_ly,而不應(yīng)該是原先的my_title_parent_id
- 其次偷办,在include標(biāo)簽中所有的android:layout_*都是有效的,但前提是必須要寫layout_width和layout_height兩個屬性
- 布局中可以包含兩個相同的include標(biāo)簽澄港,引用時可以使用不同的include的id進(jìn)行查找即可
減少布局層級之merge標(biāo)簽分析
merge標(biāo)簽可以刪除多余的層級椒涯,優(yōu)化UI。其多用于替換FrameLayout或者當(dāng)一個布局包含另一個時回梧,它主要消除視圖層次結(jié)構(gòu)中多余的視圖組废岂。主要使用在當(dāng)一個子視圖不需要指定任何針對父視圖的布局屬性時,例如你的主布局文件是垂直布局狱意,引入了一個垂直布局的include并且引入的布局沒有針對父視圖屬性時湖苞,這時如果include布局使用的LinearLayout就會沒有意義,使用的話會重復(fù)有兩個LinearLayout布局详囤,這樣的話會增多無必要的UI層次的布局财骨,這時就可以用<merge>標(biāo)簽進(jìn)行優(yōu)化成一個LinearLayout
注意事項(xiàng)
- 其標(biāo)簽只可用作xml中l(wèi)ayout布局文件的根節(jié)點(diǎn),如果擴(kuò)充的layout布局本身是由merge作為根節(jié)點(diǎn)的話纬纪,則在代碼中需要將被導(dǎo)入的layout布局文件置于ViewGroup中蚓再,同時需要設(shè)置attachToRoot為True
總結(jié)
布局優(yōu)化的分享到此就結(jié)束了,在Android開發(fā)的過程中包各,只要我們多使用這些布局標(biāo)簽,會使得我們的布局看起來更加的專業(yè)靶庙。有問題的朋友可以留言一起探討问畅。