Constraintlayout 2.0:大家要的更新來了

一年前寫ConstraintLayout,看完一篇真的就夠了麼? 文章的時候說過,任何技術都會有時限性,只有不斷的學習,不斷的更新自我,纔不會outer。 有朋友也留言,但願更新...那就有本文了。android

目前2.0只是新增了一些新功能和新玩法,對1.x版本無取代之意,因此1.x版本仍是得學習的。好文推薦 2.0版本新增的內容在實踐開發也是很是實用的,建議能夠上車了。git

因爲無知與惰性,讓咱們感受摸到了技術的天花板github

對你有用,幫忙點贊~api

基於本文發表,ConstraintLayout版本已經更新到2.0.0-beta8,因此添加依賴的姿式:markdown

AndroidX:app

implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta8'
複製代碼

支持庫:ide

implementation 'com.android.support.constraint:constraint-layout:2.0.0-beta8'
複製代碼

版本說明:oop

alpha:內部測試版,bug多多;佈局

beta:公開測試版本,bug少點,支持嚐鮮;post

rc:候選版本,功能不增,和發佈版本一致,修修小bug;

stable:穩定版本,你儘管用,bug能找到是福氣。

1、Flow流式虛擬佈局(alpha 5增長)

正常狀況下,列表顯示通常採用ListView或者RecyclerView來實現,但其子Item佈局是很是呆板的。想象一下,若是一部做品的詳情頁結束打上一堆標籤,樣式以下,該怎麼實現?

這種佈局採用Flow來實現特別的簡單和方便,並且經過flow_wrapMode屬性能夠設置不一樣對齊方式。

下面佈局代碼簡單示例:Flow佈局經過constraint_referenced_ids屬性將要約束的Viewid進行關聯,這裏簡單關聯AGTextView,因爲TextView沒有設置約束條件,因此Android Studio 4.0 會報紅,給ConstraintLayout佈局添加tools:ignore="MissingConstraints"忽略報紅提示。

Flow佈局的flow_horizontalGap屬性表示水平之間兩個View的水平間隔,flow_verticalGap則是垂直方向間隔。

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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="match_parent"  android:layout_height="match_parent"  tools:ignore="MissingConstraints"//忽略Android Studio 4.0報紅提示  tools:context=".MainActivity">   <androidx.constraintlayout.helper.widget.Flow  android:id="@+id/flow"  android:layout_width="wrap_content"  android:layout_height="wrap_content"  app:constraint_referenced_ids="tvA,tvB,tvC,tvD,tvE,tvF,tvG"  app:flow_horizontalGap="30dp" //View水平間隔  app:flow_verticalGap="30dp" //垂直間隔  app:flow_wrapMode="none"  app:layout_constraintLeft_toLeftOf="parent"  app:layout_constraintTop_toTopOf="parent" />   <TextView  android:id="@+id/tvA"  android:layout_width="50dp"  android:layout_height="50dp"  android:background="@color/colorPrimary"  android:gravity="center"  android:text="A"  android:textColor="#ffffff"  android:textSize="16sp"  />   <TextView  android:id="@+id/tvB"  android:layout_width="50dp"  android:layout_height="50dp"  android:background="@color/colorPrimary"  android:gravity="center"  android:text="B"  android:textColor="#ffffff"  android:textSize="16sp"  />   <TextView  android:id="@+id/tvC"  android:layout_width="50dp"  android:layout_height="50dp"  android:background="@color/colorPrimary"  android:gravity="center"  android:text="C"  android:textColor="#ffffff"  android:textSize="16sp"  />   <TextView  android:id="@+id/tvD"  android:layout_width="50dp"  android:layout_height="50dp"  android:background="@color/colorPrimary"  android:gravity="center"  android:text="D"  android:textColor="#ffffff"  android:textSize="16sp"  />   <TextView  android:id="@+id/tvE"  android:layout_width="50dp"  android:layout_height="50dp"  android:background="@color/colorPrimary"  android:gravity="center"  android:text="E"  android:textColor="#ffffff"  android:textSize="16sp"  />   <TextView  android:id="@+id/tvF"  android:layout_width="50dp"  android:layout_height="50dp"  android:background="@color/colorPrimary"  android:gravity="center"  android:text="F"  android:textColor="#ffffff"  android:textSize="16sp"  />   <TextView  android:id="@+id/tvG"  android:layout_width="50dp"  android:layout_height="50dp"  android:background="@color/colorPrimary"  android:gravity="center"  android:text="G"  android:textColor="#ffffff"  android:textSize="16sp"  />  </androidx.constraintlayout.widget.ConstraintLayout> 複製代碼

