ConstraintLayout 约束布局

参考
Android新特性介绍,ConstraintLayout完全解析
史上最全ConstraintLayout使用详解

概述:

约束布局,各个控件可以依据某些约束法则排列

位置功能:

相对位置

相对父控件位置

layout_constraintBottom_toBottomOf 这样的结构,可以记忆为
layout_constraintBottom 本控件位置指示 底部
toBottomOf 相对的控制位置指示 底部
app:layout_constraintBottom_toBottomOf="parent" 代表 本控件的底部位置和parent父控件的底部位置一致
一般而已,我们有Bottom,Top,Start,End 几个类型,其中Start,End和Left,Right是一致的,只是因为有些国家的left和right不是一致的,所以统一用Start,End代表。虽然Start,End和Left,Right是一致的,但是要注意Start,End是一对,Left,Right是一对,不可以混搭使用。

app:layout_constraintBottom_toBottomOf="parent" //本控件的底部位置和parent父控件的底部位置一致
app:layout_constraintEnd_toEndOf="parent"//本控件的结束位置和parent父控件的结束位置一致
app:layout_constraintStart_toStartOf="parent"//本控件的开始位置和parent父控件的开始位置一致
app:layout_constraintTop_toTopOf="parent"//本控件的头部位置和parent父控件的头部位置一致

下面代码,就是TextView的位置相对于父控件位置上下左右都是一致,因为四周都约束了,结果就是再中间

<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:context=".activity.MainActivity">
  <TextView
    android:id="@+id/imageView"
    android:text="TextView 1"
    android:background="@color/colorAccent"
    android:layout_width="200dp"
    android:layout_height="200dp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent" />
    </androidx.constraintlayout.widget.ConstraintLayout>
1.png

如果控件没有约束四边,就会有不同的效果,如下图,只约束了两边,控件的下方和父控件一致,控件的右边和父控件一致,就会导致控制整个变成右下


2.png

相对某个控件位置

和相对于父控件位置很相似,核心代码都是layout_constraintBottom_toBottomOf,只是后面变成="
@+id/viewId"
如下图,就是TextView2底部和TextView1的头部对齐,开始位置和结束位置和父控件对其

3.png

偏移量

当给控件增加了Top和Bottom的约束,就可以竖向产生偏移量,如果是增加了Start和End约束,就可以横向的偏移量。在可视化的属性里面,就是这里的滑动按钮


4.png

如果是在代码里面,就是layout_constraintVertical_bias和layout_constraintHorizontal_bias,后面参数是百分比


5.png

控件大小

在ConstraintLayout里面,控件大小总共有三种方式

Fixed 固定大小

layout_width和layout_height 里面填写固定的大小就可以,在可视化的属性里面(Attributes)看到的样子就是这样


6.png

包裹大小 wrap_content

layout_width和layout_height 里面都是wrap_content,就是跟随控件里面的内容自动变化控件大小,在可视化的属性里面(Attributes)看到的样子就是这样


7.png

匹配约束 Match Constraints

就是根据空间约束的规则来分配剩余空间,有三种模式,分别是spread,percent,wrap,通过layout_constraintHeight_default和layout_constraintWidth_default字段来标注是什么属性,一般是spread。从可视化效果来看,就是Match Constraints,如下图,从代码来看就是layout-wight和layout-height都是0,自动是Match Constraints模式。


8.png

spread 默认

有点类似于match parent,不过match parent是相对于父控件,而Match Constraints是相对于约束控件来说,从可视化的属性里面(Attributes)来看,TextView2开始和结束是相对于父控件而已,所以当wight是Match Constraints的时候,宽会填满整个父控件,而高虽然是相对于父控件,底部是相对于TextView1的top,当高变成Match Constraints的时候,会占据父控件Top到TextView1的top,效果如下图


9.png

而此时,如果看代码其实TextView2的layout-wight和layout-height都是0,就自动是Match Constraints,而且是layout_constraintHeight_default和layout_constraintWidth_default加不加效果一样


10.png

percent:按照父布局百分比设置

