Android布局優(yōu)化

本文主要記錄Android布局優(yōu)化的一些小技巧
Android中雪猪,如果一個View樹的高度太高,就會嚴重影響測量渤刃,布局和繪制的速度拥峦,因此可以使用一些方法來降低View樹的高度,提高用戶體驗

目錄

  • 避免使用過多嵌套
  • 重用布局文件<include>卖子、<merge>
  • View延時加載<ViewStub>
  • 工具HierarchyView幫助優(yōu)化布局(本文沒有介紹具體使用)

避免使用過多嵌套

先來看一個非常常見的效果

相信這樣的效果對我們來說完全不是問題略号,然而很多人會這樣寫布局

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:padding="5dp">

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@mipmap/ic_launcher" />

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginLeft="10dp"
            android:layout_weight="1"
            android:text="第一項"
            android:textSize="18sp" />

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:src="@drawable/arrows_right" />
    </LinearLayout>

    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="#cccccc" />

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:padding="5dp">

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@mipmap/ic_launcher" />

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginLeft="10dp"
            android:layout_weight="1"
            android:text="第二項"
            android:textSize="18sp" />

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:src="@drawable/arrows_right" />
    </LinearLayout>
</LinearLayout>

可以看到這里布局嵌套了多層,類似這種效果有更優(yōu)雅的寫法洋闽,效果是完全一樣的

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:divider="@drawable/spacer"
    android:orientation="vertical"
    android:showDividers="middle">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:drawableLeft="@mipmap/ic_launcher"
        android:drawablePadding="10dp"
        android:drawableRight="@drawable/arrows_right"
        android:gravity="center_vertical"
        android:padding="5dp"
        android:text="第一項"
        android:textSize="18sp" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:drawableLeft="@mipmap/ic_launcher"
        android:drawablePadding="10dp"
        android:drawableRight="@drawable/arrows_right"
        android:gravity="center_vertical"
        android:padding="5dp"
        android:text="第二項"
        android:textSize="18sp" />
</LinearLayout>

這里主要用到了LinearLayout的android:divider="@drawable/spacer"android:showDividers="middle"兩個屬性添加分割線玄柠,注意android:divider里面的參數(shù)必須是shape類型才能顯示。TextView里面則用到了android:drawableLeft="@mipmap/ic_launcher"設置文字左邊圖片诫舅,android:drawableRight="@drawable/arrows_right"同理這是文字右邊圖片羽利,android:drawablePadding="10dp"設置圖片與文字的間距。
我們可以對比一下兩個布局文件刊懈,更少的嵌套这弧,更簡潔的代碼,相信你會更喜歡第二種寫法虚汛。

重用布局文件<include>匾浪、<merge>

<include>

簡單來說<include>標簽就是為了一些通用的UI來使用的,有時候我們不想用系統(tǒng)的Toolbar卷哩,完全可以自己寫一個滿足我們的需求蛋辈,先看效果。

這里很簡單的實現(xiàn)了左邊一個圖片将谊,中間標題冷溶,右邊一個圖片,一般情況左邊是一個back按鈕瓢娜,右邊一個action按鈕挂洛,這里為了方便演示就直接用系統(tǒng)里的圖片。關鍵代碼片段如下眠砾。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:divider="@drawable/spacer"
    android:orientation="vertical"
    android:showDividers="middle">

    <RelativeLayout 
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:padding="5dp">

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@mipmap/ic_launcher" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:text="標題"
            android:textSize="18sp" />

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:src="@mipmap/ic_launcher" />
    </RelativeLayout>
    ...
</LinearLayout>

由于我們會在多個Activity使用到這個布局虏劲,你完全可以每個Activity都拷貝一份上面的代碼托酸,但我相信身為程序猿的你不會那么做,因為如果某一天需求需要改動這個布局柒巫,而你每個Activity都需要修改励堡,這時候你是崩潰的。為解決此問題我們就可以用到<include>標簽來重用此UI堡掏。
首先我們可以新建一個top_view.xml布局文件应结,代碼就是把上面<RelativeLayout>包含的整個提取出來。然后把剛剛的布局替換成<include>泉唁。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:divider="@drawable/spacer"
    android:orientation="vertical"
    android:showDividers="middle">

    <include layout="@layout/top_view" />
    ...
</LinearLayout>

使用layout="@layout/top_view"屬性將我們剛剛的布局引入即可鹅龄。非常簡便,這樣即使需要改動我們只需修改top_view.xml里面的內(nèi)容就能適用整個APP亭畜。

<merge>

簡單來說<merge>標簽可以有效的減少多余的布局嵌套扮休,這里簡單的舉個栗子。直接貼關鍵代碼

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    ...
    <include layout="@layout/ok_cancel_layouy" />
    
</LinearLayout>

ok_cancel_layouy.xml

<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:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="ok" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="cancel" />
</LinearLayout>

這時候我們看下View的層次拴鸵,拋開最外層的FrameLayout不說玷坠,先是LinearLayout接著是<include>里面的LinearLayout,最后是兩個Button劲藐,這時候內(nèi)層的LinearLayout其實是多余的八堡,我們可以使用<merge>來代替,這樣系統(tǒng)就會忽略<merge>直接放下兩個Button聘芜。
修改后的ok_cancel_layouy.xml