flow_wrapMode屬性一共有三種值,在上面的佈局的基礎上,更換一下不一樣的值,看一下效果:

none值:全部引用的View造成一條鏈,水平居中,超出屏幕兩側的View不可見。

chian值:所引用的View造成一條鏈,超出部分會自動換行,同行的View會平分寬度。

aligned值:所引用的View造成一條鏈,但View會在同行同列。

即然是一條鏈,那麼能夠經過鏈的樣式進行約束。

鏈約束

flow_wrapMode屬性爲alignedchian屬性時,經過鏈進行約束。ConstraintLayout,看完一篇真的就夠了麼? 此文有談到鏈約束(Chain)。

Flow佈局添加如下屬性進行不一樣chain約束:

  • flow_firstHorizontalStyle 約束第一條水平鏈,當有多條鏈(多行)時,只約束第一條鏈(第一行),其餘鏈(其餘行)不約束;
  • flow_lastHorizontalStyle 約束最後一條水平鏈,當有多條鏈(多行)時,只約束最後一條鏈(最後一行),其餘鏈(其餘行)不約束;
  • flow_horizontalStyle 約束全部水平鏈;
  • flow_firstVerticalStyle 同水平約束;
  • flow_lastVerticalStyle 同水平約束;
  • flow_verticalStyle 約束全部垂直鏈;

以上屬性,取值有:spreadspread_insidepacked

效果:

spread值:

代碼:

<androidx.constraintlayout.helper.widget.Flow
 android:id="@+id/flow"  android:layout_width="match_parent"  android:layout_height="wrap_content"  android:layout_marginTop="50dp"  app:constraint_referenced_ids="tvA,tvB,tvC,tvD,tvE,tvF,tvG"  app:flow_maxElementsWrap="4"  app:flow_horizontalGap="30dp"  app:flow_verticalGap="30dp"  app:flow_wrapMode="chain"  app:flow_horizontalStyle="spread"  app:layout_constraintLeft_toLeftOf="parent"  app:layout_constraintTop_toTopOf="parent" />  複製代碼

spread_inside值:

代碼:

<androidx.constraintlayout.helper.widget.Flow
 android:id="@+id/flow"  android:layout_width="match_parent"  android:layout_height="wrap_content"  android:layout_marginTop="50dp"  app:constraint_referenced_ids="tvA,tvB,tvC,tvD,tvE,tvF,tvG"  app:flow_maxElementsWrap="4"  app:flow_horizontalGap="30dp"  app:flow_verticalGap="30dp"  app:flow_wrapMode="chain"  app:flow_horizontalStyle="spread_inside"  app:layout_constraintLeft_toLeftOf="parent"  app:layout_constraintTop_toTopOf="parent" /> 複製代碼

packed值:

代碼:

<androidx.constraintlayout.helper.widget.Flow
 android:id="@+id/flow"  android:layout_width="match_parent"  android:layout_height="wrap_content"  android:layout_marginTop="50dp"  app:constraint_referenced_ids="tvA,tvB,tvC,tvD,tvE,tvF,tvG"  app:flow_maxElementsWrap="4"  app:flow_horizontalGap="30dp"  app:flow_verticalGap="30dp"  app:flow_wrapMode="chain"  app:flow_horizontalStyle="packed"  app:layout_constraintLeft_toLeftOf="parent"  app:layout_constraintTop_toTopOf="parent" />  複製代碼