控件的尺寸是按照父控件的尺寸的百分比居中限制,需要和layout_constraintHeight_percent|layout_constraintWidth_percent配合使用,如图,TextView是父控件就是ConstraintLayout,100%应该是ConstraintLayout一样大小。代码中layout_constraintHeight_percent|layout_constraintWidth_percent都是0.5,按照ConstraintLayout的50%显示,并且居中


11.png

wrap:匹配内容大小但是不超过约束的限制

就是能按照内容大小去匹配,并且不能超过约束的配置,主要是对比layout_width = "wrap_content"|layout_height = "wrap_content"来的。
如下面代码,tv1和tv2都是一样的大小,包裹1234567789的大小,然后又给了另外一层限制,都是距离左右边距是200dp,看tv1的效果,早就突破了这长度,优先了内容的展示1234567789,实际上距离左右边距没有200dp。(tv1如果想要和tv2一样的效果,可以通过代码app:layout_constrainedWidth="true"|app:layout_constrainedHeight="true"设置)
而tv2,优先保证了保持左右边距是200dp,内容展示不全


12.png
<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">

    <TextView
        android:id="@+id/tv1"
        android:layout_width="wrap_content"
        android:layout_marginStart="150dp"
        android:layout_marginEnd="150dp"
        android:layout_height="wrap_content"
        android:background="@color/colorPrimary"
        android:text="1234567789"
        android:textSize="40sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0" />

    <TextView
        android:id="@+id/tv2"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:layout_marginStart="150dp"
        android:layout_marginEnd="150dp"
        app:layout_constraintHeight_default="wrap"
        app:layout_constraintWidth_default="wrap"
        app:layout_constraintHeight_percent="0.5"
        app:layout_constraintWidth_percent="0.5"
        android:background="@color/colorAccent"
        android:text="1234567789"
        android:textSize="40sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

比例宽高

app:layout_constraintDimensionRatio="1:1"|app:layout_constraintDimensionRatio="0.5"可以设置款高比例,但是需要至少款高有一个为0。两种设置方式,1:1代表宽度和高度之间的比率,也可以用0.5等浮点型表示

<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">
    <TextView
        android:id="@+id/tv2"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintDimensionRatio="1:3"
        app:layout_constraintHeight_default="wrap"
        app:layout_constraintWidth_default="wrap"
        android:background="@color/colorAccent"
        android:text="1234567789"
        android:textSize="40sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

效果展示是


13.png

辅助线 Guidelines

自身设置

可以建立一条辅助线,将控件用于辅助线约束,可以在可视化的界面直接拖拽,通过点击下面小三角来改变约束位置和位置数值


14.gif

通过代码来看,orientation控制是横还是竖
layout_constraintGuide_begin控制位置,如果是距离开始是位置是layout_constraintGuide_begin,如果是距离结束的位置是layout_constraintGuide_end;如果是变成百分比,是layout_constraintGuide_percent="0.5"

<androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_begin="206dp" />

其余控件相对位置

就是直接通过layout_constraintBottom_toBottomOf等约束,这次是textView1的结束和guideline1对齐,textView2的开始和guideline1对齐,也就是textView1和textView2分别在guideline1两边

    <TextView
        android:id="@+id/textView1"
        android:layout_width="100dp"
        android:layout_height="200dp"
        android:background="@color/colorAccent"
        android:text="TextView 1"
        android:textSize="40sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintEnd_toEndOf="@+id/guideline1"
        />

    <TextView
        android:id="@+id/textView2"
        android:layout_width="100dp"
        android:layout_height="200dp"
        android:background="@color/colorPrimary"
        android:text="TextView2"
        android:textSize="40sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="@+id/guideline1"
        app:layout_constraintTop_toTopOf="parent" />

    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/guideline1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.5" />
15.png

自动化约束

自动连接 Autoconnect

当开启了Autoconnect的时候,也就是可视化页面上面磁铁的按钮,一般情况下会关闭,拖动控件到合适的位置,会自动添加约束。


16.gif

推断约束 Infer Constraints

我们可以把控件拖到各自位置,按照想要的布局排好,然后点击Infer Constraints按钮,也就是发光棒的样子的按钮,会自动推断当前页面上控件布局,给所有控件添加约束


17.gif

基线对齐

