Android LinearLayout線性布局詳解


  為了更好地管理Android應用的用戶界面里的各組件,Android提供了布局管理器。通過使用布局管理器,Android應用圖形用戶界面具有良好的平台無關性。推薦使用布局管理器來管理組件的分布、大小,而不是直接設置組件的位置和大小。可以使用布局管理器嵌套布局管理器,即也可作為一個UI組件來使用。

  LinearLayout可以控制組件橫向排列或者縱向排列,內容不會換行,超出屏幕部分將不會顯示出來。

 

學習圖解

 

LinearLayout 常用XML屬性及方法

【屬性一】orientation 設置子組件的排列方式(單選)

  XML: android:orientation="horizontal"

  

     horizontal:橫向排列

     vertical:縱向排列

   JAVA :linearLayout.setOrientation(LinearLayout.VERTICAL); 

      LinearLayout.HORIZONTAL 橫向排列

  

    LinearLayout.VERTICAL 縱向排列 

  

 

【屬性二】gravity 設置子組件的對齊方式(多選

   XML: android:gravity="center"

   

   JAVA :linearLayout.setGravity(Gravity.CENTER);

  

 

【屬性三】baselineAligned 設置子元素基准線對棄,默認為true

  基准線:

    打開的英語練習本,那條紅線就是基准線  

    

    

   XML: android:baselineAligned="false"  

  

   JAVA: linearLayout.setBaselineAligned(true);

代碼:true
    <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:baselineAligned="true" android:orientation="horizontal">

        <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@android:color/holo_red_light" android:padding="20dp" android:text="text1" android:textSize="30sp">

        </TextView>
        <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@android:color/holo_blue_light" android:padding="10dp" android:text="text2" android:textSize="16sp">

        </TextView>
    </LinearLayout>
  效果:

   

   

 

【搭配屬性三】baselineAlignedChildIndex LinearLayout的基准線以他的第幾個子元素為准,下標從0開始

  一個LinearLayout 里面有很多 textview ,每一個 textview 都有自己的基准線,那么LinearLayout可能也是另一個LinearLayout的子元素,作為子元素 baselineAlignedChildIndex 就決定這他的一個基准線

  XML:android:baselineAlignedChildIndex="0"
  JAVA:linearLayout.setBaselineAlignedChildIndex(0);
  代碼:⭐注意內部的LinearLayout,后面將在 第二個LinearLayout上添加 baselineAlignedChildIndex ,搭配  baselineAligned="false" 使用
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal">

    <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:baselineAligned="false" android:orientation="horizontal">

  
        <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@android:color/holo_blue_light" android:text="這是text2" android:textSize="20sp">

        </TextView>
        <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@android:color/holo_red_light" android:text="這是text1" android:textSize="30sp">

        </TextView>
        <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@android:color/holo_green_dark" android:text="這是text2" android:textSize="15sp">

        </TextView>
    </LinearLayout>
    <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="這是text4" android:textSize="25sp" android:background="@android:color/holo_orange_light"
        >

    </TextView>
    <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@android:color/black" android:text="text" android:textColor="@android:color/white" android:textSize="15sp">

   </TextView>
</LinearLayout>
  效果:
  

   

   

   

  ⭐ 總結

  • 默認LinearLayout是沒有基准線的,從圖一和圖三的對比可知。
  • 下標從0開始三個子組件,最大index為2,超過2時布局將不顯示
  • 這個屬性是用來決定當前LinearLayout的基准線時以哪個子組件為准的

 

  👂思考1:如果搭配 baselineAligned="true" 是什么樣的效果?

  代碼:(修改上方代碼)  

    

   效果:

  

   

   

   

   ⭐總結

  好像已經把上方的總結都打亂了,但是對比 baselineAligned="false" 的效果,可以發現,其實LinearLayout 的基准線其實還是在  baselineAligned="false" 時對應子組件的基准線位置為准的,可以參考 text4 和text5 的位置,他們所對棄的基准線,不是 前三個 text 變化后位置的基准線,而是變化之前的基准線位置。

 

  👂思考2:基准線時平行的,如果設置 LinearLayout 子組件為縱向排列那還有效果嗎?

 答:沒有效果沒有變化

  

 

 【屬性四】divider 分割線

  我第一次遇到這個divider 是在 ListView 中

  😳代碼

<ListView android:layout_width="match_parent" android:layout_height="match_parent" android:divider="@color/colorPrimary" android:dividerHeight="3dp">        
</ListView>

  🍎效果

  

   ⭐注意這里  divider 必須和 dividerHeight 才能顯示出效果。於是憑借經驗,你以為在LinearLayout也能如此,那就入坑了

 

  XML: android:divider="@mipmap/ic_launcher"  

  🐖必須使用圖片或者是shape文件,不能直接和ListView一樣直接使用顏色(會導致沒效果)

  🐖需要搭配 showDividers 使用才有效果

 

  JAVA: linearLayout.setDividerDrawable(getResources().getDrawable(R.mipmap.ic_launcher));

 

【關鍵屬性四】 showDividers 分割線顯示的位置(可多選)

  

  XML: android:showDividers="middle|beginning"

  JAVA:linearLayout.setShowDividers(LinearLayout.SHOW_DIVIDER_MIDDLE);

  😳關鍵代碼 :

 <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:divider="@mipmap/ic_launcher" android:showDividers="middle|beginning" android:orientation="horizontal"> <···/> </LinearLayout>

  🍎效果:

  

 

使用shape 分割

  創建 linear_line.xml

  

   將  selector 修改成shape,如下

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">

    <size android:width="5dp" android:width="5dp"/> <solid android:color="@android:color/holo_purple" /> </shape>

  🐖這里要使用 size 來定義 線的一個寬度 width 作為橫向的分割線,如果是縱向的就要定義一個 高度 height

 android:divider="@drawable/linear_line"
        android:showDividers="middle|beginning"

   🍎效果:三種可以相互組合

   

   

   

 

 【搭配屬性四】dividerPadding 分割線的padding 

  XML: android:dividerPadding="10dp"

  JAVA:linearLayout.setDividerPadding(10);

   😳代碼:

<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:divider="@drawable/linear_line" android:showDividers="middle" android:dividerPadding="10dp" android:orientation="horizontal">
</LinearLayout>

  🍎效果:

  

  

 ⭐總結

  • 默認分割線的高度或寬度是和LinearLayout 布局管理器大小一致
  • 如果是橫向布局,shape 中設置的 height 對顯示沒有影響
  • 可以發現如果是橫向排列只影響縱向的padding,縱向則影響橫向的padding

 

LinearLayout 子組件的特殊屬性

 所有子組件都受 LinearLayout.LayoutParams 控制

【屬性一】 layout_gravity 設置自身在布局管理器中的位置

   🐖上方講解到了gravity,其gravity不是LinearLayout 的特有屬性,但layout_gravity 是其子組件的特殊屬性。具體區別請參考我的博客 layout_gravity和gravity的區別:https://www.cnblogs.com/xqz0618/p/gravity.html,這里不再詳細說明

 

 

【屬性二】layout_weight 權重 💗(重要屬性)

  這是LinearLayout 及其重要的一個屬性,根據權重來設置子組件的在整個屏幕的占比,能夠達到很好的適配屏幕的效果

 代碼:

<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:divider="@drawable/linear_line" android:baselineAligned="false">

        <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:background="@android:color/holo_blue_light" android:text="text1" android:textSize="20sp">

        </TextView>
        <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="2" android:background="@android:color/holo_red_light" android:text="text2" android:textSize="30sp">

        </TextView>
        <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="3" android:background="@android:color/holo_green_dark" android:text="text3" android:textSize="15sp">

        </TextView>      
    </LinearLayout>

  🐖這里是橫向布局,將對 layout_width 進行修改得到不同的結果

情況一:將 layout_width 全部設置成 0dp,權重分別是1:2:3,設置0dp后必須使用權重才不報錯

 

   ⭐可以看出來 三個text 的寬度在誤差范圍內是和weight權重相同的 1:2:3,所以單個text 的寬度計算就為:

假設屏幕的寬度為P,單個子組件的大小為W,子組件的權重之和為G,該組件設置的權重為H
則 W = H/G*P
即當前 1:2:3
W = H/G*P = 1/(1+2+3)*P = 1/6P
text1占比為屏幕的 1/6

 

 情況二:將 layout_width 全部設置成 wrapcontent

  

   🐖情況二並沒有像情況一一樣,根據權重的比例 1:2:3,按照情況1的公式就不成立

  ⭐實際上權重是根據總屏幕的大小 P減去所有子組件的 layout_width 然后再根據權重進行分配的大小再加上 layout_width。這里說有點亂了,看分析。

   

   🔒用控件的大小減去文本的大小得到的寬度,考慮誤差范圍內,其實是 1:2:3的

假設屏幕的寬度為P,單個子組件的大小為W,子組件的權重之和為G,該組件設置的權重為H,子組件的layout_width為L
則 W = H/G*(P-3L)+L
即當前 1:2:3
text1的屏幕占比 W =H/G*(P-3L)+L = 1/(1+2+3)*(P-3L)+L
這里使用 wrap_content不好計算
反過來思考 當 L=0dp 時
W = 1/(1+2+3)*(P-0)+0= 1/6P
與上方結果一致

 

情況三:將 layout_width 全部設置成 match_parent

  

   從上圖可以看出 text1和text2 比例分別為 2:1,text3不見了,用上方的式子驗證:

假設屏幕的寬度為P,單個子組件的大小為W,子組件的權重之和為G,該組件設置的權重為H,子組件的layout_width為L
則 W = H/G*(P-3L)+L
即當前 1:2:3
由於此時 layout_width是match_parent,則 L= P
text1的屏幕占比 W =H/G*(P-3L)+L = 1/(1+2+3)*(P-3L)+L=1/(1+2+3)*(P-3P)+P = 1/6*(-2P)+P= 2/3P
由此
text2的 W = 1/3P
text3的 W = 3/(1+2+3)*(-2P)+P = 0dp
那也就是說text3並不是超出屏幕沒顯示,而是他的寬度就是為0 //可以添加一個滾動控件來驗證一下

⭐總結

  我們得到的統一公式,來計算這個屏幕占比問題(其實話說回來,你整這么麻煩干嘛,直接使用0dp不爽嗎,當然一些場景可能需要 warpcontent)

假設屏幕的寬度為P,單個子組件的大小為W,子組件的權重之和為G,該組件設置的權重為H,子組件的layout_width為L
則 W = H/G*(P-3L)+L
 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM