已有很多關(guān)于ConstrainLayout的介紹,偏向?qū)傩缘幕A(chǔ)介紹,主要講述了具有哪些屬性和基準(zhǔn)線的屬性,但到了實(shí)際項(xiàng)目中,光是知道屬性是遠(yuǎn)不夠的,完整一個(gè)略微復(fù)雜的界面,就需要屬性之間的組合使用。
而ConstainLayout屬性之前有相互牽制(當(dāng)然啦,該布局本來(lái)就叫約束布局,從屬性的使用中也體現(xiàn)出了這個(gè)概念),有的屬性A,由于另一個(gè)屬性B的不再設(shè)置,就失去A屬性的作用。
初次使用,會(huì)暈頭轉(zhuǎn)向,怎么剛剛還有效果的,加了個(gè)屬性或者改了某個(gè)已經(jīng)在的屬性的值,布局就亂套了。
總而言之,孰能生巧,體會(huì)該布局的核心思想,先規(guī)劃布局,再動(dòng)手實(shí)踐。
屬性簡(jiǎn)介
先稍微回顧一下屬性,這里只做簡(jiǎn)單羅列。
1.寬高比例
layout_constrainDimensionRatio:"w,13:2"/"h, 23:23",其中w,h可以不注明, 默認(rèn)為寬高比
2.位置對(duì)齊
layout_constraintLeft_toLeftOf: 將目標(biāo)控件的左側(cè)牽引到另外一個(gè)控件的左側(cè)
layout_constraintRight_toLeftOf: 將目標(biāo)控件的右側(cè)牽引到另外一個(gè)控件的左側(cè)
layout_constraintLeft_toRightOf: 將目標(biāo)控件的左側(cè)牽引到另外一個(gè)控件的右側(cè)
layout_constraintRight_toRightOf: 將目標(biāo)控件的右側(cè)牽引到另外一個(gè)控件的右側(cè)
layout_constraintTop_toTopOf: 將目標(biāo)控件的上側(cè)牽引到另外一個(gè)控件的上側(cè)
layout_constraintTop_toBottomOf: 將目標(biāo)控件的上側(cè)牽引到另外一個(gè)控件的下側(cè)
layout_constraintBottom_toTopOf: 將目標(biāo)控件的下側(cè)牽引到另外一個(gè)控件的上側(cè)
layout_constraintBottom_toBottomOf: 將目標(biāo)控件的下側(cè)牽引到另外一個(gè)控件的下側(cè)
================
layout_constrainStart_toEndOf:將目標(biāo)控件的左側(cè)與另一控件的右側(cè)對(duì)齊
layout_constrainStart_toStartOf:將目標(biāo)控件的左側(cè)與另一控件的左側(cè)對(duì)齊
layout_constrainEnd_toStartOf:將目標(biāo)控件的右側(cè)與另一控件的左側(cè)對(duì)齊
layout_constrainEnd_toEndOf:將目標(biāo)控件的右側(cè)與另一控件的右側(cè)對(duì)齊
3.基線對(duì)齊
layout_constrainBaseline_toBaselineOf:與目標(biāo)控件的基線對(duì)齊
4.基準(zhǔn)線【GuideLine】
orientation:vertical/horizontal 基準(zhǔn)線的方向
layout_constrainGuide_begin:基準(zhǔn)線起點(diǎn)
layout_constrainGuide_end:基準(zhǔn)線終點(diǎn)
layout_constrainGuide_percent:基準(zhǔn)線百分比模式,用于指定位置
5.牽引線
layout_constrainHorizontal_bias:水平方向上的牽引力
layout_constrainVertical_bias:垂直方向上的牽引力
6.鏈樣式
layout_constrainHorizontal_chainStyle:水平方向上的樣式
layout_constrainVertical_chainStyle:垂直方向上的樣子
layout_constrainVertical_weight:設(shè)置該控件在鏈中的權(quán)重
可以設(shè)置鏈樣式的屬性值

實(shí)踐
實(shí)現(xiàn)如下圖該界面布局

實(shí)現(xiàn)方式:一般的使用一般的嵌套布局也可以實(shí)現(xiàn),主要原因是層次會(huì)比較深,還會(huì)影響頁(yè)面繪制的時(shí)間。
約束布局:其優(yōu)勢(shì)是扁平式的局部方式,繪制時(shí)間短。
小結(jié):當(dāng)然啦,如果只是簡(jiǎn)單地實(shí)現(xiàn)整個(gè)界面,兩種方式前者除了繪制上的劣勢(shì)似乎沒(méi)有其他什么比較大差別。而約束布局ConstrainLayout的使用門檻則相對(duì)高一些,但當(dāng)開(kāi)發(fā)者已經(jīng)熟練掌握,信手拈來(lái)時(shí),那絕對(duì)是酸爽,不過(guò)出現(xiàn)某條屬性導(dǎo)致的“牽一發(fā)而動(dòng)全身”的后果。
另外:
基于作者君的業(yè)務(wù)場(chǎng)景,用戶在觀看影片的同時(shí),出現(xiàn)小半屏幕的掃碼界面。界面除了要適配不同分辨率的機(jī)型,由于不同業(yè)務(wù)方自身的UI風(fēng)格,對(duì)于界面站整個(gè)屏幕的比重也有自身的要求。因此希望開(kāi)放設(shè)置寬度屏占比、高度屏占比的接口,即對(duì)接方的開(kāi)發(fā)者通過(guò)一個(gè)方法設(shè)置浮層整體的寬高屬性值。作者君的UI設(shè)計(jì)需要需要保證整體內(nèi)容位置的美觀效果不變。
基于上訴業(yè)務(wù)需求,采用一般的嵌套布局實(shí)現(xiàn),從達(dá)到視覺(jué)結(jié)果來(lái)看,沒(méi)什么問(wèn)題,但今天的重點(diǎn)是ConstrainLayout的實(shí)踐,因此著重講述它的實(shí)現(xiàn)。
好啦,如果讀者不理解作者君的業(yè)務(wù)場(chǎng)景,就直接略過(guò)上面的話。注重看用那ConstrainLayout來(lái)實(shí)現(xiàn)如上圖的界面吧。
1.控制布局位置:Guideline的使用,限定整個(gè)界面位于右側(cè)。
Guideline是不占大小的一條輔助線,可以用來(lái)占位、劃分區(qū)域、作為定位其他view的基準(zhǔn)線。
例如項(xiàng)目中淘客二維碼界面,需要展示在屏幕的右邊
主要使用了如上述所說(shuō)的四個(gè)屬性:
orientation:vertical/horizontal 基準(zhǔn)線的方向
layout_constrainGuide_begin:基準(zhǔn)線起點(diǎn)
layout_constrainGuide_end:基準(zhǔn)線終點(diǎn)
layout_constrainGuide_percent:基準(zhǔn)線百分比模式,用于指定位置。
具體使用如下:
<!---頂部水平分割線 --!>
<android.support.constraint.Guideline
android:id="@+id/horizontalGuideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"/>
<!--右側(cè)視圖分割線線---!>
<android.support.constraint.Guideline
android:id="@+id/verticalGuideline"
android:layout_width="wrap_content"
android:layout_height="100dp"
android:orientation="vertical"
app:layout_constraintGuide_end="519dp"
app:layout_constraintRight_toRightOf="parent" />
<!---底部水平分割線 :注意用percent值來(lái)設(shè)置居于底部是為屏幕高度的適配,不建議用end或start --!>
<android.support.constraint.Guideline
android:id="@+id/horizontalGuideline2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="1.0" />
<View
android:id="@+id/view2"
android:layout_width="wrap_content" //注意,這里必須是wrap_content,不用擔(dān)心
android:layout_height="wrap_content"http://view無(wú)法展示,事實(shí)上,則是它是占滿右側(cè)的
android:background="@color/color99001122"
app:layout_constraintLeft_toRightOf="@id/verticalGuideline"
app:layout_constraintTop_toTopOf="@id/horizontalGuideline"
app:layout_constraintBottom_toBottomOf="@id/horizontalGuideline2"/>
看一下實(shí)現(xiàn)后的效果:水平的GuideLine和垂直的GuieLine。此時(shí)改變GuideLine的屬性就可以改變黑色區(qū)域的大小。OK背景色已經(jīng)寫(xiě)完。(注意:約束布局是一種扁平的布局,所有view都是同級(jí)的,不存在嵌套約束關(guān)系,
所以界面上需要擺放的其他view也要通過(guò)約束位置來(lái)實(shí)現(xiàn)上下壓縮,左側(cè)拉伸時(shí),位置能夠相對(duì)友好,以滿足視覺(jué)需求。)
layout_constrainGuide_begin:基準(zhǔn)線起點(diǎn)
layout_constrainGuide_end:基準(zhǔn)線終點(diǎn)
//當(dāng)GuideLine屬性值改變時(shí),View的大小會(huì)發(fā)生變化,但其width和height仍然為wrap_content.
//當(dāng)然還可以使用百分比的方式:
layout_constrainGuide_percent:基準(zhǔn)線百分比模式,用于指定位置