可以通过layout_constraintBaseline_toBaselineOf让两个控件几线对齐,比如,我们又text1和text2,text2的开始位置和text1的结束位置对齐,此时,我们加上layout_constraintBaseline_toBaselineOf,可以让text1和text2的基线对齐


18.gif

角度约束

可以约束某个控件相对于某个控件的角度,比如text2在text1的100dp外90°的方向。0°是正上方,顺时针旋转,所以text2在text1的右边。


19.png

代码主要是这个三个

app:layout_constraintCircle="@id/tv1"  //目标控件的id
app:layout_constraintCircleAngle="90"  //对于目标控件的角度,负数无效
app:layout_constraintCircleRadius="100dp"  //到目标控件中间的距离
<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">

    <TextView
        android:id="@+id/tv1"
        android:background="@color/colorPrimary"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Text1"
        android:textSize="40sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
    <TextView
        android:id="@+id/tv2"
        android:text="Text2"
        android:textSize="20sp"
        android:background="@color/colorAccent"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintCircle="@id/tv1"
        app:layout_constraintCircleAngle="90"
        app:layout_constraintCircleRadius="100dp"/>

</androidx.constraintlayout.widget.ConstraintLayout>

控件内边距、外边距、GONE Margin

内外边距

这个和别的控件一模一样,主要是通过layout_margin和padding来控制的

GONE Margin

这个属性比较奇怪,当依赖的目标是gone的时候,本目标的GONE Margin才会生效,而且要注意方向,比如设置了layout_constraintTop_toTopOf方向约束,那么layout_goneMarginTop才会生效
如图,依赖的控件没有gone的时候,goneMargin没有效果


21.png

等控件tv1隐藏


22.png

Barrier(屏障)

这个和基线一样,是个不显示在屏膜上的,可以对多个控件进行一个自动合适的适配
比如下图,ABC三个控件,我希望B是放在A和C的右侧,但是A和C里面的文字不定的,不知道哪个长一点,如果我设定B是在A的右侧,当C过长的时候,可能就覆盖了B,虽然可以使用一个控件包裹AC来完成,但是多了一层,可以使用Barrier

23.png

Barrier是一个控件,控件并不显示在页面上, 只是为了约束别的控件,主要有两个属性


<!--  用于控制Barrier相对于给定的View的位置  -->
app:barrierDirection="top|bottom|left|right|start|end"  
 
<!--  取值是要依赖的控件的id,Barrier将会使用ids中最大的一个的宽/高作为自己的位置  -->
app:constraint_referenced_ids="id,id"

比如如下代码,需要依赖的控件是tvA,tvB,位于这些控件的end。会根据tvA,tvB自适应,如果tvA比较长,就是tvA后面,tvB比较长,就是tvB后面。

<androidx.constraintlayout.widget.Barrier
        android:id="@+id/barrier"
        app:constraint_referenced_ids="tvA,tvC"
        app:barrierDirection="end"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

效果图如下


24.gif

可以通过把控件B放在Barrier右侧来实现我们要的功能


25.gif

Group(组)

就是可以把控件加入一个组,对一组控件进行显示或者隐藏操作,同样不显示在页面上,主要就是通过constraint_referenced_ids="id,id……"将控件Id添加进去

<androidx.constraintlayout.widget.Group
        android:visibility="gone"
        app:constraint_referenced_ids="tvA,tvB,tvC"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

Placeholder(占位符)

可以在页面上提前部署一个占位符的控件,通过调用这个占位符的setContent(int id),可以将别的控件移动到占位符控件的位置

<androidx.constraintlayout.widget.Placeholder
        android:id="@+id/place"
        android:layout_width="50dp"
        android:layout_height="50dp"
        app:layout_constraintEnd_toEndOf="parent" />

Chains(链)

把一系列控件首位相连进行排列,会自动形成链,默认是spread,均分剩余空间,有水平链或者垂直链,代码如下

