这是我参与更文挑战的第2天,活动详情查看: 更文挑战
ConstraintLayout 布局的用法
一、基础用法
位置控制
app:layout_constraintTop_toTopOf="" 我的顶部和谁的顶部对齐
app:layout_constraintBottom_toBottomOf="" 我的底部和谁的底部对齐
app:layout_constraintLeft_toLeftOf="" 我的左边和谁的左边对齐
app:layout_constraintRight_toRightOf="" 我的右边和谁的右边对齐
app:layout_constraintStart_toStartOf="" 我的开始位置和谁的开始位置对齐
app:layout_constraintEnd_toEndOf="" 我的结束位置和谁的结束位置对齐
app:layout_constraintTop_toBottomOf="" 我的顶部位置在谁的底部位置
app:layout_constraintStart_toEndOf="" 我的开始位置在谁的结束为止
尺寸限制
android:minWidth="" 设置view的最小宽度
android:minHeight="" 设置view的最小高度
android:maxWidth="" 设置view的最大宽度
android:maxHeight="" 设置view的最大高度
二、0dp (app:layout_constraintWidth_default="spread|percent|wrap")
layout_constraintWidth_default和layout_constraintHeight_default,其取值有spread|percent|wrap,这几个值取值不同,产生的效果也不一样
1:spread 占用所有的符合约束的空间
spread是默认值,所以可以不写 app:layout_constraintWidth_default="spread"
<?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"
android:background="#DAF3FE">
<TextView
android:id="@+id/A"
android:layout_width="0dp"
android:layout_height="60dp"
android:layout_marginStart="50dp"
android:layout_marginTop="50dp"
android:layout_marginEnd="50dp"
android:background="@drawable/tv_bg"
android:gravity="center"
android:text="A"
android:textColor="@color/black"
android:textSize="25sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_default="spread" />
</androidx.constraintlayout.widget.ConstraintLayout>
2:percent:占据空间百分比,按照父布局的百分比设置
layout_constraintWidth_default
layout_constraintWidth_percent
<?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"
android:background="#DAF3FE">
<TextView
android:id="@+id/A"
android:layout_width="0dp"
android:layout_height="100dp"
android:gravity="center"
android:text="AA"
android:textColor="@color/black"
android:textSize="25sp"
android:textStyle="bold"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_default="percent"
app:layout_constraintWidth_percent="0.5" />
</androidx.constraintlayout.widget.ConstraintLayout>
3:wrap:匹配内容大小但不超过约束限制
第一个TextView虽然设置了左右边距,但是还是被内容撑过去了。第二个TextView设置的边距生效(k宽度需设置为0dp)
<?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"
android:background="#DAF3FE">
<TextView
android:id="@+id/A"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="100dp"
android:gravity="center"
android:text="AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
android:textColor="@color/black"
android:textSize="25sp"
android:textStyle="bold"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<TextView
android:id="@+id/B"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="100dp"
android:gravity="center"
android:text="AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
android:textColor="@color/black"
android:textSize="25sp"
android:textStyle="bold"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/A"
app:layout_constraintWidth_default="wrap"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
4:填满剩余空间
android:layout_width="wrap_content"
android:layout_height="0dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
三、Chains(链 app:layout_constraintHorizontal_chainStyle="spread|spread_inside|packed")
Chains(链),它可以将多个控件在水平或者垂直方向,形成一条链,用于平衡这些控件的位置
属性:layout_constraintHorizontal_chainStyle和layout_constraintVertical_chainStyle
值:spread、spread_inside、packed
1:spread 均分剩余空间
2:spread_inside 两侧的控件贴两边,剩下的控件均分剩余空间
app:layout_constraintHorizontal_chainStyle="spread_inside"
3:packed 控件紧贴一起居中
app:layout_constraintHorizontal_chainStyle="packed"
<?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"
android:background="#DAF3FE">
<TextView
android:id="@+id/A"
android:layout_width="80dp"
android:layout_height="80dp"
android:gravity="center"
android:text="A"
android:textColor="@color/black"
android:textSize="25sp"
android:textStyle="bold"
app:layout_constraintEnd_toStartOf="@id/B"
app:layout_constraintHorizontal_chainStyle="spread"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/B"
android:layout_width="80dp"
android:layout_height="80dp"
android:gravity="center"
android:text="B"
android:textColor="@color/black"
android:textSize="25sp"
android:textStyle="bold"
app:layout_constraintEnd_toStartOf="@id/C"
app:layout_constraintStart_toEndOf="@id/A"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/C"
android:layout_width="80dp"
android:layout_height="80dp"
android:gravity="center"
android:text="C"
android:textColor="@color/black"
android:textSize="25sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/B"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
四、Flow(流式布局)
<androidx.constraintlayout.helper.widget.Flow
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:constraint_referenced_ids="A,B,C,D,E"
app:flow_wrapMode="chain"
app:layout_constraintTop_toTopOf="parent" />
1:链约束(app:flow_wrapMode="none|chian|aligned")
1.1:none 默认值,所有引用的View形成一条链,水平居中,超出屏幕两侧的View不可见
1.2:chain 超出部分自动换行居中,同行的View平分宽度
1.3:aligned 超出部分自动换行靠左,同行的View平分宽度
当flow_wrapMode的值是chian或aligned时,我们还可以针对不同的链进行配置
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" 最后一条垂直链的配置,其他条不生效
2:对齐约束(app:flow_verticalAlign="top|bottom|center|baseline")
<!-- top:顶对齐、bottom:底对齐、center:中心对齐、baseline:基线对齐 -->
(app:flow_verticalAlign="top|bottom|center|baseline"))
<!-- start:开始对齐、end:结尾对齐、center:中心对齐 -->
app:flow_horizontalAlign="start|end|center"
2.1:top对齐
2.2:bottom对齐
2.3:center对齐
3:设置权重(app:layout_constraintHorizontal_weight="2")
layout_constraintHorizontal_weight和layout_constraintVertical_weight
<?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"
android:background="#DAF3FE">
<TextView
android:id="@+id/A"
android:layout_width="60dp"
android:layout_height="100dp"
android:gravity="center"
android:text="A"
android:textColor="@color/black"
android:textSize="25sp"
android:textStyle="bold" />
<TextView
android:id="@+id/B"
android:layout_width="60dp"
android:layout_height="60dp"
android:gravity="center"
android:text="B"
android:textColor="@color/black"
android:textSize="25sp"
android:textStyle="bold" />
<TextView
android:id="@+id/C"
android:layout_width="60dp"
android:layout_height="60dp"
android:gravity="center"
android:text="C"
android:textColor="@color/black"
android:textSize="25sp"
android:textStyle="bold" />
<TextView
android:id="@+id/D"
android:layout_width="60dp"
android:layout_height="60dp"
android:gravity="center"
android:text="D"
android:textColor="@color/black"
android:textSize="25sp"
android:textStyle="bold" />
<TextView
android:id="@+id/E"
android:layout_width="60dp"
android:layout_height="160dp"
android:gravity="center"
android:text="E"
android:textColor="@color/black"
android:textSize="25sp"
android:textStyle="bold" />
<androidx.constraintlayout.helper.widget.Flow
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:constraint_referenced_ids="A,B,C,D,E"
app:flow_verticalAlign="top"
app:flow_wrapMode="chain"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
五、基线对齐(app:layout_constraintBaseline_toBaselineOf="@id/tv1")
通过layout_constraintBaseline_toBaselineOf让两个不同大小的文案基线对齐
<?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"
android:background="#DAF3FE">
<TextView
android:id="@+id/tv1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="100"
android:textColor="@color/black"
android:textSize="50sp"
android:textStyle="bold"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="元"
android:textColor="@color/black"
android:textSize="20sp"
app:layout_constraintBaseline_toBaselineOf="@id/tv1"
app:layout_constraintLeft_toRightOf="@id/tv1" />
</androidx.constraintlayout.widget.ConstraintLayout>
六、百分比偏移(app:layout_constraintHorizontal_bias="0.2")
layout_constraintHorizontal_bias、layout_constraintVertical_bias 设置百分比偏移
app:layout_constraintHorizontal_bias="" 水平偏移 取值范围是0-1的小数
app:layout_constraintVertical_bias="" 垂直偏移 取值范围是0-1的小数
<?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"
android:background="#DAF3FE">
<TextView
android:layout_width="100dp"
android:layout_height="60dp"
android:background="@drawable/tv_bg"
android:gravity="center"
android:text="Text"
android:textColor="@color/black"
android:textSize="25sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintHorizontal_bias="0.3"
app:layout_constraintVertical_bias="0.6" />
</androidx.constraintlayout.widget.ConstraintLayout>
七、GONE Margin(app:layout_goneMarginXxx="0dp")
比如控件B在控件A的右侧(B控件依赖A控件显示),B设置了Gone Margin属性,当A显示时B的GONE Margin不会生效,当A隐藏时,B的GONE Margin才会生效
app:layout_goneMarginBottom="0dp"
app:layout_goneMarginEnd="0dp"
app:layout_goneMarginLeft="0dp"
app:layout_goneMarginRight="0dp"
app:layout_goneMarginStart="0dp"
app:layout_goneMarginTop="0dp"
八、比例宽高(app:layout_constraintDimensionRatio="1:1")
app:layout_constraintDimensionRatio
ConstraintLayout中可以对宽高设置比例,前提是至少有一个约束维度设置为0dp,这样比例才会生效,该属性可使用两种设置:
-
浮点值,表示宽度和高度之间的比率
-
宽度:高度,表示宽度和高度之间形式的比率
<?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"
android:background="#DAF3FE">
<TextView
android:id="@+id/B"
android:layout_width="0dp"
android:layout_height="200dp"
android:gravity="center"
android:text="A"
android:textColor="@color/black"
android:textSize="25sp"
android:textStyle="bold"
app:layout_constraintDimensionRatio="1:1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
九、Guideline(参考线 androidx.constraintlayout.widget.Guideline)
Guideline也可以用来做一些百分比分割之类的需求,有着很好的屏幕适配效果,Guideline有水平和垂直方向之分,位置可以使用针对父级的百分比或者针对父级位置的距离
android:orientation="horizontal|vertical" 辅助线的对齐方式
app:layout_constraintGuide_percent="0-1" 距离父级宽度或高度的百分比(小数形式)
app:layout_constraintGuide_begin="" 距离父级起始位置的距离(左侧或顶部)
app:layout_constraintGuide_end="" 距离父级结束位置的距离(右侧或底部)
<?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"
android:background="#DAF3FE"
tools:ignore="HardcodedText">
<androidx.constraintlayout.widget.Guideline
android:id="@+id/Guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.2" />
<TextView
android:id="@+id/A"
android:layout_width="100dp"
android:layout_height="60dp"
android:gravity="center"
android:text="A"
android:textColor="@color/black"
android:textSize="25sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/Guideline" />
</androidx.constraintlayout.widget.ConstraintLayout>
十、Barrier(屏障 app:barrierDirection="top|bottom|left|right|start|end" )
AB两个控件上下排布,但是长短不确定,C控件需要位于AB两个内容中最长的右侧,此时可以使用屏障来进行辅助布局
<!-- 用于控制Barrier相对于给定的View的位置 -->
app:barrierDirection="top|bottom|left|right|start|end"
<!-- 取值是要依赖的控件的id,Barrier将会使用ids中最大的一个的宽/高作为自己的位置 -->
app:constraint_referenced_ids="id,id"
<?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:background="#DAF3FE"
android:layout_height="match_parent">
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:text="1111111111"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
android:text="222222"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView1" />
<androidx.constraintlayout.widget.Barrier
android:id="@+id/barrier7"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="end"
app:constraint_referenced_ids="textView2,textView1" />
<TextView
android:id="@+id/textView3"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:text="3333333333333333333"
app:layout_constraintStart_toEndOf="@+id/barrier7"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
十一、Group(组 app:constraint_referenced_ids="A,B,C")
Group可以控制关联的id控件显示或者隐藏
app:constraint_referenced_ids="id,id" 加入组的控件id
<androidx.constraintlayout.widget.Group
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="visible"
app:constraint_referenced_ids="A,B,C" />
十二、Placeholder(占位符 androidx.constraintlayout.widget.Placeholder)
它可以在布局中占好位置,通过app:content=""属性,或者动态调用setContent()设置内容,来让某个控件移动到此占位符中
<?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"
android:background="#DAF3FE">
<TextView
android:id="@+id/A"
android:layout_width="100dp"
android:layout_height="60dp"
android:gravity="center"
android:text="A"
android:textColor="@color/black"
android:textSize="25sp"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.constraintlayout.widget.Placeholder
android:layout_width="100dp"
android:layout_height="60dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:content="@+id/A"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
十三、角度约束(app:layout_constraintCircleAngle="45")
<?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"
android:background="#DAF3FE">
<ImageView
android:id="@+id/android"
android:layout_width="100dp"
android:layout_height="100dp"
android:src="@mipmap/ic_launcher"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/jetpack"
android:layout_width="60dp"
android:layout_height="60dp"
android:src="@mipmap/ic_launcher_round"
app:layout_constraintCircle="@+id/android"
app:layout_constraintCircleAngle="45"
app:layout_constraintCircleRadius="70dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
十四、ImageFilterButton & ImageFilterView
它们的大致作用有两部分,一是可以用来做圆角图片,二是可以叠加图片资源进行混合过滤,下面一一展示
1:app:roundPercent设置圆角
<?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"
android:background="#DAF3FE">
<androidx.constraintlayout.utils.widget.ImageFilterView
android:layout_width="100dp"
android:layout_height="100dp"
android:src="@mipmap/ic_test"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:roundPercent="0.5" />
</androidx.constraintlayout.widget.ConstraintLayout>
2:app:crossfade 属性形成交叉淡化效果
3:MockView 充当原型图
十五、Layer(层布局)
Layer常用来增加背景,或者共同动画,图层 (Layer) 在布局期间会调整大小,其大小会根据其引用的所有视图进行调整,代码的先后顺序也会决定着它的位置,如果代码在所有引用view的最后面,那么它就会在所有view的最上面,反之则是最下面,在最上面的时候如果添加背景,就会把引用的view覆盖掉