其餘效果你們在實踐能夠嘗試看看效果,建議點贊收藏本文,在使用不會能夠翻閱一下,效率事半功倍,省得從新浪費時間谷歌搜索。


對齊

上文XML佈局中,全部TextView的寬高是一致的,因此看着整整齊齊,當寬高不一致時,能夠進行對齊處理。我的試了一下app:flow_wrapMode="aligned"下的對齊,沒啥效果,估計有默認值了吧。看看flow_wrapMode屬性爲nonechain狀況吧。

Flow佈局添加如下屬性進行不一樣Align約束:

  • flow_verticalAlign 垂直方向對齊,取值有:topbottomcenterbaseline;
  • flow_horizontalAlign 水平方向對齊,取值有:startendcenter;

對齊方向通常與鏈的方向相反纔可生效,例如垂直鏈樣式,通常對齊View的左右邊和中間。

簡單舉個例子:垂直方向頂部對齊。

效果圖:

能夠看到EGF頂部對齊。

代碼:

<androidx.constraintlayout.helper.widget.Flow
 android:id="@+id/flow"  android:layout_width="match_parent"  android:layout_height="wrap_content"  android:layout_marginTop="50dp"  app:constraint_referenced_ids="tvA,tvB,tvC,tvD,tvE,tvF,tvG"  app:flow_maxElementsWrap="4"  app:flow_horizontalGap="30dp"  app:flow_verticalGap="30dp"  app:flow_wrapMode="chain"  app:flow_verticalAlign="top"  app:layout_constraintHorizontal_chainStyle="spread"  app:layout_constraintLeft_toLeftOf="parent"  app:layout_constraintTop_toTopOf="parent" /> 複製代碼

簡單的理解alignedchiannone的定製版,經過添加不一樣的屬性定製而成。因爲Flow是虛擬佈局,簡單理解就是約束助手,它並不會增長佈局層級,卻能夠像正常的佈局同樣使用。

其餘屬性

上文的XML的佈局沒有設置Flow對View的組織方式(水平or 垂直),能夠經過orientation屬性來設置水平horizontal和垂直vertical方向,例如改成垂直方向。


flow_wrapMode屬性爲alignedchian時,經過flow_maxElementsWrap屬性控制每行最大的子View數量。例如:flow_maxElementsWrap=3


flow_wrapMode屬性爲none時,A和G被擋住了,看不到。

要A或者G可見,經過設置flow_horizontalBias屬性,取值在0-1之間。前提條件是flow_horizontalStyle屬性爲packed纔會生效。

<androidx.constraintlayout.helper.widget.Flow
 android:id="@+id/flow"  android:orientation="horizontal"  android:layout_width="wrap_content"  android:layout_height="wrap_content"  app:constraint_referenced_ids="tvA,tvB,tvC,tvD,tvE,tvF,tvG"  app:flow_horizontalGap="30dp"  app:flow_verticalGap="30dp"  app:flow_wrapMode="none"  app:flow_horizontalStyle="packed"  app:flow_horizontalBias="0"  android:layout_marginTop="10dp"  app:layout_constraintRight_toRightOf="parent"  app:layout_constraintLeft_toLeftOf="parent"  app:layout_constraintTop_toTopOf="parent" />  複製代碼

效果圖: 設置flow_horizontalBias=1那麼G就能夠看到了。該屬性還有其餘相似ChainStyle的屬性w玩法,具體能夠實踐體驗。固然,也能夠在flow_wrapMode屬性爲其餘值生效。

經過不一樣的屬性能夠搭配不少不一樣的效果,再加上MotionLayout動畫,那就更炫酷了。

2、Layer 層佈局