<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">

    <TextView
        android:id="@+id/tvA"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@color/colorAccent"
        android:text="A"
        android:textSize="40sp"
        app:layout_constraintEnd_toStartOf="@id/tvB"
        app:layout_constraintStart_toStartOf="parent" />
    <TextView
        android:id="@+id/tvB"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@color/colorAccent"
        android:text="B"
        android:textSize="40sp"
        app:layout_constraintEnd_toStartOf="@id/tvC"
        app:layout_constraintStart_toEndOf="@id/tvA" />
    <TextView
        android:id="@+id/tvC"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@color/colorAccent"
        android:text="C"
        android:textSize="40sp"
        app:layout_constraintStart_toEndOf="@id/tvB"
        app:layout_constraintEnd_toEndOf="parent"/>

</androidx.constraintlayout.widget.ConstraintLayout>

效果呈现就是三个控件均匀分布


20.png

layout_constraintHorizontal_chainStyle和layout_constraintVertical_chainStyle分别对水平和垂直链设置模式,模式可选的值有:spread、packed、spread_inside。
spread:就是默认的均分
packed:所有控件紧贴在一起


27.png

spread_inside:两侧的控件贴近两边,剩下的控件均分


28.png

链还可以设置权重,通过layout_constraintHorizontal_weight|layout_constraintVertical_weight来设置
代码如下

<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">

    <TextView
        android:id="@+id/tvA"
        app:layout_constraintHorizontal_weight="1"
        app:layout_constraintHorizontal_chainStyle="packed"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:background="@color/colorAccent"
        android:text="A"
        android:textSize="40sp"
        app:layout_constraintEnd_toStartOf="@id/tvB"
        app:layout_constraintStart_toStartOf="parent" />
    <TextView
        android:id="@+id/tvB"
        app:layout_constraintHorizontal_weight="2"
        app:layout_constraintHorizontal_chainStyle="packed"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:background="@color/colorPrimary"
        android:text="B"
        android:textSize="40sp"
        app:layout_constraintEnd_toStartOf="@id/tvC"
        app:layout_constraintStart_toEndOf="@id/tvA" />
    <TextView
        android:id="@+id/tvC"
        app:layout_constraintHorizontal_weight="1"
        app:layout_constraintHorizontal_chainStyle="packed"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:background="@color/colorAccent"
        android:text="C"
        android:textSize="40sp"
        app:layout_constraintStart_toEndOf="@id/tvB"
        app:layout_constraintEnd_toStartOf="@id/tvD"/>
    <TextView
        android:id="@+id/tvD"
        app:layout_constraintHorizontal_weight="2"
        app:layout_constraintHorizontal_chainStyle="packed"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:background="@color/colorPrimary"
        android:text="D"
        android:textSize="40sp"
        app:layout_constraintStart_toEndOf="@id/tvC"
        app:layout_constraintEnd_toEndOf="parent"/>

</androidx.constraintlayout.widget.ConstraintLayout>

效果图


29.png

Flow 流式布局

一般链约束需要控件首尾相连,但是可以使用Flow,会默认将所有控件约束起来。Flow本身不展示在页面上,也是一种虚拟布局。需要的constraintlayout 2.0才有,如果没有,需要去build.gradle看一下constraintlayout的版本
通过app:constraint_referenced_ids="id1,id2,id3……"等设置要进行布局的控件id
通过app:flow_wrapMode=""来设置排列方式,none是默认,就是连续排列,超出的部分不可见。chian是超出部分自动换行,同行的会平分。aligned是超出部分自动换行,同行会一边靠齐。
通过orientation属性,决定是垂直还是水平。
常规使用如下,TextView的id就是A,B,C,D,E,文本也是,通过Flow的app:constraint_referenced_ids将id添加,app:flow_wrapMode可以写也可以不写,默认就是none。


30.png

排列方式:app:flow_wrapMode

none:默认属性,就是连续平分空间的排列,如果超出的部分则不可见,代码如下

