1.约束布局是什么
约束布局: 可以理解为是相对布局的增强版,在相对布局的基础上增加了线性布局和百分比布局的属性。顾名思义它是通过各种属性的约束,限定来对控件的位置进行控制,从而达到特定的排版。
好处: 减少了布局的层级的嵌套和渲染时间
2.使用前的准备
新建一个项目,像下图中默认的布局就是约束布局
如果你的项目中无法联想出下图中的布局,你需要在app/build.gradle文件中添加implementation 'com.android.support.constraint:constraint-layout:1.1.3'
点击下图右上角Sync Now即可
AndroidStudio还提供了将普通布局一键转换为约束布局的便捷操作:
以上操作可以作为一个参考,具体属性的运用还是以代码为主,自动生成具有一定的局限性,有时候会改变原来的布局。
3.基本属性(app下总共50个)
如果你是手动将其他布局方式改为约束布局记得在约束布局外层添加
xmlns:app="http://schemas.android.com/apk/res-auto"
否则会报红,找不到以下app:下的属性
1.相对于父布局的属性
constraintXXX:表示当前控件的某一边
toYYYOf:表示目标控件的某侧
app:layout_constraintBottom_toBottomOf="parent" //当前控件的底部与父布局底部对齐
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBaseline_toBaselineOf="parent" //当前控件的基准线与父布局的基准线对齐
2.相对于兄弟(同一层级)控件的属性
根据控件的id增加约束来确定位置,与父控件属性相同,只是约束不同
//btn3位于btn1的下边
<Button
android:id="@+id/btn3"
android:layout_width="100dp"
android:layout_height="70dp"
android:text="@string/btn3"
android:textSize="20sp"
app:layout_constraintTop_toBottomOf="@id/btn1" />
3.中心定位和偏移量
偏移范围:0-1
水平方向:0-1(从左到右)
垂直方向:0-1(从上到下)
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
//以上两个属性设置控件为水平居中
app:layout_constraintHorizontal_bias="0.2"//水平居中的基础上向稍左偏移
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent"
//以上两个属性设置控件为垂直居中
app:layout_constraintVertical_bias="0.7"//垂直居中的基础上稍向下偏移
- 经验证偏移量结合中心定位的四个属性才会有效,直接在控件设置偏移量不会对控件产生影响。
- 运用以上属性可以控制实现的效果:
<?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="match_parent"
android:layout_height="match_parent"
tools:context="com.syp.constraintlayoutdemo.MainActivity">
<!--位于父控件中心位置-->
<TextView
android:id="@+id/tv1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="中心位置"
android:textSize="30sp"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintVertical_bias="0.5"
app:layout_constraintBaseline_toBaselineOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<!--与父控件左侧对齐-->
<Button
android:id="@+id/btn1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/btn1"
app:layout_constraintLeft_toLeftOf="parent" />
<!--位于按钮1的右边(当前控件按钮2左侧与按钮1右侧对齐)-->
<Button
android:id="@+id/btn2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/btn2"
app:layout_constraintLeft_toRightOf="@id/btn1" />
<!--位于按钮1的下边-->
<Button
android:id="@+id/btn3"
android:layout_width="100dp"
android:layout_height="70dp"
android:text="@string/btn3"
android:textSize="20sp"
app:layout_constraintTop_toBottomOf="@id/btn1" />
<!--位于父容器的右下边-->
<Button
android:id="@+id/btn4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/btn4"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent" />
<!--位于按钮3的右边,按钮2的下边-->
<Button
android:id="@+id/btn5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/btn5"
app:layout_constraintLeft_toRightOf="@id/btn3"
app:layout_constraintTop_toBottomOf="@id/btn2" />
<!--位于按钮5的右边,按钮3的下边-->
<Button
android:id="@+id/btn6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/btn6"
app:layout_constraintLeft_toRightOf="@id/btn5"
app:layout_constraintTop_toBottomOf="@id/btn3" />
<!--位于按钮4的左边,与按钮3基线对齐-->
<Button
android:id="@+id/btn7"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/btn7"
app:layout_constraintRight_toLeftOf="@id/btn4"
app:layout_constraintBaseline_toBaselineOf="@id/btn3"/>
</android.support.constraint.ConstraintLayout>
4.尺寸约束(强制约束)
以下尺寸的约束属性只有宽高为wrap_content时有效(与其他控件使用方式相同)
android:minHeight:最小高度
android:maxWidth:最大宽度
android:maxHeight:最大高度
以下强制约束可以对宽高为wrap_content控件进行进一步约束:
当控件自身的宽度大于约束的宽度的时候会使约束条件失效,此时就需要将
app:layout_constrainedWidth的值设为true
android:layout_width="wrap_content"
app:layout_constrainedWidth="true" //默认为false
例如:
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/btn01"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="AAAAAAAAAAA" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
app:layout_constrainedWidth="true"
app:layout_constraintLeft_toRightOf="@id/btn01"
app:layout_constraintRight_toRightOf="parent" />
</android.support.constraint.ConstraintLayout>
默认情况如下图
将layout_constrainedWidth属性设为true
5.圆形布局
圆形布局中的三个属性:
app:layout_constraintCircle:"@id/xxx",该控件的约束控件的id,即根据xxx控件产生的约束条件
app:layout_constraintCircleRadius:"xxx",指定该控件中心与约束控件中心距离,即半径
app:layout_constraintCircleAngle:"xxx",指定该控件中心与约束控件中心的偏移角度(竖直的上方为0°,水平右侧为90°)
例如:
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/btn01"
android:layout_width="400dp"
android:layout_height="300dp"
android:background="@color/green" />
<Button
android:id="@+id/btn_circle"
android:layout_width="300dp"
android:layout_height="300dp"
android:background="@drawable/shape_const_circle"
android:text="center"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" />
<Button
android:id="@+id/btn02"
android:layout_width="100dp"
android:layout_height="60dp"
android:background="@color/red"
android:text="test"
app:layout_constraintCircle="@id/btn01"
app:layout_constraintCircleAngle="45"
app:layout_constraintCircleRadius="80dp" />
<Button
android:id="@+id/btn_test"
android:layout_width="60dp"
android:layout_height="60dp"
android:background="@drawable/shape_const_circle"
android:text="test"
android:visibility="visible"
app:layout_constraintCircle="@id/btn01"
app:layout_constraintCircleAngle="45"
app:layout_constraintCircleRadius="80dp" />
<Button
android:id="@+id/btn03"
android:layout_width="100dp"
android:layout_height="60dp"
android:background="@color/red"
android:textColor="@color/white"
app:layout_constraintCircle="@id/btn01"
app:layout_constraintCircleAngle="225"
app:layout_constraintCircleRadius="80dp" />
<Button
android:layout_width="60dp"
android:layout_height="60dp"
android:background="@drawable/shape_const_circle"
android:text="symmetries"
app:layout_constraintCircle="@id/btn01"
app:layout_constraintCircleAngle="225"
app:layout_constraintCircleRadius="80dp" />
<!--圆形布局-->
<!-- app:layout_constraintCircle:指定参照的控件id,(参照控件用于约束 约束控件的位置),此处指定btn02控件约束于btn01控件的中心-->
<!-- app:layout_constraintCircleRadius:指定约束的控件中心与参照控件中心的距离(半径)-->
<!-- app:layout_constraintCircleAngle:指定约束的控件中心与参照控件中心的角度(偏移量)-->
</android.support.constraint.ConstraintLayout>
6.百分比约束(针对父控件的百分比)
app:layout_constraintHeight_percent="0.2" //表示百分比,相对父控件的百分比,高度占比20%
例如:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<Button
android:layout_width="0dp"
android:layout_height="0dp"
android:background="@color/red"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintHeight_percent="0.2"
app:layout_constraintWidth_percent="0.5"/>
<!--在约束布局中,0dp代表match_parent-->
<!--layout_constraintHeight_percent表示百分比,相对于父控件的宽、高-->
</android.support.constraint.ConstraintLayout>
注意:约束布局中控件的宽高属性有三种方式:
- 固定宽高
- wrap_content
- 0dp(即mach_parent,约束布局中被0dp替代)
0dp用在width上,则水平方向必须有约束,不然失效,同理,用在height上,竖直方向必须有约束,因0dp(match_constraint是用在约束上面的,没有约束,0dp是不成立的)
例如:控件依然显示为原始大小
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintHeight_percent="0.3"
app:layout_constraintWidth_percent="0.5"/>
</android.support.constraint.ConstraintLayout>
只要加上例如以下任意一个或多个约束,控件就可以按照百分比正常显示。
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
7.Chains链式
- 概念: 在同一个轴上,一组控件通过一个双向的约束关系关联起来(成为链的条件),并且链条的属性由链条头(横向的最左端或者纵向的最顶端)的控件控制
- 俩种属性方向(在chain head 设置该属性,即水平或垂直方向的第一个控件)
app:layout_constraintHorizontal_chainStyle="spread"(水平)
app:layout_constraintVertical_chainStyle="spread"(垂直)
- 三种属性值
- spread: 默认值。均匀分布(控件宽为wrap_content或确定值)
- spread_inside: 与spread类型,只是chain两端的控件不占父容器的空间,多余的空间由chain里的控件平分
- packed: chain 上的所有控件居中紧挨在一起
- 代码示例
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/btn1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/btn1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@id/btn2"
app:layout_constraintHorizontal_chainStyle="spread" />
<Button
android:id="@+id/btn2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/btn2"
app:layout_constraintLeft_toRightOf="@id/btn1"
app:layout_constraintRight_toLeftOf="@id/btn3" />
<Button
android:id="@+id/btn3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/btn3"
app:layout_constraintLeft_toRightOf="@id/btn2"
app:layout_constraintRight_toRightOf="parent" />
</android.support.constraint.ConstraintLayout>
属性值(spread、spread_inside、packed)对应效果图分别如下:
-
spread
-
spread_inside
-
packed
注意: -
当设置spread时,可以分别为每个子控件设置权重,对应的属性为layout_constraintHorizontal_weight和layout_constraintVertical_weight,与LinearLayout的weight类似,需要注意的是,此时子控件的layout_width需要设成0dp。
-
当设置packed时,可以设置chain在水平或垂直方向上的偏移量,对应的属性为layout_constraintHorizontal_bias和layout_constraintVertical_bias,取值在0到1之间。(目前验证设置在链条头有效)
8.Ratio比例
- 理解:在约束布局中,当前控件宽或者高确定(个人理解0dp,固定值)的话,可以根据比例确定另一边的大小,通过layout_constraintDimensionRatio属性来设定宽高比例
- 三种设定方式
//默认设定ratio = 宽:高
app:layout_constraintDimensionRatio="1:2"
//比例ratio = 高:宽
app:layout_constraintDimensionRatio="w,1:2"
//比例ratio = 宽:高
app:layout_constraintDimensionRatio="H,1:2"
- 代码示例
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/btn1"
android:layout_width="0dp"
android:layout_height="50dp"
android:text="@string/btn1"
android:visibility="visible"
app:layout_constraintDimensionRatio="3:1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" />
<Button
android:id="@id/btn2"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_marginTop="20dp"
android:layout_marginBottom="20dp"
android:text="@string/btn2"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="w,1:2"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn1" />
</android.support.constraint.ConstraintLayout>
- 效果图
9.goneMargin
- 作用:主要用于约束的控件被设为不可见状态时使用的margin值
- 属性:
当前view和另一个view绑定后,另一个view属性设为gone后以下属性生效
app:layout_goneMarginLeft="20dp"
app:layout_goneMarginTop="20dp"
app:layout_goneMarginBottom="20dp"
app:layout_goneMarginEnd="20dp"
app:layout_goneMarginRight="20dp"
app:layout_goneMarginStart="20dp"
- 代码示例:
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/btn01"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/btn1"
android:visibility="gone"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@id/btn02" />
<Button
android:id="@+id/btn02"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/btn2"
android:visibility="visible"
app:layout_constraintLeft_toRightOf="@id/btn01"
app:layout_goneMarginLeft="20dp" />
</android.support.constraint.ConstraintLayout>
10.虚拟辅助布局
- Guildline:仅是一个工具类,不会被显示,用于约束布局中的定位辅助(有助简化部分适配,减少层级嵌套)
-
俩个方向:
//宽度为零,高度为ConstraintLayout的高度 android:orientation="vertical" //Guideline高度为零,宽度为ConstraintLayout的高度 android:orientation="horizontal"
-
三种定位方式:
指定距离左侧或顶部的固定距离(app:layout_constraintGuide_begin="100dp"
)
指定距离右侧或底部的固定距离(app:layout_constraintGuide_end="100dp"
)
指定在父控件中宽度或高度的百分比(app:layout_constraintGuide_percent="0.7"
) -
代码示例:
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.constraint.Guideline
android:id="@+id/guideline"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_end="100dp" />
<Button
android:id="@+id/button1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="Button"
app:layout_constraintLeft_toLeftOf="@+id/guideline"/>
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="Button"
app:layout_constraintRight_toRightOf="@+id/guideline"
app:layout_constraintTop_toBottomOf="@id/button1" />
<Button
android:id="@+id/button3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="Button"
app:layout_constraintRight_toRightOf="@+id/guideline"
app:layout_constraintTop_toBottomOf="@id/button2" />
</android.support.constraint.ConstraintLayout>
- 效果图:
- 结合示例可以看出:Guidline水平方向时,宽为mach_parent时button3的app:layout_constraintRight_toRightOf="@+id/guideline"属性失效,若想此属性生效,需将宽设为0dp,wrap_content或固定宽度。
- Barrier
- 用一种view来限定自身的辅助线,限制源是一组view的id
- 属性:
constraint_referenced_ids
限制源,值由一组id值组成,id值之间使用逗号隔开
barrierDirection
指定限制的方向(有left\top\right\bottom\start\end六组值),根据限制源来限定的,如该属性值为right的时候,表示该Barrier位于ids这一组控件的最右侧
- 代码示例:
针对左侧标题长度不一,右侧内容要求左对齐的情况使用很方便
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/tv_phone_id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:layout_marginTop="10dp"
android:text="手机号:"
app:layout_constraintTop_toTopOf="parent"
android:textSize="15sp"
app:layout_constraintLeft_toLeftOf="parent"/>
<TextView
android:id="@+id/tv_password_id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="密码:"
android:textSize="15sp"
app:layout_constraintLeft_toLeftOf="@id/tv_phone_id"
app:layout_constraintTop_toBottomOf="@id/tv_phone_id" />
<TextView
android:id="@+id/tv_confirm_password_id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="确认密码:"
android:textSize="15sp"
app:layout_constraintLeft_toLeftOf="@id/tv_phone_id"
app:layout_constraintTop_toBottomOf="@id/tv_password_id" />
<EditText
android:id="@+id/et_phone_id"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="@null"
android:hint="请输入正确的手机号"
android:textSize="15sp"
android:layout_marginRight="16dp"
app:layout_constraintBottom_toBottomOf="@id/tv_phone_id"
app:layout_constraintLeft_toRightOf="@id/barrier2"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="@id/tv_phone_id" />
<EditText
android:id="@+id/et_password_id"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="@null"
android:hint="请输入密码"
android:textSize="15sp"
android:layout_marginRight="16dp"
app:layout_constraintBottom_toBottomOf="@id/tv_password_id"
app:layout_constraintLeft_toRightOf="@id/barrier2"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="@id/tv_password_id" />
<EditText
android:id="@+id/et_confirm_password_id"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:background="@null"
android:hint="请再次输入密码"
android:textSize="15sp"
android:layout_marginRight="16dp"
app:layout_constraintBottom_toBottomOf="@id/tv_confirm_password_id"
app:layout_constraintLeft_toRightOf="@id/barrier2"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="@id/tv_confirm_password_id" />
<android.support.constraint.Barrier
android:id="@+id/barrier2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="right"
app:constraint_referenced_ids="tv_phone_id,tv_password_id,tv_confirm_password_id" />
<android.support.constraint.Guideline
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</android.support.constraint.ConstraintLayout>
- 效果图:
- Group
-
作用:用于多个控件的统一显示隐藏
-
属性:
android:visibility="visible" //显示隐藏 app:constraint_referenced_ids="btn01,btn02" //要控制(显示隐藏)控件组的id集合
-
代码示例:
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.constraint.Group
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
app:constraint_referenced_ids="btn01,btn02" />
<Button
android:id="@+id/btn01"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/btn1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@id/btn02" />
<Button
android:id="@+id/btn02"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/btn2"
app:layout_constraintLeft_toRightOf="@id/btn01" />
<Button
android:id="@+id/btn03"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/btn3"
app:layout_constraintLeft_toRightOf="@id/btn02" />
</android.support.constraint.ConstraintLayout>
- 注意:多个Group可以引用相同的控件,最终由它们先后的位置决定
例如:
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.constraint.Group
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
app:constraint_referenced_ids="btn01,btn02" />
<android.support.constraint.Group
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="visible"
app:constraint_referenced_ids="btn02" />
<Button
android:id="@+id/btn01"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/btn1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@id/btn02" />
<Button
android:id="@+id/btn02"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/btn2"
app:layout_constraintLeft_toRightOf="@id/btn01" />
<Button
android:id="@+id/btn03"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/btn3"
app:layout_constraintLeft_toRightOf="@id/btn02" />
</android.support.constraint.ConstraintLayout>
- 效果图:
https://github.com/VinnyChen/ConstraintLayoutDemo
角度定位:https://blog.csdn.net/PIYELL/article/details/78726270
参考以上两篇文章对比融合
- Placeholder(占位符)
- 作用:在Placeholder中可使用setContent()设置另一个控件的id,使这个控件移动到占位符的位置
- 属性:
app:content="@+id/textview"
- 例如:新建一个Placeholder约束在屏幕的左上角,新建一个TextView约束在屏幕的右上角,在Placeholder中设置 app:content="@+id/textview",这时TextView会跑到屏幕的左上角
<android.support.constraint.Placeholder
android:id="@+id/placeholder"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:content="@+id/textview"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#cccccc"
android:padding="16dp"
android:text="TextView"
android:textColor="#000000"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
4.如何使用(补充)
4.1动态修改布局约束
-
作用:可以在代码中灵活修改布控件约束,从而调整整体布局显示。
-
方法:ConstraintSet cs = new ConstraintSet();
-
1.获取当前目标控件的约束集合):
cs.clone(clRootContainer); //clRootContainer布局id
-
2.清除约束:
cs.clear(surfaceView.getId()); //surfaceView.getId()控件id
-
3.修改约束:
cs.connect(rgRobotControl.getId(), ConstraintSet.LEFT, clRootContainer.getId(), ConstraintSet.LEFT); //rgRobotControl.getId()、clRootContainer.getId()控件id
-
关于ConstraintSet的connect方法:
connect方法有两个重载方法,分别有四个参数和五个参数(多一个margin参数);多的那个参数可以让我们设置该方向的margin;-
另外四个参数如下:
startID:需要设置约束的控件的ID,通过控件View#getId()方法获取;
startSide:要设置哪个方向的约束,对应xml文件中 layout_constraintLeft_toRightOf等属性下划线左边的Left部分;
endID:约束参考控件的ID,设置与哪一个控件的约束,对应xml文件中layout_constraintLeft_toLeftOf="parent"等属性的参数;
endSide:设置参考控件提供的约束的方向:对应xml文件中layout_constraintLeft_toRightOf等属性下划线右边的Right部分
-
-
-
以横竖屏切换为例
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
int mCurrentOrientation = getResources().getConfiguration().orientation;
//竖屏
if (mCurrentOrientation == Configuration.ORIENTATION_PORTRAIT) {
changeToPortraitLayout();
} else {
changeToLandscapeLayout();
}
}
- 修改约束代码示例:
/**
* 动态设置竖屏状态下布局约束
*/
private void changeToPortraitLayout() {
ConstraintSet cs = new ConstraintSet();
//获取当前目标控件的约束集合
cs.clone(clRootContainer);
//修改surfaceView约束
//清除约束
cs.clear(surfaceView.getId());
cs.connect(surfaceView.getId(), ConstraintSet.LEFT, clRootContainer.getId(), ConstraintSet.LEFT);
cs.connect(surfaceView.getId(), ConstraintSet.TOP, findViewById(R.id.topTitle).getId(), ConstraintSet.BOTTOM);
cs.connect(surfaceView.getId(), ConstraintSet.RIGHT, clRootContainer.getId(), ConstraintSet.RIGHT);
cs.connect(surfaceView.getId(), ConstraintSet.BOTTOM, findViewById(R.id.guideCenter).getId(), ConstraintSet.TOP);
//修改控制切换按钮的约束,这里不能调用cs的clear方法清除约束,否者无法正常显示该控件
cs.connect(rgRobotControl.getId(), ConstraintSet.LEFT, clRootContainer.getId(), ConstraintSet.LEFT);
cs.connect(rgRobotControl.getId(), ConstraintSet.TOP, findViewById(R.id.guideCenter).getId(), ConstraintSet.BOTTOM);
cs.connect(rgRobotControl.getId(), ConstraintSet.RIGHT, clRootContainer.getId(), ConstraintSet.RIGHT);
//修改控制Fragment的约束
cs.clear(controlContainer.getId());
cs.connect(controlContainer.getId(), ConstraintSet.TOP, rgRobotControl.getId(), ConstraintSet.BOTTOM);
cs.connect(controlContainer.getId(), ConstraintSet.LEFT, rgRobotControl.getId(), ConstraintSet.LEFT);
cs.connect(controlContainer.getId(), ConstraintSet.RIGHT, rgRobotControl.getId(), ConstraintSet.RIGHT);
cs.connect(controlContainer.getId(), ConstraintSet.BOTTOM, clRootContainer.getId(), ConstraintSet.BOTTOM);
//将修改过的约束重新应用到ConstrainLayout
cs.applyTo(clRootContainer);
}
其中,必须先clone目标ConstraintLayout的约束,在现有约束上修改,否者新的约束会覆盖已有约束。 经过测试,如果其中一个方向上的约束没有显示设置,就不能调用clear方法清除旧的约束,我这里出现了控件无法显示的现象;
- changeToLandscapeLayout方法和changeToPortraitLayout方法实现相似;
持续更新中…
5.基础的demo案例(一个Activity+多个Fragment)
https://github.com/Snowy-syp/ConstraintLayoutDemo
6.一个复杂布局的实战
更新中…