Layer也是一個約束助手ConstraintHelper,相對Flow比較簡單,經常使用來增長背景,或者共同動畫。因爲ConstraintHelper自己繼承自View,跟咱們本身經過View在ConstraintLayout佈局中給多個View添加共同背景沒什麼區別,只是更方便而已。

一、添加背景

ImageViewTextView添加個共同背景:

效果:

代碼:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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="match_parent"   android:layout_height="match_parent">    <androidx.constraintlayout.helper.widget.Layer  android:id="@+id/layer"  android:layout_marginTop="50dp"  android:layout_width="wrap_content"  android:layout_height="wrap_content"  android:background="@color/colorPrimary"  app:constraint_referenced_ids="ivImage,tvName"  app:layout_constraintLeft_toLeftOf="@id/ivImage"  app:layout_constraintRight_toRightOf="parent"  android:padding="10dp"  app:layout_constraintTop_toTopOf="parent"  tools:ignore="MissingConstraints" />    <ImageView  android:id="@+id/ivImage"  android:layout_width="wrap_content"  android:layout_height="wrap_content"  android:layout_marginTop="10dp"  android:src="@mipmap/ic_launcher_round"  app:layout_constraintLeft_toLeftOf="parent"  app:layout_constraintRight_toRightOf="parent"  app:layout_constraintTop_toBottomOf="@id/layer" />   <TextView  android:id="@+id/tvName"  android:layout_width="wrap_content"  android:layout_height="wrap_content"  android:text="新小夢"  android:textColor="#FFFFFF"  android:paddingTop="5dp"  app:layout_constraintLeft_toLeftOf="@id/ivImage"  app:layout_constraintRight_toRightOf="@id/ivImage"  app:layout_constraintTop_toBottomOf="@id/ivImage" />  </androidx.constraintlayout.widget.ConstraintLayout> 複製代碼

二、共同動畫

經過屬性動畫給ImageView和TextView添加經過動畫效果。

效果:

代碼:

val animator = ValueAnimator.ofFloat( 0f, 360f)
animator.repeatMode=ValueAnimator.RESTART animator.duration=2000 animator.interpolator=LinearInterpolator() animator.repeatCount=ValueAnimator.INFINITE animator.addUpdateListener {  layer.rotation= it.animatedValue as Float } layer.setOnClickListener {  animator.start() } 複製代碼

對屬性動畫模糊的同窗能夠看看:Android屬性動畫,看完這篇夠用了吧

支持:旋轉、位移、縮放動畫。透明效果試了一下,是針對自身的,而不是約束的View。

3、自定義ConstraintHelper

FlowLayer都是ConstraintHelper的子類,當二者不知足需求時,能夠經過繼承ConstraintHelper來實現想要的約束效果。

在某乎APP有這麼個相似的動畫廣告:

那麼經過自定義ConstraintHelper來實現就很是簡單:

class AdHelper :
 ConstraintHelper {   constructor(context: Context?) : super(context)   constructor(context: Context?,attributeSet: AttributeSet):super(context,attributeSet)   constructor(context: Context?,attributeSet: AttributeSet,defStyleAttr: Int):super(context,attributeSet,defStyleAttr)    override fun updatePostLayout(container: ConstraintLayout?) {  super.updatePostLayout(container)  val views = getViews(container)  views.forEach {  val anim = ViewAnimationUtils.createCircularReveal(it, 0, 0, 0f, it.width.toFloat())  anim.duration = 5000  anim.start()  }  }  } 複製代碼

佈局引用AdHleper

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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="match_parent">   <com.example.constraint.AdHelper  android:layout_width="wrap_content"  android:layout_height="wrap_content"  app:constraint_referenced_ids="ivLogo"  app:layout_constraintLeft_toLeftOf="@id/ivLogo"  app:layout_constraintRight_toRightOf="@id/ivLogo"  app:layout_constraintTop_toTopOf="@id/ivLogo" />   <ImageView  android:id="@+id/ivLogo"  android:layout_width="match_parent"  android:layout_height="wrap_content"  android:layout_margin="20dp"  android:adjustViewBounds="true"  android:scaleType="fitXY"  android:src="@mipmap/ic_logo"  app:layout_constraintTop_toTopOf="parent" />  </androidx.constraintlayout.widget.ConstraintLayout> 複製代碼

