VV-安卓佈局總彙篇
零、前言
一直以來覺得佈局也沒什麼好講的,特別是自從有了ConstraintLayout,拖拖接接基本上就行了
最近寫個播放器,感覺佈局並不是我想的這樣簡單,有的時候拖不出想要的結果,佈局程式碼改不好也挺尷尬
脫出來的控制元件畢竟是IDE的智商,一個控制元件屬性非常多,可讀性不怎樣,所以在此總結一下安卓的佈局
插播一段感悟:我經常思考工具與使用者間的關係:
用工具
和 會用工具
之差異: 良庖歲更刀,割也;族庖月更刀,折也
,工具的使用方法體現了一位 工匠
的技藝
《庖丁解牛》是我最喜歡的一篇古文,如何在做任何事上 以無厚入有間,恢恢乎其於遊刃必有餘地矣
是我的思考
文中的八字成為我接觸新事物的律典: 依乎天理,因其固然
。通其理,方用之,是 匠者
與 匠師
的差異
如果你不懂牛的構造原理,拿一把屠刀固然可殺牛取肉,但庖丁: 以神遇而不以目視,官知止而神欲行
提刀而立,為之四顧,為之躊躇滿志,善刀而藏之
的感覺也就與你無緣,而這是一位匠者的自豪。
寫一個程式就像打造一件藝術品,製造的過程便是 解牛
,IDE、API、執行環境就是我手中的劍
普通屠夫遇牛則斬,好肉壞肉在一起切,煮成一大雜燴。庖丁的匠心獨運是我追求的境界:
吾生也有涯,而知也無涯,以有涯隨無涯
願君且行且珍惜。
本文測試圖示是svg的安卓xml版,通過精心挑選,如下:

本文測試圖示.png
一、首先說開發者選項中的兩個佈局分析利器:
1.佈局的邊框顯示:
- 模擬器的Dev Tools裡,真機開發者選項裡:

佈局邊界.png
2.佈局的過渡繪製分析:
- 也在開發者選項裡,不過不是切換按鈕,裡面有選項,一般選第二個,如果綠色色弱選第三個(還挺貼心)

過渡繪製.png
3.從一個佈局看看用法:
佈局的巢狀可能導致一篇區域被繪製多次,根據繪製的次數多少分為下面幾種顏色:
原色 < 藍色 < 綠色 < 粉色 < 紅色
(吐槽:綠色 > 藍色總覺得挺彆扭)

待分析佈局.png
layout/activity_over_draw.xml:用5個白色背景的RelativeLayout巢狀
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="350dp" android:layout_height="350dp" android:background="@android:color/white" android:gravity="center" tools:context=".MainActivity"> <RelativeLayout android:layout_width="300dp" android:layout_height="300dp" android:layout_centerInParent="true" android:background="@android:color/white"> <RelativeLayout android:layout_width="200dp" android:layout_height="200dp" android:layout_centerInParent="true" android:background="@android:color/white"> <RelativeLayout android:layout_width="100dp" android:layout_height="100dp" android:layout_centerInParent="true" android:background="@android:color/white"> <RelativeLayout android:layout_width="50dp" android:layout_height="50dp" android:layout_centerInParent="true" android:background="@android:color/white"> </RelativeLayout> </RelativeLayout> </RelativeLayout> </RelativeLayout> </RelativeLayout>
4.講一下佈局的族譜:
可見XXXLayout都繼承自ViewGroup,最終都是View,所以View、ViewGroup的通用佈局屬性都可以用
不同的佈局有自己獨特的佈局屬性、詳見後文

常見佈局.png
一、RelativeLayout
從RelativeLayout原始碼總尋找@attr檢視的特有屬性
看起來挺多,但通過下面分分類,也就一目瞭然了
* @attr RelativeLayout_gravity * @attr RelativeLayout_ignoreGravity * @attr RelativeLayout_Layout_layout_alignWithParentIfMissing * @attr RelativeLayout_Layout_layout_toLeftOf * @attr RelativeLayout_Layout_layout_toRightOf * @attr RelativeLayout_Layout_layout_above * @attr RelativeLayout_Layout_layout_below * @attr RelativeLayout_Layout_layout_alignBaseline * @attr RelativeLayout_Layout_layout_alignLeft * @attr RelativeLayout_Layout_layout_alignTop * @attr RelativeLayout_Layout_layout_alignRight * @attr RelativeLayout_Layout_layout_alignBottom * @attr RelativeLayout_Layout_layout_alignParentLeft * @attr RelativeLayout_Layout_layout_alignParentTop * @attr RelativeLayout_Layout_layout_alignParentRight * @attr RelativeLayout_Layout_layout_alignParentBottom * @attr RelativeLayout_Layout_layout_centerInParent * @attr RelativeLayout_Layout_layout_centerHorizontal * @attr RelativeLayout_Layout_layout_centerVertical * @attr RelativeLayout_Layout_layout_toStartOf * @attr RelativeLayout_Layout_layout_toEndOf * @attr RelativeLayout_Layout_layout_alignStart * @attr RelativeLayout_Layout_layout_alignEnd * @attr RelativeLayout_Layout_layout_alignParentStart * @attr RelativeLayout_Layout_layout_alignParentEnd
1.gravity
決定內部控制元件擺放的位置(父控制元件主動)

