為了更好地管理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