2.水平居中放置互聯(lián)view:Chain的使用
約束view位于水平線的下方
layout_constraintTop_toBottomOf
【頂部線的位置被壓縮后,view也自動(dòng)向下移動(dòng)】
view水平居中對(duì)齊
=========
layout_constraintEnd_toStartOf
layout_constraintStart_toEndOf
這兩個(gè)屬性來(lái)確認(rèn)相鄰view之前的關(guān)系(可能會(huì)想為什么讓不用left_ToRight等屬性,也可能讓三個(gè)view排成一排啊、是可以排成一排,但設(shè)置的下面屬性就失效了。建議自己寫(xiě)一下感受下。)
============
layout_constraintHorizontal_chainStyle
設(shè)置chainStyle的不同值,view之間的間距會(huì)不一樣。(回顧上文的藍(lán)色圖)
設(shè)置所有view距離頂部線的高度一致
1. 可以分別設(shè)置每個(gè)view的marginTop
2.也可以設(shè)置首個(gè)view的marginTop,其他view與它Top_toTop對(duì)齊。
3.或者其他我沒(méi)有想到的更好的方案............
<ImageView
android:id="@+id/iv_detail_pop_taobao"
android:layout_width="60dp"
android:layout_height="60dp"
android:background="@drawable/saoma_taobao"
android:layout_marginTop="50dp"
app:layout_constraintTop_toBottomOf="@id/horizontalGuideline"
app:layout_constraintEnd_toStartOf="@id/iv_detail_pop_tmall"
app:layout_constraintStart_toEndOf="@id/verticalGuideline"
app:layout_constraintHorizontal_chainStyle="packed" //設(shè)值緊湊模式
android:layout_marginRight="20dp" //通過(guò)marginRight來(lái)自定義彼此之間的間距
/>
<ImageView
android:id="@+id/iv_detail_pop_tmall"
android:layout_width="60dp"
android:layout_height="60dp"
android:background="@drawable/saoma_tianmao"
app:layout_constraintTop_toTopOf="@id/iv_detail_pop_taobao"
app:layout_constraintEnd_toStartOf="@id/iv_detail_pop_alipay"
app:layout_constraintStart_toEndOf="@id/iv_detail_pop_taobao"
android:layout_marginRight="20dp"
/>
<ImageView
android:id="@+id/iv_detail_pop_alipay"
android:layout_width="60dp"
android:layout_height="60dp"
android:background="@drawable/saoma_zhifubao"
app:layout_constraintTop_toTopOf="@id/iv_detail_pop_taobao"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/iv_detail_pop_tmall"

文字一行的擺放也是如此,不再贅述。
讓某個(gè)text居中就更容易了,只要指明他左邊或右邊的參照物,或者start 和end的參照物,就可以在兩個(gè)參照物之間居中
<TextView
android:layout_width="wrap_content"
android:layout_height="32dp"
android:layout_marginTop="20dp"
android:text="該寶貝需掃碼購(gòu)買"
android:textColor="@color/colorWhite"
android:textSize="22sp"
app:layout_constraintLeft_toRightOf="@id/guideline2"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_tmall_title" />
實(shí)現(xiàn)效果

圖片隨寬高自伸縮
UI需求描述:居中且大小可伸縮的圖片,讓圖片左右兩側(cè)的間隙保持一個(gè)百分比定值。比如左右側(cè)始終為10%間距。
約束布局沒(méi)有可以設(shè)置間距大小為百分比的屬性,這里采用重新設(shè)置圖片寬高的屬性來(lái)達(dá)到目的。
根據(jù)開(kāi)發(fā)這傳入的整體寬度值500,計(jì)算圖片的大小為 500-210%500=400,即圖片大小為400*400,常規(guī)的做法需要通過(guò)代碼動(dòng)態(tài)修改圖片的寬、高值。這里使用了約束布局的一個(gè)屬性:設(shè)置寬高比,只需重寫(xiě)一個(gè)值,略簡(jiǎn)單。
app:layout_constraintDimensionRatio="1:1"
那么在代碼中只需要設(shè)置寬與高其中一個(gè)值就可以保持1:1的大小
指定寬高之一為定值,剩下的一個(gè)必須為0dp。

最后一行文字的位置也就很簡(jiǎn)單了:以底部guideLine的基準(zhǔn)線,再設(shè)置偏移位置。
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="客服電話:0571-851378778"
android:textColor="@color/coloraabbcc"
android:textSize="18sp"
android:layout_marginBottom="50dp"
app:layout_constraintBottom_toBottomOf="@id/horizontalGuideline2"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toRightOf="@id/verticalGuideline"
/>
由于為了保證美觀性,自適應(yīng)布局在UI設(shè)計(jì)時(shí)會(huì)以最小與最大情況考慮各類圖片的大小和其間距,所以并非所有的尺寸都要縮放(如上述的白色方塊圖為例子)。如果要做到縮放,則需要通過(guò)代碼動(dòng)態(tài)地設(shè)置大小,目前還不支持百分比。
到這里為止,幾乎約束布局的所有類型的屬性都已經(jīng)用了一遍。重點(diǎn)思考和實(shí)現(xiàn),在這過(guò)程中體會(huì)約束布局的美妙~~