android-基礎知識-佈局
一.七大布局
七大布局分別爲:線性佈局(LInearLayout)、相對佈局(RelativeLayout)、幀佈局(FrameLayout)、表格佈局(TableLayout)、絕對佈局(absoluteLayout)、網格佈局(GridLayout)、約束佈局(ConstraintLayout)
1.相似屬性之間的區別:
- gravity的 start 和left的區別:
left是絕對的左邊,start會根據不同的國家習慣改變。
比如在從右向左順序閱讀的國家,start代表的就是在右邊 - fill_parent 和 match_parent:
Android2.2中match_parent和fill_parent是一個意思兩個參數意思一樣,match_parent更貼切,於是從2.2開始兩個詞都可以用。那麼如果考慮低版本的使用情況你就需要用fill_parent了
1.LinearLayout:
1.weight 屬性分析
- 整體思路:
- 0dp 按整體1 計算比例 如weight分別爲1、2、3。那麼實際比例爲1、2、3
- wrap_content :先wrap_content 分配大小,然後剩餘比例分配,注意:wrap_content 最大佔1
- march_parent: 按佔1分配
- 實例分析:
(1). LinearLayout 三個佈局依次爲全爲 match_parent weight 1、2、3。結果爲2:1:0。
原因:
- step 1:個個都是fill_parent,但是屏幕只有一個啦,那麼1 - 3 = - 2 fill_parent
- step 2:依次比例是1/6,2/6,3/6
- step 3:先到先得,先分給one,計算: 1 - 2 * (1/6) = 2/3 fill_parent 接着到two,計算: 1 - 2 * (2/6) = 1/3 fill_parent 最後到three,計算 1 - 2 * (3/6) = 0 fill_parent
- step 4:所以最後的結果是:one佔了兩份,two佔了一份,three什麼都木有
(2). LinearLayout 兩個佈局AB依次爲match_parent wrap_content,weight 1、1。結果爲1:0。
(3). LinearLayout 兩個佈局AB依次爲wrap_content match_parent,weight 1、1。結果爲<=1:1。
- 當wrap_content 佔1/3時 剩餘空間 1-1/3-1=-1/3。分配空間A 1/2-1/3=1/6。B 1-1/6=5/6 結果AB 1:5
- 當wrap_content 佔1時 AB 1:1
-
(4). LinearLayout 兩個佈局AB依次爲wrap_content wrap_content,weight 1、1。結果爲1:1。
2.ConstraintLayout:
2.1 介紹
約束佈局ConstraintLayout是一個ViewGroup,可以在Api9以上的Android系統使用它,它的出現主要是爲了解決佈局嵌套過多的問題,以靈活的方式定位和調整小部件。從 Android Studio 2.3 起,官方的模板默認使用 ConstraintLayout。
2.2.爲什麼要用ConstraintLayout
在開發過程中經常能遇到一些複雜的UI,可能會出現佈局嵌套過多的問題,嵌套得越多,設備繪製視圖所需的時間和計算功耗也就越多。
- 減少嵌套:上下左右位置可以對齊其他控件的上下左右。
- 有些人考慮到了嵌套佈局帶來的風險,所以用一個RelativeLayout來裝下所有的控件。那麼問題來了,既然用RelativeLayout可以解決問題,爲什麼還要使用ConstraintLayout呢?因爲ConstraintLayout使用起來比RelativeLayout更靈活,性能更出色!還有一點就是ConstraintLayout可以按照比例約束控件位置和尺寸,能夠更好地適配屏幕大小不同的機型。
2.3. 下面來看看相對定位的常用屬性:
layout_constraintLeft_toLeftOf
layout_constraintLeft_toRightOf
layout_constraintRight_toLeftOf
layout_constraintRight_toRightOf
layout_constraintTop_toTopOf
layout_constraintTop_toBottomOf
layout_constraintBottom_toTopOf
layout_constraintBottom_toBottomOf
layout_constraintBaseline_toBaselineOf
layout_constraintStart_toEndOf
layout_constraintStart_toStartOf
layout_constraintEnd_toStartOf
layout_constraintEnd_toEndOf
2.4. 角度定位:
app:layout_constraintCircle="@+id/TextView1"(以誰爲中心)
app:layout_constraintCircleAngle=“120”(角度)
app:layout_constraintCircleRadius=“150dp”(中心距離)
2.5 margin
- 在使用margin的時候要注意兩點:
- 控件必須在佈局里約束一個相對位置
- margin只能大於等於0
2.6 goneMargin
- goneMargin主要用於約束的控件可見性被設置爲gone的時候使用的margin值
舉個例子:
1.假設TextView2的左邊約束在TextView1的右邊,並給TextView2設一個app:layout_goneMarginLeft="10dp"
2.這個時候,TextView2左邊沒有邊距
3.這個時候把TextView1的可見性設爲gone
4.TextView1消失後,TextView2有一個距離左邊10dp的邊距。
2.4 尺寸約束
- 使用指定的尺寸
- 使用wrap_content,讓控件自己計算大小
當控件的高度或寬度爲wrap_content時,可以使用下列屬性來控制最大、最小的高度或寬度:
android:minWidth 最小的寬度
android:minHeight 最小的高度
android:maxWidth 最大的寬度
android:maxHeight 最大的高度
注意!當ConstraintLayout爲1.1版本以下時,使用這些屬性需要加上強制約束,如下所示:
app:constrainedWidth=”true”
app:constrainedHeight=”true” - 使用 0dp (MATCH_CONSTRAINT)
官方不推薦在ConstraintLayout中使用match_parent,可以設置 0dp (MATCH_CONSTRAINT) 配合約束代替match_parent - 寬高比
當寬或高至少有一個尺寸被設置爲0dp時,可以通過屬性layout_constraintDimensionRatio設置寬高比,舉個例子:
<TextView
android:id="@+id/TextView1"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" />
寬設置爲0dp,寬高比設置爲1:1,這個時候TextView1是一個正方形
2.5 輔助工具
2.5.1 Optimizer
- 當我們使用 MATCH_CONSTRAINT 時,ConstraintLayout 將對控件進行 2 次測量,ConstraintLayout在1.1中可以通過設置 layout_optimizationLevel 進行優化,可設置的值有:
- none:無優化
- standard:僅優化直接約束和屏障約束(默認)
- direct:優化直接約束
- barrier:優化屏障約束
- chain:優化鏈約束
- dimensions:優化尺寸測量
-
2.5.2 Barrier
假設有3個控件ABC,C在AB的右邊,但是AB的寬是不固定的,這個時候C無論約束在A的右邊或者B的右邊都不對。當出現這種情況可以用Barrier來解決。Barrier可以在多個控件的一側建立一個屏障,屏障位置在AB的右邊最長邊。
這個時候C只要約束在Barrier的右邊就可以了,代碼如下
TextView
android:id="@+id/TextView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/TextView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@+id/TextView1" />
<android.support.constraint.Barrier
android:id="@+id/barrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="right"
app:constraint_referenced_ids="TextView1,TextView2" />
<TextView
android:id="@+id/TextView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintLeft_toRightOf="@+id/barrier" />
app:barrierDirection爲屏障所在的位置,可設置的值有:bottom、end、left、right、start、top
app:constraint_referenced_ids爲屏障引用的控件,可設置多個(用“,”隔開)
2.6 Group
Group可以把多個控件歸爲一組,方便隱藏或顯示一組控件
<android.support.constraint.Group
android:id="@+id/group"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="invisible"
app:constraint_referenced_ids="TextView1,TextView3" />
2.7 Placeholder
Placeholder指的是佔位符。在Placeholder中可使用setContent()設置另一個控件的id,使這個控件移動到佔位符的位置。
2.8 Guideline
Guildline像輔助線一樣,在預覽的時候幫助你完成佈局(不會顯示在界面上)。
Guildline的主要屬性:
android:orientation 垂直vertical,水平horizontal
layout_constraintGuide_begin 開始位置
layout_constraintGuide_end 結束位置
layout_constraintGuide_percent 距離頂部的百分比(orientation =horizontal時則爲距離左邊)
二.UI佈局優化
1.卡頓原因
- 人爲在UI線程中做輕微耗時操作,導致UI線程卡頓;
- 佈局Layout過於複雜,無法在16ms內完成渲染;
- 同一時間動畫執行的次數過多,導致CPU或GPU負載過重;
- View過度繪製,導致某些像素在同一幀時間內被繪製多次,從而使CPU或GPU負載過重;
- View頻繁的觸發measure、layout,導致measure、layout累計耗時過多及整個View頻繁的重新渲染;
- 內存頻繁觸發GC過多(同一幀中頻繁創建內存),導致暫時阻塞渲染操作;
- 冗餘資源及邏輯等導致加載和執行緩慢;
- ANR;
2. include merge viewStub
viewStub加載方式 :
- view.inflate:避免調用多次,因爲inflate一次後 viewstub就被替換成根佈局了,多次調用會報錯
- setVisiable:原因會調inflate
建議調用setVisiable方法,源碼裏面做了第一次visiable時inflate的判斷
3.不用設置不必要的背景,避免過度繪製
4.UI優化工具 Layout Inspector,HierarchyViewer
Sdk 25.3.0 以後HierarchyViewer被廢棄了,取而代之的是Layout Inspector
功能:檢查佈局嵌套情況,以及佈局邊界
5.檢測UI卡頓工具 TraceView ,BlockCanary,Lint
5.1 TraceView
有兩種啓動方式:
- 藉助Android SDK中的DDMS工具
- Androidstudio自帶的traceview查看(Android profiler)。
profiler可以查看cpu memory network 每個方法的耗時時間等
5.2 Lint
詳情鏈接引用自 https://blog.csdn.net/luzhenyuxfcy/article/details/79398761
Lint 怎麼用
Android studio Analyze ->Inspect Code ->
Lint優化哪些問題
- 遺漏的翻譯(沒用上的翻譯)比如國際化未被翻譯的字段值
- 佈局性能(以前是 layoutopt工具,可以解決無用佈局、嵌套太多、佈局太多)
- 未使用到資源
- 不一致的數組大小
- 國際化問題(硬編碼)
- 圖標的問題(重複的圖標,錯誤的大小)
- 可用性問題(如不指定的文本字段的輸入型)
- manifest文件的錯誤
三.UI佈局適配
- dp px 2. .9圖片
傳統dp適配方式的缺點
- android中的dp在渲染前會將dp轉爲px,計算公式:
- px = density * dp;
- density = dpi / 160;
- px = dp * (dpi / 160);
- 屏幕尺寸、分辨率、像素密度(dpi)三者關係
像素密度dpi=√{(長度像素數^2 + 寬度像素數^2)}/ 屏幕尺寸
比如:屏幕分辨率爲:1920*1080,屏幕尺寸爲5吋的話,那麼dpi爲440。 - 代碼中過去density方式:
public int dip2px(float dipValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dipValue * scale + 0.5f);
}
屏幕分辨率限定符與 smallestWidth 限定符適配原理
詳細鏈接(部分引用自 https://www.jianshu.com/p/1302ad5a4b04)
我這裏要講的是使用 swdp限定符,即 smallestWidth(最小寬度) 限定符 來進行適配,使用這種方式只需要少量 dimens.xml 文件即可達到適配,而且根本不用考慮虛擬按鍵的問題。如果只適配手機,dimens.xml 文件所佔的體積只有 100 多 KB,即使加上平板和 TV,也就500多KB,完全可以接收。這種方案已經在自己多個項目中應用過了,經過幾十臺手機測試過,基本不會出現適配有問題的情況。製作生成對應 dimens.xml 文件插件(後面會講)的作者也說過他在待過的兩家大公司實踐過,所以請放心使用。
屏幕分辨率限定符:
屏幕分辨率限定符適配需要在 res 文件夾下創建各種屏幕分辨率對應的 values-xxx 文件夾,生成各種分辨率對應的 dimens.xml 文件。
文件以px 爲單位適配
smallestWidth 限定符 適配原理
- smallestWidth 限定符適配原理與屏幕分辨率限定符適配原理一樣,系統都是根據限定符去尋找對應的 dimens.xml 文件。例如程序運行在最小寬度爲 360dp 的設備上,系統會自動找到對應的 values-sw360dp 文件夾下的 dimens.xml 文件。
- 區別就在於屏幕分辨率限定符適配是拿 px 值等比例縮放,而 smallestWidth 限定符適配是拿 dp 值來等比縮放而已。
- 需要注意的是“最小寬度”是不區分方向的,即無論是寬度還是高度,哪一邊小就認爲哪一邊是“最小寬度”。
爲什麼選擇 smallestWidth 限定符適配?
既然原理都一樣,都需要多套 dimens.xml 文件,那爲什麼要選擇 smallestWidth 限定符適配呢?
- 屏幕分辨率限定符適配是根據屏幕分辨率的,Android設備分辨率一大堆,而且還要考慮虛擬鍵盤,這樣就需要大量的 dimens.xml 文件。因爲無論手機屏幕的像素多少,密度多少,90% 的手機的最小寬度都爲 360dp,所以採用 smallestWidth 限定符適配只需要少量 dimens.xml 文件即可。
- 屏幕分辨率限定符適配採用的是 px 單位,而 smallestWidth 限定符適配採用的單位是 dp 和 sp,dp 和 sp 是google 推薦使用的計量單位。又由於很多應用要求字體大小隨系統改變,所以字體單位使用 sp 也更靈活。
- 屏幕分辨率限定符適配需要設備分辨率與 values-xx 文件夾完全匹配才能達到適配,而 smallestWidth 限定符適配尋找 dimens.xml 文件的原理是從大往小找,例如設備的最小寬度爲 360dp,就會先去找 values-360dp,發現沒有則會向下找 values-320dp,如果還是沒有才找默認的 values 下的 demens.xml 文件,所以即使沒有完全匹配也能達到不錯的適配效果。
插件 ScreenMatch
以設計圖最小寬度(單位爲 dp)作爲基準值,生成所有設備對應的 dimens.xml 文件
mipmap文件夾關係:
header 1 | mipmap-lhdpi | mipmap-mdpi | mipmap-hdpi | mipmap-xhdpi | mipmap-xxhdpi | mipmap-xxxhdpi |
---|---|---|---|---|---|---|
dpi範圍 | (0-120]dpi | (120-160]dpi | (160-240]dpi | (240-320]dpi | (320-480]dpi | (480-640]dpi |
1dp對應px(luffy) | 0.75 | 1 | 1.5 | 2 | 3 | 4 |
當合適的mipmap文件夾中沒有對應的圖片的時候,會優先往高的找,會優先找最近的
mipmap文件夾圖片優先使用規則
當合適的mipmap文件夾中沒有對應的圖片的時候,會優先往高的找,會優先找最近的