<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">
    <TextView
        android:id="@+id/A"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:background="@color/colorPrimaryDark"
        android:gravity="center"
        android:text="A"
        android:textColor="@color/colorWhite"
        android:textSize="25sp"
        android:textStyle="bold" />

    <TextView
        android:id="@+id/B"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:background="@color/colorPrimaryDark"
        android:gravity="center"
        android:text="B"
        android:textColor="@color/colorWhite"
        android:textSize="25sp"
        android:textStyle="bold" />

    <TextView
        android:id="@+id/C"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:background="@color/colorPrimaryDark"
        android:gravity="center"
        android:text="C"
        android:textColor="@color/colorWhite"
        android:textSize="25sp"
        android:textStyle="bold" />

    <TextView
        android:id="@+id/D"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:background="@color/colorPrimaryDark"
        android:gravity="center"
        android:text="D"
        android:textColor="@color/colorWhite"
        android:textSize="25sp"
        android:textStyle="bold" />

    <TextView
        android:id="@+id/E"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:background="@color/colorPrimaryDark"
        android:gravity="center"
        android:text="E"
        android:textColor="@color/colorWhite"
        android:textSize="25sp"
        android:textStyle="bold" />
    <TextView
        android:id="@+id/F"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:background="@color/colorPrimaryDark"
        android:gravity="center"
        android:text="F"
        android:textColor="@color/colorWhite"
        android:textSize="25sp"
        android:textStyle="bold" />
    <TextView
        android:id="@+id/G"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:background="@color/colorPrimaryDark"
        android:gravity="center"
        android:text="G"
        android:textColor="@color/colorWhite"
        android:textSize="25sp"
        android:textStyle="bold" />
    <TextView
        android:id="@+id/H"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:background="@color/colorPrimaryDark"
        android:gravity="center"
        android:text="H"
        android:textColor="@color/colorWhite"
        android:textSize="25sp"
        android:textStyle="bold" />

    <androidx.constraintlayout.helper.widget.Flow
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:flow_wrapMode="none"
        app:constraint_referenced_ids="A,B,C,D,E,F,G,H" />


</androidx.constraintlayout.widget.ConstraintLayout>

效果图如下


31.png

chain:超出部分自动换行,并且所有控件等分

<androidx.constraintlayout.helper.widget.Flow
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:flow_wrapMode="chain"
        app:constraint_referenced_ids="A,B,C,D,E,F,G,H" />

效果图


32.png

aligned:超出部分也自动换行,但是不是等分而是靠一边显示

<androidx.constraintlayout.helper.widget.Flow
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:flow_wrapMode="aligned"
        app:constraint_referenced_ids="A,B,C,D,E,F,G,H" />

效果图


33.png

排列方向:orientation

通过orientation为horizontal|vertical可以控制是水平还是垂直,orientation为vertical是垂直,默认是水平

<androidx.constraintlayout.helper.widget.Flow
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:constraint_referenced_ids="A,B,C,D,E,F,G,H" />

效果图


34.png

间隔距离:flow_horizontalGap|flow_verticalGap

通过flow_horizontalGap|flow_verticalGap可以设置各个控件水平或者垂直的间隔距离,要注意一下是水平还是垂直方向的排列,下面代码,是垂直排列,而且间隔是20dp,可以看到控件不在紧紧贴在一起了。

<androidx.constraintlayout.helper.widget.Flow
        app:flow_verticalGap="20dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:constraint_referenced_ids="A,B,C,D,E,F,G,H" />

效果图


35.png

每条链配置

当flow_wrapMode的值是chian或aligned时,通过flow_horizontalStyle等属性,可以对每条链或者所有链进行配置,有三种模式,和链一样
spread:均分排列


36.png

packed:贴在一起居中


37.png

spread_inside:紧贴两边,其余的均分
38.png

app:flow_horizontalStyle="packed|spread|spread_inside" 所有水平链的配置

app:flow_verticalStyle="packed|spread|spread_inside" 所有垂直链的配置
app:flow_firstHorizontalStyle="packed|spread|spread_inside" 第一条水平链的配置,其他条不生效
app:flow_firstVerticalStyle="packed|spread|spread_inside" 第一条垂直链的配置,其他条不生效
app:flow_lastHorizontalStyle="packed|spread|spread_inside" 最后一条水平链的配置,其他条不生效
app:flow_lastVerticalStyle="packed|spread|spread_inside" 最后一条垂直链的配置,其他条不生效

对齐约束

控件在Flow里面,默认是居中对齐的,但是控件大小不一样,可以设置不同的对齐方式。通过flow_verticalAlign|flow_horizontalAlign来控制。如果是水平链是通过flow_verticalAlign控制,如果是垂直链是通过flow_horizontalAlign控制。下面都是以水平链做展示
top:头部对齐