gravity.png
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="250dp" android:layout_height="250dp" android:background="@android:color/white" android:gravity="center_horizontal" tools:context=".MainActivity"> <ImageView android:layout_width="100dp" android:layout_height="100dp" android:src="@drawable/icon_center"/> </RelativeLayout>
2.子控制元件主動找Parent(子循父)
//與父控制元件左、上、右、下對齊 layout_alignParentLeft、layout_alignParentTop 、layout_alignParentRight、layout_alignParentBottom //居中、水平居中、垂直居中 layout_centerInParent、layout_centerHorizontal、layout_centerVertical //效果等同於-layout_alignParentLeft、layout_alignParentRight,AndroidStudio推薦使用這兩個 layout_alignParentStart 、layout_alignParentEnd

RelativeLayout子循父屬性一覽.png
3.子控制元件主動找子控制元件(子循兄)
//參照屬性 layout_above、layout_below layout_toLeftOf、layout_toRightOf==layout_toStartOf、layout_toEndOf //對齊屬性 layout_alignTop、layout_alignBottom、layout_alignBaseline layout_alignLeft、layout_alignRight ==layout_alignStart、layout_alignEnd

RelativeLayout子循兄屬性一覽.png
4.通過一個圖總結一下RelativeLayout
佈局檔案見文後原始碼,有點長,不貼了
這裡說一下:padding和margin,兩者都可以讓自己與旁邊的控制元件產生間隙,區別在於:
比如你在一個大箱子裡,又被箱子裡的石頭緊緊困住,padding就像縮小自己尋求空隙,margin就是把石頭推開
當margin太大,石頭不能往外偏移了,石頭就會如圖四

邊距.png
二、ConstraintLayout 約束佈局
大學時學solidworks(3D軟體)時便對約束有很深的印象,約束可以實現複雜結構的關聯
1.定位屬性
AndroidStudio中快速打入
ste ==layout_constraintStart_toEndOf ss==layout_constraintStart_toStartOf es==layout_constraintEnd_toStartOf ete ==layout_constraintEnd_toEndOf ttt ==layout_constraintTop_toTopOf ttb ==layout_constraintTop_toBottomOf btt ==layout_constraintBottom_toTopOf btb ==layout_constraintBottom_toBottomOf

ConstraintLayout定位屬性一覽.png

ConstraintLayout樣例.png
2.邊距屬性

待定位邊距屬性一覽.png
3.乖離率---bias:
layout_constraintHorizontal_bias
layout_constraintVertical_bias
頭接父頭,尾接父尾,長寬固定的情況不能實現:
實驗一下,結果居中了,調節 layout_constraintHorizontal_bias
的值(0~1)

Horizontal_bias.png
<ImageView android:id="@+id/id_iv_center" android:layout_width="50dp" android:layout_height="50dp" android:src="@drawable/icon_center" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias=".9" app:layout_constraintStart_toStartOf="parent"/>
4.比例寬高:layout_constraintDimensionRatio
<ImageView android:id="@+id/id_iv_center" android:layout_width="50dp" android:layout_height="0dp" android:src="@drawable/icon_center" android:scaleType="centerCrop" app:layout_constraintDimensionRatio="1:4" android:background="@color/colorPrimary" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent"/>

比例寬高.png
5.控制元件鏈
還記得是結構的雙鏈表吧,除首位節點,其他都持有前後的引用,這裡約束也相似
也能實現一個接著一個,後面有連到前面的結構。
鏈模式:加在鏈頭,加在鏈頭,加在鏈頭(重要的話說三遍)
水平鏈模式: layout_constraintHorizontal_chainStyle
垂直鏈模式: layout_constraintVertical_chainStyle

鏈.png
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="230dp" android:layout_height="230dp" android:background="@android:color/white"> <!--左--> <ImageView android:id="@+id/id_iv_left" android:layout_width="30dp" android:layout_height="30dp" android:src="@drawable/icon_left" app:layout_constraintHorizontal_bias=".3" app:layout_constraintEnd_toStartOf="@id/id_iv_right" app:layout_constraintHorizontal_chainStyle="spread_inside" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" tools:layout_editor_absoluteY="0dp"/> <!--右--> <ImageView android:id="@+id/id_iv_right" android:layout_width="30dp" android:layout_height="30dp" android:src="@drawable/icon_right" app:layout_constraintEnd_toStartOf="@+id/id_iv_top" app:layout_constraintStart_toEndOf="@id/id_iv_left"/> <!--上--> <ImageView android:id="@+id/id_iv_top" android:layout_width="30dp" android:layout_height="30dp" android:src="@drawable/icon_top" app:layout_constraintEnd_toStartOf="@id/id_iv_bottom" app:layout_constraintStart_toEndOf="@id/id_iv_right"/> <!--下--> <ImageView android:id="@+id/id_iv_bottom" android:layout_width="30dp" android:layout_height="30dp" android:src="@drawable/icon_bottom" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@id/id_iv_top"/> </android.support.constraint.ConstraintLayout>
注:鏈自己寫比較麻煩,可以在預覽區選中,自動生成:

自動生成鏈.png
6.三個不可視的輔助標籤
1).參考線輔助定位:Guideline
就當是一個gone的view,但保留自己的位置資訊,為佈局提供參考
<android.support.constraint.Guideline android:id="@+id/center_in_h" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" app:layout_constraintGuide_percent="0.5"/>

Guideline.png
2).組:Group
試了一下,並不像我想象中的那麼強大,不能靠分組定位。可在程式碼裡同組Gone掉,有點雞肋。
<android.support.constraint.Group android:id="@+id/id_left_right" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintEnd_toEndOf="parent" app:constraint_referenced_ids="id_iv_left,id_iv_right"/>
3).屏障:Barrier
這個挺不錯的,將view打包,提供一個約束參考,有點像分組定位,可惜貌似只能一邊。可看作一個透明的牆,能提供依靠。

barrier.png
<!--左--> <ImageView android:id="@+id/id_iv_left" android:layout_width="30dp" android:layout_height="30dp" android:src="@drawable/icon_left" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent"/> <!--右--> <ImageView android:id="@+id/id_iv_right" android:layout_width="30dp" android:layout_height="30dp" android:src="@drawable/icon_right" app:layout_constraintStart_toEndOf="@id/id_iv_left" app:layout_constraintTop_toTopOf="parent"/> <ImageView android:id="@+id/id_iv_center" android:layout_width="30dp" android:layout_height="30dp" android:src="@drawable/icon_center" app:layout_constraintTop_toBottomOf="@id/barrier"/> <android.support.constraint.Barrier android:id="@+id/barrier" android:layout_width="wrap_content" android:layout_height="wrap_content" app:constraint_referenced_ids="id_iv_left,id_iv_right" app:barrierDirection="bottom"/>
三、最後舉一個小栗子
可以看出ConstraintLayout可以減少佈局的層次,減少過渡繪製的次數
一個0.65的豎直參考線,三個圖示形成鏈,頂底對齊父控制元件

比較.png
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="70dp" android:layout_marginTop="100dp" android:foreground="?android:attr/selectableItemBackground" android:orientation="horizontal"> <ImageView android:id="@+id/id_iv_icon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="8dp" android:src="@mipmap/icon_default" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent"/> <TextView android:id="@+id/id_tv_music_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="5dp" android:text="勇氣" android:textColor="#363636" android:textSize="18dp" app:layout_constraintBottom_toTopOf="@id/id_tv_singer" app:layout_constraintStart_toEndOf="@id/id_iv_icon" app:layout_constraintTop_toTopOf="parent"/> <TextView android:id="@+id/id_tv_singer" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="5dp" android:text="葛強麗" android:textColor="#898989" android:textSize="12dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="@id/id_tv_music_name" app:layout_constraintTop_toBottomOf="@id/id_tv_music_name"/> <ImageView android:id="@+id/id_iv_ctrl" android:layout_width="28sp" android:layout_height="28sp" android:layout_toStartOf="@id/id_iv_next" android:src="@drawable/icon_stop_2" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toStartOf="@+id/id_iv_next" app:layout_constraintStart_toStartOf="@+id/point7_h" app:layout_constraintTop_toTopOf="parent"/> <ImageView android:id="@+id/id_iv_next" android:layout_width="28sp" android:layout_height="28sp" android:layout_toStartOf="@id/id_iv_pre_list" android:src="@drawable/icon_next" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toStartOf="@+id/id_iv_pre_list" app:layout_constraintStart_toEndOf="@+id/id_iv_ctrl" app:layout_constraintTop_toTopOf="parent"/> <android.support.constraint.Guideline android:id="@+id/point7_h" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" app:layout_constraintGuide_percent="0.65"/> <ImageView android:id="@+id/id_iv_pre_list" android:layout_width="28sp" android:layout_height="28sp" android:src="@drawable/icon_music_list" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@+id/id_iv_next" app:layout_constraintTop_toTopOf="parent"/> </android.support.constraint.ConstraintLayout>
後記:捷文規範
1.本文成長記錄及勘誤表
專案原始碼 | 日期 | 備註 |
---|---|---|
V0.1--無 | 2018-11-2 | ofollow,noindex">VV-安卓佈局總彙篇 |
2.更多關於我
筆名 | 微信 | 愛好 | |
---|---|---|---|
張風捷特烈 | 1981462002 | zdl1994328 | 語言 |
我的github | 我的簡書 | 我的CSDN | 個人網站 |
3.宣告
1----本文由張風捷特烈原創,轉載請註明
2----歡迎廣大程式設計愛好者共同交流
3----個人能力有限,如有不正之處歡迎大家批評指證,必定虛心改正
4----看到這裡,我在此感謝你的喜歡與支援