<merge xmlns:android="http://schemas.android.com/apk/res/android">

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="ok" />

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="cancel" />
</merge>

View延時加載<ViewStub>

上面我們知道了通過<include>可以引用通用UI兄渺,還可以使用<ViewStub>來引用并實現(xiàn)延遲加載。<ViewStub>是一個非常輕量級的控件汰现,它沒有大小溶耘,沒有繪制,也不參與布局服鹅。填寫資料的時候,有時會有更多資料填寫百新,這時候我們需要實現(xiàn)點擊更多才顯示其他資料企软,效果如下


點擊more的時候會多出兩個輸入框


布局文件如下

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:orientation="vertical"
    android:layout_height="match_parent">

    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp"
        android:hint="name" />

    <ViewStub
        android:id="@+id/view_stub"
        android:layout_width="match_parent"
        android:layout="@layout/more_layout"
        android:layout_height="wrap_content" />

    <Button
        android:id="@+id/btn_more"
        android:layout_width="wrap_content"
        android:text="more"
        android:layout_height="wrap_content" />
</LinearLayout>

more_layout.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <EditText
        android:id="@+id/et_more1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:hint="more1" />

    <EditText
        android:id="@+id/et_more2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp"
        android:hint="more2" />
</LinearLayout>

點擊more進行顯示

        btn_more = (Button) findViewById(R.id.btn_more);
        btn_more.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ViewStub viewStub = (ViewStub) findViewById(R.id.view_stub);
                1.viewStub.setVisibility(View.VISIBLE);
                if (viewStub != null) {
                    2.View inflatedView = viewStub.inflate();
                    et_more1 = (EditText) inflatedView.findViewById(R.id.et_more1);
                    et_more2 = (EditText) inflatedView.findViewById(R.id.et_more2);
                }
            }
        });

有兩種方法可以讓<ViewStub>的布局進行顯示,一種是直接設置viewStub.setVisibility(View.VISIBLE)饭望,第二種則是使用inflate來加載仗哨,如要獲取到里面控件,我們一般采用第二種方法铅辞。
從上面可以看出<ViewStub>的用法類似于<include>厌漂,不同的是<ViewStub>必須指定layout_widthlayout_height屬性,還有一點需要注意<ViewStub>所加載的布局是不可以使用<merge>標簽的斟珊。

對于Android布局優(yōu)化就寫這些苇倡,另外系統(tǒng)還提供了一個工具HierarchyView可以幫助我們更好的優(yōu)化布局,需要學習更多的可以直接閱讀官網(wǎng)的文章。(需要科學上網(wǎng))

第一次寫文章旨椒,有疑問或錯誤的歡迎指出晓褪,互相學習。

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末综慎,一起剝皮案震驚了整個濱河市涣仿,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌示惊,老刑警劉巖好港,帶你破解...
    沈念sama閱讀 211,194評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異米罚,居然都是意外死亡钧汹,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評論 2 385
  • 文/潘曉璐 我一進店門阔拳,熙熙樓的掌柜王于貴愁眉苦臉地迎上來崭孤,“玉大人,你說我怎么就攤上這事糊肠”娉瑁” “怎么了?”我有些...
    開封第一講書人閱讀 156,780評論 0 346
  • 文/不壞的土叔 我叫張陵货裹,是天一觀的道長嗤形。 經(jīng)常有香客問我,道長弧圆,這世上最難降的妖魔是什么赋兵? 我笑而不...
    開封第一講書人閱讀 56,388評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮搔预,結果婚禮上霹期,老公的妹妹穿的比我還像新娘。我一直安慰自己拯田,他們只是感情好历造,可當我...
    茶點故事閱讀 65,430評論 5 384
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著船庇,像睡著了一般吭产。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上鸭轮,一...
    開封第一講書人閱讀 49,764評論 1 290
  • 那天臣淤,我揣著相機與錄音,去河邊找鬼窃爷。 笑死邑蒋,一個胖子當著我的面吹牛姓蜂,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播寺董,決...
    沈念sama閱讀 38,907評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼覆糟,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了遮咖?” 一聲冷哼從身側響起滩字,我...
    開封第一講書人閱讀 37,679評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎御吞,沒想到半個月后麦箍,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,122評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡陶珠,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,459評論 2 325
  • 正文 我和宋清朗相戀三年挟裂,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片揍诽。...
    茶點故事閱讀 38,605評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡诀蓉,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出暑脆,到底是詐尸還是另有隱情渠啤,我是刑警寧澤,帶...
    沈念sama閱讀 34,270評論 4 329
  • 正文 年R本政府宣布添吗,位于F島的核電站沥曹,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏碟联。R本人自食惡果不足惜妓美,卻給世界環(huán)境...
    茶點故事閱讀 39,867評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望鲤孵。 院中可真熱鬧壶栋,春花似錦、人聲如沸普监。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽鹰椒。三九已至,卻和暖如春呕童,著一層夾襖步出監(jiān)牢的瞬間漆际,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評論 1 265
  • 我被黑心中介騙來泰國打工夺饲, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留奸汇,地道東北人施符。 一個月前我還...
    沈念sama閱讀 46,297評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像擂找,于是被迫代替她去往敵國和親戳吝。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,472評論 2 348

推薦閱讀更多精彩內(nèi)容