android-基礎知識-佈局

android-基礎知識-佈局

一.七大布局

七大布局分別爲:線性佈局(LInearLayout)、相對佈局(RelativeLayout)、幀佈局(FrameLayout)、表格佈局(TableLayout)、絕對佈局(absoluteLayout)、網格佈局(GridLayout)、約束佈局(ConstraintLayout)

1.相似屬性之間的區別:

  1. gravity的 start 和left的區別:

        left是絕對的左邊,start會根據不同的國家習慣改變。

        比如在從右向左順序閱讀的國家,start代表的就是在右邊
  2. fill_parent 和 match_parent:

        Android2.2中match_parent和fill_parent是一個意思兩個參數意思一樣,match_parent更貼切,於是從2.2開始兩個詞都可以用。那麼如果考慮低版本的使用情況你就需要用fill_parent了

1.LinearLayout:

1.weight 屬性分析
  1. 整體思路:
  • 0dp 按整體1 計算比例 如weight分別爲1、2、3。那麼實際比例爲1、2、3
  • wrap_content :先wrap_content 分配大小,然後剩餘比例分配,注意:wrap_content 最大佔1
  • march_parent: 按佔1分配
  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:

簡書地址引用:

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加載方式 :

  1. view.inflate:避免調用多次,因爲inflate一次後 viewstub就被替換成根佈局了,多次調用會報錯
  2. 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

有兩種啓動方式:

  1. 藉助Android SDK中的DDMS工具
  2. 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佈局適配

  1. dp px 2. .9圖片

傳統dp適配方式的缺點

  1. android中的dp在渲染前會將dp轉爲px,計算公式:
  • px = density * dp;
  • density = dpi / 160;
  • px = dp * (dpi / 160);
  1. 屏幕尺寸、分辨率、像素密度(dpi)三者關係

    像素密度dpi=√{(長度像素數^2 + 寬度像素數^2)}/ 屏幕尺寸

    比如:屏幕分辨率爲:1920*1080,屏幕尺寸爲5吋的話,那麼dpi爲440。
  2. 代碼中過去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 限定符適配呢?

  1. 屏幕分辨率限定符適配是根據屏幕分辨率的,Android設備分辨率一大堆,而且還要考慮虛擬鍵盤,這樣就需要大量的 dimens.xml 文件。因爲無論手機屏幕的像素多少,密度多少,90% 的手機的最小寬度都爲 360dp,所以採用 smallestWidth 限定符適配只需要少量 dimens.xml 文件即可。
  2. 屏幕分辨率限定符適配採用的是 px 單位,而 smallestWidth 限定符適配採用的單位是 dp 和 sp,dp 和 sp 是google 推薦使用的計量單位。又由於很多應用要求字體大小隨系統改變,所以字體單位使用 sp 也更靈活。
  3. 屏幕分辨率限定符適配需要設備分辨率與 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文件夾中沒有對應的圖片的時候,會優先往高的找,會優先找最近的

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章