4、ImageFilterButton

圓角圖片,圓形圖片怎麼實現?自定義View?經過ImageFilterButton,一個屬性就搞定;ImageFilterButto能作的還有更多。

看看如何實現圓角或圓形圖片:

原圖:

roundPercent屬性設置爲1,取值在0-1,由正方形向圓形過渡。

<androidx.constraintlayout.utils.widget.ImageFilterButton
 android:layout_width="wrap_content"  android:layout_height="wrap_content"  android:layout_marginTop="100dp"  app:roundPercent="1"  android:src="@mipmap/ic_launcher"  app:layout_constraintLeft_toLeftOf="parent"  app:layout_constraintRight_toRightOf="parent"  app:layout_constraintTop_toTopOf="parent" /> 複製代碼

效果:

也能夠經過設置round屬性來實現:

<androidx.constraintlayout.utils.widget.ImageFilterButton
 android:layout_width="wrap_content"  android:layout_height="wrap_content"  android:layout_marginTop="100dp"  android:src="@mipmap/ic_launcher"  app:layout_constraintLeft_toLeftOf="parent"  app:layout_constraintRight_toRightOf="parent"  app:layout_constraintTop_toTopOf="parent"  app:round="50dp" /> 複製代碼

其餘屬性:

altSrcsrc屬性是同樣的概念,altSrc提供的資源將會和src提供的資源經過crossfade屬性造成交叉淡化效果。默認狀況下,crossfade=0altSrc所引用的資源不可見,取值在0-1。 例如:

<androidx.constraintlayout.utils.widget.ImageFilterButton
 android:id="@+id/ivImage"  android:layout_width="wrap_content"  android:layout_height="wrap_content"  android:layout_marginTop="100dp"  android:src="@mipmap/ic_launcher"  app:altSrc="@mipmap/ic_sun"  app:crossfade="0.5"  app:layout_constraintLeft_toLeftOf="parent"  app:layout_constraintRight_toRightOf="parent"  app:layout_constraintTop_toTopOf="parent"  app:round="50dp" /> 複製代碼

crossfade=0.5時,效果:

crossfade=1時,效果:


接下來幾個屬性是對圖片進行調節:

warmth色溫:1=neutral天然, 2=warm暖色, 0.5=cold冷色

brightness亮度:0 = black暗色, 1 = original原始, 2 = twice as bright兩倍亮度;這個效果很差貼圖,你們自行驗證;

saturation飽和度:0 = grayscale灰色, 1 = original原始, 2 = hyper saturated超飽和

contrast對比:1 = unchanged原始, 0 = gray暗淡, 2 = high contrast高對比;

上面屬性的取值都是0、一、2,不過你們能夠取其餘值,效果也是不同的。 最後一個屬性overlay,表示不知道怎麼用,看不到沒效果,你們看看評論跟我說聲?

5、ImageFilterView

ImageFilterViewImageFilterButton的屬性如出一轍,只是它兩繼承的父類不同,一些操做也就不同。ImageFilterButton繼承自AppCompatImageButton,也就是ImageButtion。而ImageFilterView繼承自ImageView

6、MockView

