android textview 文字居中_Android布局优化,看这3点就够了
碼個蛋(codeegg)第 712 次推文
作者:Android技術
博客:https://www.jianshu.com/p/2ee61b88175e
前言
在編寫Android布局時總會遇到這樣或者那樣的痛點,比如:
有些布局的在很多頁面都用到了,而且樣式都一樣,每次用到都要復制粘貼一大段,有沒有辦法可以復用呢?
解決了1中的問題之后,發現復用的布局外面總要額外套上一層布局,要知道布局嵌套是會影響性能的吶;
有些布局只有用到時才會顯示,但是必須提前寫好,雖然設置了為invisible或gone,還是多多少少會占用內存的。
要解決這些痛點,我們可以請Android布局優化三劍客出碼,它們分別是include、merge和ViewStub三個標簽,現在我們就來認識認識它們吧。在此之前,我們先來看看我們本次項目的界面效果:
界面不復雜,我們來逐個實現吧。
include
include的中文意思是“包含”、“包括”,當你在一個主頁面里使用include標簽時,就表示當前的主布局包含標簽中的布局,這樣一來,就能很好地起到復用布局的效果了。在那些常用的布局比如標題欄和分割線等上面用上它可以極大地減少代碼量的。它有兩個主要的屬性:
layout:必填屬性,為你需要插入當前主布局的布局名稱,通過R.layout.xx的方式引用;
id:當你想給通過include添加進來的布局設置一個id的時候就可以使用這個屬性,它可以重寫插入主布局的布局id。
下面我們就來實戰一番。
我們先創建一個ViewOptimizationActivity,然后再創建一個layout_include.xml布局文件,它的內容非常簡單,就一個TextView:
<?xml version="1.0" encoding="utf-8"?>.com/apk/res/android"
android:layout_width="match_parent"
android:gravity="center_vertical"
android:textSize="14sp"
android:background="@android:color/holo_red_light"
android:layout_height="40dp">
現在我們就用include標簽,將其添加到ViewOptimizationActivity的布局中:
<?xml version="1.0" encoding="utf-8"?>.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=".ViewOptimizationActivity">android:textSize="18sp"
android:text="1、include標簽的使用"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />android:id="@+id/tv_include1"
layout="@layout/layout_include"/>
沒錯,include的使用就是這么簡單,只需指明要包含的布局id就行。除此之外,我們還給這個include標簽設置了一個id,為了驗證它就是layout_include.xml的根布局TextView的id,我們在ViewOptimizationActivity中初始化TextView,并給它設置文字:
TextView tvInclude1 = findViewById(R.id.tv_include1);tvInclude1.setText("1.1 常規下的include布局");
運行之后可以可以看到如下布局:
說明我們設置的layout和id都是成功的。不過你可能會對id這個屬性有疑問:id我可以直接在TextView中設置啊,為什么重寫它呢?別忘了我們的目的是復用,當你在一個主布局中使用include標簽添加兩個以上的相同布局時,id相同就會沖突了,所以重寫它可以讓我們更好地調用它和它里面的控件。還有一種情況,假如你的主布局是RelateLayout,這時為了設置相對位置,你也需要給它們設置不同的id。
重寫根布局的布局屬性
除了id之外,我們還可以重寫寬高、邊距和可見性(visibility)這些布局屬性。但是一定要注意,單單重寫android:layout_height或者android:layout_width是不行,必須兩個同時重寫才起作用。包括邊距也是這樣,如果我們想給一個include進來的布局添加右邊距的話的完整寫法是這樣的:
android:layout_width="match_parent"android:layout_height="40dp"
android:layout_marginEnd="40dp"
android:id="@+id/tv_include2"
layout="@layout/layout_include"/>
初始化后設置一段文字就可以看到如下的效果了:
可以看到,1.2顯然比1.1多了一個右邊距。
控件ID相同時的處理
在1.1中我們知道了id屬性可以重寫include布局的根布局id,但對于根布局里面的布局和控件是無能為力的,如果這時一個布局在主布局中include了多次,那怎么區別里面的控件呢?
我們先創建一個layout_include2.xml的布局,它的根布局是FrameLayout,里面有一個TextView,它的id是tv_same:
<?xml version="1.0" encoding="utf-8"?>.com/apk/res/android"
android:layout_width="match_parent"
android:background="@android:color/holo_orange_light"
android:layout_height="wrap_content">android:gravity="center_vertical"
android:id="@+id/tv_same"
android:layout_width="match_parent"
android:layout_height="50dp" />
在主布局中添加進去:
<?xml version="1.0" encoding="utf-8"?>.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=".ViewOptimizationActivity">
……android:id="@+id/view_same"
layout="@layout/layout_include2"/>
為了區分,這里給第二個layout_include2設置了id。也許你已經反應過來了,沒錯,我們就是要創建根布局的對象,然后再去初始化里面的控件:
TextView tvSame = findViewById(R.id.tv_same);tvSame.setText("1.3 這里的TextView的ID是tv_same");
FrameLayout viewSame = findViewById(R.id.view_same);
TextView tvSame2 = viewSame.findViewById(R.id.tv_same);
tvSame2.setText("1.3 這里的TextView的ID也是tv_same");
運行之后可以看到這樣的效果:
可見雖然控件的id雖然相同,但是使用起來是沒有沖突的。
merge
include標簽雖然解決了布局重用的問題,卻也帶來了另外一個問題:布局嵌套。因為把需要重用的布局放到一個子布局之后就必須加一個根布局,如果你的主布局的根布局和你需要include的根布局都是一樣的(比如都是LinearLayout),那么就相當于在中間多加了一層多余的布局了。那么有沒有辦法可以在使用include時不增加布局層級呢?答案當然是有的,那就是使用merge標簽。
使用merge標簽要注意一點:必須是一個布局文件中的根節點,看起來跟其他布局沒什么區別,但它的特別之處在于頁面加載時它的不會繪制的。打個比方,它就像是布局或者控件的搬運工,把“貨物”搬到主布局之后就會功成身退,不會占用任何空間,因此也就不會增加布局層級了。這正如它的名字一樣,只起“合并”作用。
merge常規使用
我們來驗證一下,首先創建一個layout_merge.xml,在根節點使用merge標簽:
<?xml version="1.0" encoding="utf-8"?>.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">android:id="@+id/tv_merge1"
android:text="我是merge中的TextView1"
android:background="@android:color/holo_green_light"
android:gravity="center"
android:layout_width="wrap_content"
android:layout_height="40dp" />android:layout_toEndOf="@+id/tv_merge1"
android:id="@+id/tv_merge2"
android:text="我是merge中的TextView2"
android:background="@android:color/holo_blue_light"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="40dp" />
這里我使用了一些相對布局的屬性,原因后面你就知道了。我們接著在ViewOptimizationActivity的布局添加RelativeLayout,然后使用include標簽將layout_merge.xml添加進去:
android:layout_width="match_parent"android:layout_height="wrap_content">android:id="@+id/view_merge"
layout="@layout/layout_merge"/>
運行出來的效果圖:
merge標簽對布局層級的影響
在layout_merge.xml中,我們使用相對布局的屬性android:layout_toEndOf將藍色TextView設置到了綠色TextView的右邊,而layout_merge.xml的父布局是RelativeLayout,所以這個屬性是起了作用了,merge標簽不會影響里面的控件,也不會增加布局層級。
如果你還不放心,可以用Android Studio來檢查。我用的Android Studio是3.1版本的,可以通過Layout Inspector查看布局層級,不過記得要先在真機或者模擬器上把項目跑起來。依次點擊Tools-Layout Inspector,然后選擇你要查看的Activity,就可以看到如下的層級圖:
可以看到RelativeLayout下面直接就是兩個TextView了,merge標簽并沒有增加布局層級。從這里也可以看出merge的局限性,即你需要明確將merge里面的布局和控件include到什么類型的布局中,才能提前設置好merge里面的布局和控件的位置。
merge的ID
在學習include標簽時我們知道,它的android:id屬性可以重寫被include的根布局id,但如果根節點是merge呢?前面說了merge并不會作為一個布局繪制出來,所以這里給它設置id是不起作用的。我們可以在它的父布局RelativeLayout中再加一個TextView,使用android:layout_below屬性把設置到layout_merge下面:
android:layout_width="match_parent"android:layout_height="wrap_content">android:id="@+id/view_merge"
layout="@layout/layout_merge"/>android:text="我不是merge中的布局"
android:layout_below="@+id/view_merge"
android:background="@android:color/holo_purple"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="40dp"/>
運行之后你會發現新加的TextView會把merge布局蓋住,沒有像預期那樣在其下方。如果把android:layout_below中的id改為layout_merge.xml中任一TextView的id(比如tv_merge1),運行之后就可以看到如下效果:
這也符合2.2中的情況,即父布局RelativeLayout下級布局就是include進去的TextView了。
ViewStub
你一定遇到這樣的情況:頁面中有些布局在初始化時沒必要顯示,但是又不得不事先在布局文件中寫好,雖然設置成了invisible或gone,但是在初始化時還是會加載,這無疑會影響頁面加載速度。針對這一情況,Android為我們提供了一個利器————ViewStub。這是一個不可見的,大小為0的視圖,具有懶加載的功能,它存在于視圖層級中,但只會在setVisibility和inflate方法調用只會才會填充視圖,所以不會影響初始化加載速度。它有以下三個重要屬性:
android:layout:ViewStub需要填充的視圖名稱,為“R.layout.xx”的形式;
android:inflateId:重寫被填充的視圖的父布局id。
與include標簽不同,ViewStub的android:id屬性是設置ViewStub本身id的,而不是重寫布局id,這一點可不要搞錯了。另外,ViewStub還提供了OnInflateListener接口,用于監聽布局是否已經加載了。
我們先創建一個layout_view_stub.xml,里面放置一個Switch開關:
android:layout_width="match_parent"android:layout_height="wrap_content">android:id="@+id/view_merge"
layout="@layout/layout_merge"/>android:text="我不是merge中的布局"
android:layout_below="@+id/view_merge"
android:background="@android:color/holo_purple"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="40dp"/>
然后在Activity的布局中修改如下:
<?xml version="1.0" encoding="utf-8"?>.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=".ViewOptimizationActivity">android:textSize="18sp"
android:text="3、ViewStub標簽的使用"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />android:id="@+id/view_stub"
android:inflatedId="@+id/view_inflate"
android:layout="@layout/layout_view_stub"
android:layout_width="match_parent"
android:layout_height="100dp" />android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">android:text="顯示"
android:id="@+id/btn_show"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="wrap_content" />android:text="隱藏"
android:id="@+id/btn_hide"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="wrap_content" />android:text="操作父布局控件"
android:id="@+id/btn_control"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
在ViewOptimizationActivity中監聽ViewStub的填充事件:
viewStub.setOnInflateListener(new ViewStub.OnInflateListener {@Override
public void onInflate(ViewStub viewStub, View view) {
Toast.makeText(ViewOptimizationActivity.this, "ViewStub加載了
總結
以上是生活随笔為你收集整理的android textview 文字居中_Android布局优化,看这3点就够了的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: javascript createele
- 下一篇: android sina oauth2.