介绍
ConstraintLayout是可以灵活定位、调整小部件的ViewGroup,API9开始支持的Support库,用来解决布局嵌套过多的问题。 developer.android.com/reference/a…
developer.android.com/training/co…
开发指南
1. Relative positioning 相对位置
相对位置是ConstrainLayout中创建布局的基础构建块之一,这些约束允许你定位一个部件相对于另外一个的位置,你可以在水平和垂直轴上约束部件。
-
水平:left, right, start, end
-
垂直:top, bottom, text baseline
下面是可用约束的列表他们都支持引用另一个部件的id或parent
-
layout_constraintLeft_toLeftOf
-
layout_constraintLeft_toRightOf
-
layout_constraintRight_toLeftOf
-
layout_constraintRight_toRightOf
-
layout_constraintTop_toTopOf
-
layout_constraintTop_toBottomOf
-
layout_constraintBottom_toTopOf
-
layout_constraintBottom_toBottomOf
-
layout_constraintBaseline_toBaselineOf
-
layout_constraintStart_toEndOf
-
layout_constraintStart_toStartOf
-
layout_constraintEnd_toStartOf
-
layout_constraintEnd_toEndOf
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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">
<TextView
android:id="@+id/txtA"
......
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
<TextView
android:id="@+id/txtB"
......
app:layout_constraintRight_toLeftOf="@id/txtA"
app:layout_constraintBottom_toTopOf="@id/txtA"/>
</androidx.constraintlayout.widget.ConstraintLayout>
复制代码
2. Margins 边距
- android:layout_marginStart
- android:layout_marginEnd
- android:layout_marginLeft
- android:layout_marginTop
- android:layout_marginRight
- android:layout_marginBottom
Margins属性需要和constraintXXX_toXXX属性配套使用才生效
当相对部件不可见时,Margins属性同样生效
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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">
<TextView
android:id="@+id/txtA"
......
android:layout_marginLeft="20dp"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:background="@android:color/holo_red_light"/>
<TextView
android:id="@+id/txtB"
......
app:layout_constraintRight_toLeftOf="@id/txtA"
app:layout_constraintBottom_toTopOf="@id/txtA"
android:background="@android:color/holo_green_light"/>
</androidx.constraintlayout.widget.ConstraintLayout>
复制代码
以上,txtA设置layout_marginLeft属性,没有效果。
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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">
<TextView
android:id="@+id/txtA"
......
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:background="@android:color/holo_red_light"/>
<TextView
android:id="@+id/txtB"
......
android:layout_marginRight="20dp"
app:layout_constraintRight_toLeftOf="@id/txtA"
app:layout_constraintBottom_toTopOf="@id/txtA"
android:background="@android:color/holo_green_light"/>
</androidx.constraintlayout.widget.ConstraintLayout>
复制代码
以上,txtB设置layout_marginRight属性,有效果。
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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">
<TextView
android:id="@+id/txtA"
......
android:visibility="gone"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:background="@android:color/holo_red_light"/>
<TextView
android:id="@+id/txtB"
......
android:layout_marginRight="20dp"
app:layout_constraintRight_toLeftOf="@id/txtA"
app:layout_constraintBottom_toTopOf="@id/txtA"
android:background="@android:color/holo_green_light"/>
</androidx.constraintlayout.widget.ConstraintLayout>
复制代码
以上,txtA不可见后,txtB的layout_marginRight属性仍然生效。
Margins 相对不可见View的边距。View可见时,不生效
- layout_goneMarginStart
- layout_goneMarginEnd
- layout_goneMarginLeft
- layout_goneMarginTop
- layout_goneMarginRight
- layout_goneMarginBottom
先看下View可见的效果
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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">
<TextView
android:id="@+id/txtA"
......
android:visibility="visible"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
<TextView
android:id="@+id/txtB"
......
app:layout_goneMarginRight="20dp"
app:layout_constraintRight_toLeftOf="@id/txtA"
app:layout_constraintBottom_toTopOf="@id/txtA"/>
</androidx.constraintlayout.widget.ConstraintLayout>
复制代码
下面看下View不可见的效果
可见,右侧是有边距的。
3. 居中位置,parent也可以改成其他View的id值
- 水平居中
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
复制代码
- 垂直居中
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
复制代码
4. Bias 偏移
相反约束默认是使部件居中显示,即偏移50%,可以通过Bias属性来改变偏差
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintHorizontal_bias="0.3"
复制代码
5. Circular positioning (Added in 1.1) 环形位置
可以以角度和距离约束一个部件的中心,相对于另一个部件的中心位置,即相对于另一个部件中心的圆形上。
- layout_constraintCircle 另一个部件ID
- layout_constraintCircleRadius 半径
- layout_constraintCircleAngle 角度 (from 0 to 360)
6. Visibility behavior 可见行为
ConstraintLayout中的Widgets,如果设置Gone。虽然不可见,但大小会变成0的占位。可以用来做动画基础。
7. Dimensions constraints 尺寸约束
7.1 Minimum dimensions on ConstraintLayout ConstraintLayout最小尺寸
- android:minWidth set the minimum width for the layout
- android:minHeight set the minimum height for the layout
- android:maxWidth set the maximum width for the layout
- android:maxHeight set the maximum height for the layout
这些属性是设置在ConstraintLayout,且设置wrap_content。
7.2 Widgets dimension constraints 部件尺寸约束
设置android:layout_width和android:layout_height属性值指定控件的尺寸。
- 使用指定数值
- 使用wrap_content 要求控件自己计算自己的大小
- 使用0dp 相当于match_constraint
重要: MATCH_PARENT不推荐使用. 可以使用MATCH_CONSTRAINT。
7.3 WRAP_CONTENT enforcing constraints (Added in 1.1)
在1.1前,设置wrap_content属性,会被视为文字尺寸,即约束不会限制结果尺寸。通常这已经足够(更快)。有些情况,仍然希望强制执行约束限制结果尺寸,这种情况,可以使用新的属性。
- app:layout_constrainedWidth="true|false"
- app:layout_constrainedHeight="true|false"
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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">
<TextView
android:id="@+id/txtA"
......
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:background="@android:color/holo_red_light"/>
<TextView
android:id="@+id/txtB"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="A B C D E F G H I J K L M N O P Q R S T U V W X Y Z"
......
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toRightOf="@id/txtA"
android:background="@android:color/holo_green_light"/>
</androidx.constraintlayout.widget.ConstraintLayout>
复制代码
以上,同时约束左侧、右侧的情况。可见,约束没有起作用。
<!-- 增加app:layout_constrainedWidth="true"属性后 -->
复制代码
8. Ratio 宽高比例
8.1 设置宽、高中一个属性值为0dp。
非0的属性值,根据Radio设置值为0dp的属性值
取值:
- 浮点值,表示宽度和高度之间的比率(比如:1.0F)
- "宽度:高度"形式的比率(比如:1:1)
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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">
<TextView
android:id="@+id/txtA"
android:layout_width="160dp"
android:layout_height="0dp"
......
app:layout_constraintDimensionRatio="1.0"/>
<TextView
android:id="@+id/txtB"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:text="A B C D E F G H I J K L M N O P Q R S T U V W X Y Z"
......
app:layout_constraintDimensionRatio="1:1"/>
</androidx.constraintlayout.widget.ConstraintLayout>
复制代码
8.2 宽、高属性都设置成0dp
满足所有约束的最大尺寸并保持指定的比例,要根据某一个特定边的尺寸限制另一个特定边,可以预先附加W 或 H,表示想要约束的宽度或高度。
app:layout_constraintDimensionRatio="W,1:1"
复制代码
9. Chains
链在单个轴上提供一组相似行为(水平或垂直),另一个轴独立约束。
9.1 Creating a chain 创建
一组控件通过双向链接,连接在一起,则被视为链。
错误代码示例<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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">
<TextView
android:id="@+id/txtA"
......
app:layout_constraintHorizontal_chainStyle="spread"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<TextView
android:id="@+id/txtB"
......
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toRightOf="@id/txtA"
app:layout_constraintRight_toRightOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
复制代码
以上,可以理解成,是B对A的单向链。A并没有链接到B上。
正确代码示例
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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">
<TextView
android:id="@+id/txtA"
......
app:layout_constraintHorizontal_chainStyle="spread"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@id/txtB"
app:layout_constraintTop_toTopOf="parent"/>
<TextView
android:id="@+id/txtB"
......
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toRightOf="@id/txtA"
app:layout_constraintRight_toRightOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
复制代码
9.2 Chain heads 链头
链由第一个元素(链头)的属性控制。 链头,水平链的最左侧,垂直链的最顶部。
9.4 Chain Style 样式
- layout_constraintHorizontal_chainStyle
- layout_constraintVertical_chainStyle
取值:
- spread -- 默认,元素将展开,居中均分展示。
- spread权重模式 -- spread模式下,控件设置成0dp,则会分割可用空间。
- spread_inside -- 类似spread模式,两端控件靠边,其他居中均分展示。
- packed -- 链中所有元素,作为一个整体,默认居中,水平或垂直偏差,通过属性Bias控制。
- spread
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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">
<TextView
android:id="@+id/txtA"
......
app:layout_constraintHorizontal_chainStyle="spread"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@id/txtB"
app:layout_constraintTop_toTopOf="parent"/>
<TextView
android:id="@+id/txtB"
......
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toRightOf="@id/txtA"
app:layout_constraintRight_toLeftOf="@id/txtC"/>
<TextView
android:id="@+id/txtC"
......
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toRightOf="@id/txtB"
app:layout_constraintRight_toRightOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
复制代码
- spread权重模式
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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">
<TextView
android:id="@+id/txtA"
......
app:layout_constraintHorizontal_chainStyle="spread"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@id/txtB"
app:layout_constraintTop_toTopOf="parent"/>
<TextView
android:id="@+id/txtB"
......
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toRightOf="@id/txtA"
app:layout_constraintRight_toLeftOf="@id/txtC" />
<TextView
android:id="@+id/txtC"
android:layout_width="0dp"
android:layout_height="120dp"
......
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toRightOf="@id/txtB"
app:layout_constraintRight_toRightOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
复制代码
可见,WidgetC宽度占了全部剩余空间
如果有多个控件设置了0dp,可以通过属性控制各自权重值
- app:layout_constraintHorizontal_weight
- app:layout_constraintVertical_weight
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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">
<TextView
android:id="@+id/txtA"
......
app:layout_constraintHorizontal_chainStyle="spread"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@id/txtB"
app:layout_constraintTop_toTopOf="parent"/>
<TextView
android:id="@+id/txtB"
android:layout_width="0dp"
android:layout_height="150dp"
......
app:layout_constraintHorizontal_weight="2"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toRightOf="@id/txtA"
app:layout_constraintRight_toLeftOf="@id/txtC" />
<TextView
android:id="@+id/txtC"
android:layout_width="0dp"
android:layout_height="120dp"
......
app:layout_constraintHorizontal_weight="1"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toRightOf="@id/txtB"
app:layout_constraintRight_toRightOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
复制代码
- spread_inside
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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">
<TextView
android:id="@+id/txtA"
......
app:layout_constraintHorizontal_chainStyle="spread_inside"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@id/txtB"
app:layout_constraintTop_toTopOf="parent"/>
<TextView
android:id="@+id/txtB"
......
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toRightOf="@id/txtA"
app:layout_constraintRight_toLeftOf="@id/txtC" />
<TextView
android:id="@+id/txtC"
......
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toRightOf="@id/txtB"
app:layout_constraintRight_toRightOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
复制代码
- packed
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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">
<TextView
android:id="@+id/txtA"
......
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@id/txtB"
app:layout_constraintTop_toTopOf="parent"/>
<TextView
android:id="@+id/txtB"
......
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toRightOf="@id/txtA"
app:layout_constraintRight_toLeftOf="@id/txtC" />
<TextView
android:id="@+id/txtC"
......
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toRightOf="@id/txtB"
app:layout_constraintRight_toRightOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
复制代码
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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">
<TextView
android:id="@+id/txtA"
......
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintHorizontal_bias="0.3"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@id/txtB"
app:layout_constraintTop_toTopOf="parent"/>
<TextView
android:id="@+id/txtB"
......
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toRightOf="@id/txtA"
app:layout_constraintRight_toLeftOf="@id/txtC" />
<TextView
android:id="@+id/txtC"
......
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toRightOf="@id/txtB"
app:layout_constraintRight_toRightOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
复制代码
10. 辅助布局
developer.android.google.cn/reference/a…?
- Barrier
- ConstraintSet
- Group
- Guideline
- PlaceHolder