<androidx.constraintlayout.helper.widget.Flow
        app:flow_horizontalGap="10dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:constraint_referenced_ids="A,B,C,D,E,F"
        app:flow_verticalAlign="top" />
39.png

bottom:底部对齐


40.png

center:居中对齐


41.png

baseline:基线对齐
要注意一下,当其中一个TextView里面的文字F不在中间的时候,是根据F的基线对齐的,如果是都是在中间,和center效果一样
42.png

数量约束 flow_maxElementsWrap

可以通过flow_maxElementsWrap = "数量值"来约束一条链最大的数量,需要配合flow_wrapMode属性使用,如下代码,flow_maxElementsWrap约束了一条链最多4个,配合了flow_wrapMode是多的靠一边排列,如是none不行,显示不出效果

<androidx.constraintlayout.helper.widget.Flow
        app:flow_horizontalGap="10dp"
        app:flow_wrapMode="aligned"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:constraint_referenced_ids="A,B,C,D,E,F"
        app:flow_verticalAlign="center"
        app:flow_maxElementsWrap="4"/>

效果图


43.png

Layer层布局

本质上而已,这个控件是把可以把别的控件加载在它上面,变成一层一层的,它没办法自己设置位置,设置大小,跟着它上面的层自己调整,它不是虚拟的控件,可以被看见,如果它是最上面一层,会覆盖所有的层。主要也是通过constraint_referenced_ids添加别的层的id。
下面代码,虽然写了Layer的位置和大小,但是全部失效,是跟着A和B控件来的,颜色没有失效,可以看到。Layer是在A和B前面写的,所有在最底层,如果在A和B后面就会覆盖掉A和B。
constraint_referenced_ids的顺序没有任何影响,Layer的顺序就是写控件的顺序。

<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:background="@color/colorAccent"
        android:layout_width="300dp"
        android:layout_height="300dp"
        app:constraint_referenced_ids="A,B"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
    <TextView
        android:id="@+id/A"
        android:layout_width="60dp"
        android:layout_height="90dp"
        android:background="@color/colorPrimaryDark"
        android:gravity="center"
        android:text="A"
        android:textColor="@color/colorWhite"
        android:textSize="25sp"
        android:textStyle="bold" />

    <TextView
        android:id="@+id/B"
        app:layout_constraintEnd_toEndOf="parent"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:background="@color/colorPrimaryDark"
        android:gravity="center"
        android:text="B"
        android:textColor="@color/colorWhite"
        android:textSize="25sp"
        android:textStyle="bold" />
</androidx.constraintlayout.widget.ConstraintLayout>

效果图


44.png

ImageFilterButton & ImageFilterView

这两个控件有点像ImageButton和ImageView的关系,有两个特殊作用,再ImageFilterButton|ImageFilterView中都可以。下面主要用ImageFilterView测试

圆角

可以通过app:roundPercent设置圆角的比例,app:round设置大小

<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.utils.widget.ImageFilterView
        app:roundPercent="0.5"
        app:round="50dp"
        android:background="@color/colorAccent"
        android:layout_width="100dp"
        android:layout_height="100dp"/>
    
</androidx.constraintlayout.widget.ConstraintLayout>

效果图


45.png

多层图片

src可以设置第一层图片,altSrc可以再设置一层图片,再src上面,默认是透明的,需要通过crossfade属性来设置,0-1直接的值
效果图如下,第一层图片是Android的图标,第二层图片破了的图片,crossfade是0.5


46.png

其余属性调整

warmth属性可以用来调节色温
brightness属性用来调节亮度
saturation属性用来调节饱和度
contrast属性用来调节对比度
这几个属性涉及到美术了,目前不太了解

MockView 原型图软件

这个控件,说可以来画原型图,id就是控件里面的文字,使用很简单

<androidx.constraintlayout.utils.widget.MockView
        android:id="@+id/MockView"
        android:layout_width="100dp"
        android:layout_height="100dp"/>

效果如下


47.png
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,569评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,499评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,271评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,087评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,474评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,670评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,911评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,636评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,397评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,607评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,093评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,418评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,074评论 3 237
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,092评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,865评论 0 196
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,726评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,627评论 2 270

推荐阅读更多精彩内容