還記得你家項目經理給你的UI原型圖麼?想不想回敬一下項目經理,是時候了~ MockView能簡單的幫助構建UI界面,經過對角線造成的矩形+標籤。例如:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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="match_parent">   <androidx.constraintlayout.utils.widget.MockView  android:id="@+id/first"  android:layout_width="100dp"  android:layout_height="100dp"  app:layout_constraintLeft_toLeftOf="parent"  app:layout_constraintTop_toTopOf="parent" />   <androidx.constraintlayout.utils.widget.MockView  android:id="@+id/second"  android:layout_width="100dp"  android:layout_height="100dp"  app:layout_constraintLeft_toRightOf="@id/first"  app:layout_constraintTop_toBottomOf="@id/first" />  </androidx.constraintlayout.widget.ConstraintLayout> 複製代碼

效果:

中間黑色顯示的是MockViewid。經過MockView能夠很好的構建一些UI思路。

7、MotionLayout

MitionLayou主要是用來實現動做動畫,能夠參考個人另外一篇文章:Android MotionLayout動畫:續寫ConstraintLayout新篇章

8、邊距問題的補充

ConstraintLayout實踐經驗的朋友應該知道margin設置負值在ConstraintLayout是沒有效果的。例以下面佈局:TextView B的layout_marginLeftlayout_marginTop屬性是不會生效的。

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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="match_parent">   <TextView  android:id="@+id/vA"  android:layout_width="100dp"  android:layout_height="100dp"  android:layout_marginLeft="30dp"  android:layout_marginTop="30dp"  android:background="@color/colorPrimary"  android:gravity="center"  android:text="A"  android:textColor="#FFFFFF"  android:textSize="20sp"  app:layout_constraintLeft_toLeftOf="parent"  app:layout_constraintTop_toTopOf="parent" />   <TextView  android:id="@+id/vB"  android:layout_width="100dp"  android:layout_height="100dp"  android:layout_marginLeft="-30dp"  android:layout_marginTop="-30dp"  android:background="@color/colorAccent"  android:gravity="center"  android:text="B"  android:textColor="#FFFFFF"  android:textSize="20sp"  app:layout_constraintLeft_toRightOf="@id/vA"  app:layout_constraintTop_toBottomOf="@id/vA" />  </androidx.constraintlayout.widget.ConstraintLayout> 複製代碼

效果: 能夠經過輕量級的Space來間接實現這種效果。

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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="match_parent">   <TextView  android:id="@+id/vA"  android:layout_width="100dp"  android:layout_height="100dp"  android:layout_marginLeft="30dp"  android:layout_marginTop="30dp"  android:background="@color/colorPrimary"  android:gravity="center"  android:text="A"  android:textColor="#FFFFFF"  android:textSize="20sp"  app:layout_constraintLeft_toLeftOf="parent"  app:layout_constraintTop_toTopOf="parent" />   <Space  android:id="@+id/space"  android:layout_width="0dp"  android:layout_height="0dp"  android:layout_marginRight="30dp"  android:layout_marginBottom="30dp"  app:layout_constraintBottom_toBottomOf="@id/vA"  app:layout_constraintRight_toRightOf="@id/vA" />   <TextView  android:id="@+id/vB"  android:layout_width="100dp"  android:layout_height="100dp"  android:layout_marginLeft="-30dp"  android:layout_marginTop="-30dp"  android:background="@color/colorAccent"  android:gravity="center"  android:text="B"  android:textColor="#FFFFFF"  android:textSize="20sp"  app:layout_constraintLeft_toRightOf="@id/space"  app:layout_constraintTop_toBottomOf="@id/space" />  </androidx.constraintlayout.widget.ConstraintLayout> 複製代碼

效果:

2.0還增長了ConstraintProperties類用於經過api(代碼)更新ConstraintLayout子視圖;其餘一些能夠參考官方文檔,估計也差很少了。

參考:

官方英文文檔

能讀到末尾的小夥伴都是很棒,耐力很好。若是本文對你有用,幫忙點個贊,推薦好文。

最後的最後,我的能力有限,有理解錯誤或者錯誤的地方,但願你們幫忙糾正,很是感謝。

歡迎star 歡迎點贊Github

本文使用 mdnice 排版

相關文章
相關標籤/搜索