目录
一、 Chains
链使我们能够对一组在水平或竖直方向互相关联的控件的属性进行统一管理。
成为链条的条件:
一组控件之间通过一个双向的约束关系链接起来,并且链的属性由一条链的头结点控制,如下图所示:
布局如下:
<?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/btn_A"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="A"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@+id/btn_B"/>
<Button
android:id="@+id/btn_B"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="B"
app:layout_constraintLeft_toRightOf="@+id/btn_A"
app:layout_constraintRight_toRightOf="parent"/>
</android.support.constraint.ConstraintLayout>
预览图效果:
二、Chains的样式
Chains的样式一共有以下五种:
上图列出5种效果图是在水平方向上的,类似的垂直方向上也具有这5种效果,
分别通过下面2个属性来控制这2个方向上的Chain Style
- layout_constraintHorizontal_chainStyle:水平链条的样式
- layout_constraintVertical_chainStyle:竖直链条的样式
下面以水平方向的Chain Style举例说明
样式1
默认的style是Spread,无需设置,效果如下图所示:
<?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/btn_A"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="A"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@+id/btn_B"/>
<Button
android:id="@+id/btn_B"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="B"
app:layout_constraintLeft_toRightOf="@+id/btn_A"
app:layout_constraintRight_toLeftOf="@+id/btn_C"/>
<Button
android:id="@+id/btn_C"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="C"
app:layout_constraintLeft_toRightOf="@+id/btn_B"
app:layout_constraintRight_toRightOf="parent"/>
</android.support.constraint.ConstraintLayout>
样式2
当在链头设置了app:layout_constraintHorizontal_chainStyle="spread_inside"
就变成了下面的效果:
布局上只需要修改button A即可,因为它是链头
<Button
android:id="@+id/btn_A"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="A"
app:layout_constraintHorizontal_chainStyle="spread_inside"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@+id/btn_B"/>
样式3
权重链设置,这时候就不是使用app:layout_constraintHorizontal_chainStyle
属性了,而是使用layout_constraintHorizontal_weight
属性(垂直分布用layout_constraintVertical_weight
)。
这个效果类似于LinearLayout的weight属性,效果图如下:
3个button的weight都是1,即它们宽度所占的比例是1:1的,需要注意的是,如果要使用权重,那么控件的宽度必须要设置为0dp(这里说的是水平分布的情况,如果是垂直分布是要设置高度的),因此3个button都必须做修改,如下所示:
<?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/btn_A"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="A"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@+id/btn_B"/>
<Button
android:id="@+id/btn_B"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="B"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintLeft_toRightOf="@+id/btn_A"
app:layout_constraintRight_toLeftOf="@+id/btn_C"/>
<Button
android:id="@+id/btn_C"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="C"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintLeft_toRightOf="@+id/btn_B"
app:layout_constraintRight_toRightOf="parent"/>
</android.support.constraint.ConstraintLayout>
样式4
在默认样式的基础上,添加属性app:layout_constraintHorizontal_chainStyle="packed"
到链头,效果如下:
这种效果就类似于垂直分布的LinearLayout的android:gravity="center_horizontal"
属性
布局上只需要修改buttonA
<Button
app:layout_constraintHorizontal_chainStyle="packed"
android:id="@+id/btn_A"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="A"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@+id/btn_B"/>
样式5
在样式4的基础上通过app:layout_constraintHorizontal_bias="0.3"
属性,值取0~1之间来控制整个链头距离父控件(ConstraintLayout)左边的距离
下图是值取0.3的效果:
布局上还是只修改链头就好
<Button
app:layout_constraintHorizontal_bias="0.3"
app:layout_constraintHorizontal_chainStyle="packed"
android:id="@+id/btn_A"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="A"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@+id/btn_B"/>
三、Group
用于控制一组控件的可见性
由于ConstraintLayout是扁平化的布局方式,很多时候我们想要控制多个组件的动态显示和隐藏那就得初始化的时候将这几个控件都findViewById一次,很是麻烦,为了省事,通常会将这几个控件用一个父控件包裹起来,通过控制父控件的可见性来达到目的,但是这样就违背了ConstraintLayout的扁平化布局的思想,那怎么解决呢?
通过Group组件,可以将需要一起控制的几个组件的id统一管理,对Group组件设置visibility属性就可以同时作用于所管理的组件上,如下所示:
<android.support.constraint.Group
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
app:constraint_referenced_ids="btn_A,btn_B" />
效果图:
前提,需要将ConstraintLayout组件升级到1.1.x版本上,例如:
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
四、Ratio
ConstrainLayout提供了ratio属性,用来控制View的宽高比例。这个属性用于列表上需要控制item的宽高比例就非常好用了。以前要实现这种效果还得在代码中动态的设置item的宽高信息,现在如果使用ConstrainLayout布局那就变得很省事了。
使用Ratio属性,宽高两个尺寸中至少要一个是MATCH_CONSTRAINT(0dp)
默认情况下,1:2,表示宽:高=1:2,宽为1,高为2
宽高都为MATCH_CONSTRAINT(0dp)时,可以在比例前加W或者H:
W,1:2 表示高=1,宽=2,即 H:W = 1:2
H,1:2 表示宽=1,高=2,即 W:H = 1:2
如果记不住的话,可以这么记,字母(w或者h)永远表示的是比例中的后者,那么比例中的前者自然代表的就是另一个了,例如w,4:3中, 由于w代表的是比例中的后者,所以宽占3,高占4.
例如:
布局文件如下:
<?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/btn_A"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="A"
app:layout_constraintDimensionRatio="1:2"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<Button
android:id="@+id/btn_B"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="B"
app:layout_constraintDimensionRatio="2:1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btn_A"/>
<Button
android:id="@+id/btn_C"
android:layout_width="0dp"
android:layout_height="0dp"
android:text="C"
app:layout_constraintDimensionRatio="w,1:2"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/btn_B"/>
</android.support.constraint.ConstraintLayout>
五、Circular 定位
可以使用角度和距离来约束一个控件相对于另一个控件的位置。
示意图如下:
选定控件后,就可以通过修改角度和半径来布局了,相关属性如下:
- layout_constraintCircle:参照控件的id
- layout_constraintCircleRadius:两个控件中心连线的距离(半径)
- layout_constraintCircleAngle:当前View的中心与目标View的中心的连线与Y轴方向的夹角(取值:0~360,顺时针递增)
如下所示:
布局如下:
<?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/btn_A"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="45°"
app:layout_constraintCircle="@id/btn_B"
app:layout_constraintCircleAngle="45"
app:layout_constraintCircleRadius="100dp"
/>
<Button
android:id="@+id/btn_B"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="参考View"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
<Button
android:id="@+id/btn_C"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="90°"
app:layout_constraintCircle="@id/btn_B"
app:layout_constraintCircleAngle="90"
app:layout_constraintCircleRadius="100dp"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="135°"
app:layout_constraintCircle="@id/btn_B"
app:layout_constraintCircleAngle="135"
app:layout_constraintCircleRadius="100dp"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="180°"
app:layout_constraintCircle="@id/btn_B"
app:layout_constraintCircleAngle="180"
app:layout_constraintCircleRadius="100dp"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="225°"
app:layout_constraintCircle="@id/btn_B"
app:layout_constraintCircleAngle="225"
app:layout_constraintCircleRadius="100dp"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="270°"
app:layout_constraintCircle="@id/btn_B"
app:layout_constraintCircleAngle="270"
app:layout_constraintCircleRadius="100dp"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="315°"
app:layout_constraintCircle="@id/btn_B"
app:layout_constraintCircleAngle="315"
app:layout_constraintCircleRadius="100dp"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="360°"
app:layout_constraintCircle="@id/btn_B"
app:layout_constraintCircleAngle="360"
app:layout_constraintCircleRadius="100dp"
/>
</android.support.constraint.ConstraintLayout>
六、强制约束
默认情况下,对于两个控件之间如果彼此设置了约束,当其中一个控件的宽度或者高度不断递增的时候,他是会超出约束范围的,如下所示:
布局如下:
<?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:padding="20dp">
<ImageView
android:id="@+id/iv_cover"
android:layout_width="100dp"
android:layout_height="100dp"
android:src="@mipmap/ic_launcher"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginTop="4dp"
android:gravity="center_vertical"
android:maxLines="2"
android:text="标题啊啊标题啊啊标题啊啊标题啊啊标题啊啊标题啊啊标"
app:layout_constraintLeft_toRightOf="@+id/iv_cover"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="@+id/iv_cover"/>
</android.support.constraint.ConstraintLayout>
可以看到TextView明明设置了在图片的右侧,并且还设置了marginLeft,然而当TextView的内容增多的时候,这个约束就不起作用了.
解决这个问题,可以通过这个属性来强制约束
app:layout_constrainedWidth="true"
添加在TextView后的效果如下:
如果要设置垂直方向的高度强制约束,对应的也有一个属性:
app:layout_constrainedHeight="true"
例如这种情况:
对应布局如下:
<?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:padding="20dp">
<ImageView
android:id="@+id/iv_cover"
android:layout_width="100dp"
android:layout_height="100dp"
android:src="@mipmap/ic_launcher"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
<TextView
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginTop="4dp"
android:gravity="top"
android:text="标题啊啊标题啊啊标题啊啊标题啊啊标题啊啊啊标题啊啊标题啊啊标题啊题啊啊标题啊啊标题啊啊标题啊啊标标题啊啊标题啊啊标题啊啊标题啊啊标题啊啊标题啊啊标"
app:layout_constraintBottom_toBottomOf="@+id/iv_cover"
app:layout_constraintLeft_toRightOf="@+id/iv_cover"
app:layout_constraintTop_toTopOf="@+id/iv_cover"/>
</android.support.constraint.ConstraintLayout>
明明设置了TextView的底部是和ImageView对齐的,但是当文字增多的情况下,却超出了约束条件,这时候就可以使用强制约束了,在TextView上添加app:layout_constrainedHeight="true"
后,效果如下:
六、ConstraintSet
(1)首先要声明一下ConstraintSet对象
private val set = ConstraintSet()
(2)其次需要复制一份父布局的约束,方法有三个如下:
set.clone(constraintLayout: ConstraintLayout);
set.clone(set: ConstraintSet);
set.clone(context: Context, constraintLayoutId: Int);
例如:
set.clone(rootLayout)
简单说明一下,如果要修改一个TextView的约束,需要找到TextView的父布局,然后调用上述方法clone一份, 另外这里需要注意一下,在调用clone()方法的时候,必须保证这个父布局的所有子布局都设置了 id,不然会报如下错误:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.liuniukeji.lightlanguage/com.mufeng.light.ui.activity.CurriculumClassifyActivity}: java.lang.RuntimeException: All children of ConstraintLayout must have ids to use ConstraintSet
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2817)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2892)
at android.app.ActivityThread.-wrap11(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1593)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
Caused by: java.lang.RuntimeException: All children of ConstraintLayout must have ids to use ConstraintSet
at android.support.constraint.ConstraintSet.clone(ConstraintSet.java:688)
(3)第三步就需要去设置组件之间的约束了,常用方法有:
set.connect(startID: Int, startSide: Int, endID: Int, endSide: Int, margin: Int)
set.connect(startID: Int, startSide: Int, endID: Int, endSide: Int)
例如: 修改一个id为text的TextView的约束,相依赖的约束组件为一个id为btn的Button,修改为text的左边和btn的左边对其,边距margin为20px:
set.connect(R.id.text,ConstraintSet.LEFT,ConstraintSet.R.id.btn,ConstraintSet.LEFT,20)
设置text水平剧中于父布局parent
set.centerHorizontally(R.id.text, ConstraintSet.PARENT_ID)
设置text的高度为10px
set.constrainHeight(R.id.text, 10);
如果要设置动画,可以这样做(要求api版本为19及以上)
TransitionManager.beginDelayedTransition(rootLayout)
(4)最后一步 ,apply一下使设置生效
set.applyTo(rootLayout)
6.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:id="@+id/rootLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/tv_info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World"
android:textColor="@color/common_colorAccent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="start"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
点击按钮后, 按钮会执行动画, 知道左边靠近文本的右边, 顶部和文本顶部对齐, 执行完后效果图如下:
具体代码实现如下:
class TestConstraintSetActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_constraint_set)
val rootLayout = findViewById<ConstraintLayout>(R.id.rootLayout)
findViewById<Button>(R.id.btn_start).setOnClickListener {
ConstraintSet().apply {
// 克隆跟布局的约束
clone(rootLayout)
//clear(R.id.btn_start) // 清空btn_start的所有布局约束
clear(R.id.btn_start,ConstraintSet.BOTTOM) // 仅清空bottom约束
clear(R.id.btn_start,ConstraintSet.END) // 仅清空right约束
// 添加约束,btn的start在tv的end
connect(R.id.btn_start, ConstraintSet.START, R.id.tv_info, ConstraintSet.END)
// 添加约束,btn的top和tv的top对齐
connect(R.id.btn_start, ConstraintSet.TOP, R.id.tv_info, ConstraintSet.TOP)
// 采用动画的方式执行上面的布局参数修改
val transition = ChangeBounds()
transition.duration = 1000L
TransitionManager.beginDelayedTransition(rootLayout,transition)
// 设置回跟布局
applyTo(rootLayout)
}
}
}
}
七、Flow的用法
Flow管理的view 自身可以不设置layout_constraintStart_toEndOf 等位置
如果不设置,那么需要设置width=“0dp” 和app:layout_constraintWidth_default=“wrap”
如果是Textview最好设置 android:singleLine=“true”
Flow其他属性具体如下:
<androidx.constraintlayout.helper.widget.Flow
android:id="@+id/flow"
//宽度要指定,否则会顶出屏幕外面
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
//引用的id(内部的view的id)
app:constraint_referenced_ids="tv_type,tv_online_state,tv_switch_state"
//chain或者aligned,chain:链形式,依次挨着排,aligned会两端对齐
app:flow_wrapMode="chain"
//首行的对齐方式,packed:靠最左侧挨着排,水平间隔:horizontalGap生效,
// spread:分散对齐,两端不贴边。spread_inside:分散对齐,两头贴边
app:flow_firstHorizontalStyle="packed"
//最后一行的对齐方式,其他属性参考firstHorizontalStyle
app:flow_lastHorizontalStyle="packed"
// 全局水平bias,为0时,每行都贴左边,可解决中间行单独占一行时,不贴最左侧的问题
app:flow_horizontalBias="0"
// 第一行水平bias,为0时,贴最左边
app:flow_firstHorizontalBias="0"
// 最后一行水平bias,为0时,贴最左边
app:flow_lastHorizontalBias="0"
// 控件水平方向上的间隔
app:flow_horizontalGap="10dp"
// 行间隔
app:flow_verticalGap="8dp"
app:layout_constraintEnd_toStartOf="@id/ibt_go"
app:layout_constraintStart_toEndOf="@id/guideline"
app:layout_constraintTop_toTopOf="@id/tv_org_name" />
例如:
<?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">
<ImageView
android:id="@+id/ivDefaultIcon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginBottom="122dp"
android:src="@drawable/common_ic_net_error"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:visibility="visible" />
<androidx.constraintlayout.helper.widget.Flow
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
app:constraint_referenced_ids="tvDefaultTip,tvRetry"
app:flow_horizontalStyle="packed"
app:flow_verticalGap="5dp"
app:flow_wrapMode="chain"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/ivDefaultIcon" />
<TextView
android:id="@+id/tvDefaultTip"
style="@style/regular_title_14"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:singleLine="true"
android:text="@string/没有匹配结果"
android:textColor="@color/black_60"
android:visibility="gone"
app:layout_constrainedWidth="true"
app:layout_constraintEnd_toStartOf="@+id/tvRetry"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/ivDefaultIcon"
tools:visibility="visible" />
<TextView
android:id="@+id/tvRetry"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:singleLine="true"
android:text="@string/重试_4150"
android:textColor="@color/primary_100"
android:textSize="14sp"
android:visibility="gone"
app:layout_constrainedWidth="true"
app:layout_constraintBottom_toBottomOf="@+id/tvDefaultTip"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/tvDefaultTip"
app:layout_constraintTop_toTopOf="@+id/tvDefaultTip"
tools:visibility="visible" />
</androidx.constraintlayout.widget.ConstraintLayout>
效果如下:
当tvDefaultTip内容很多时,tvRetry就会自动布局到下一行,如下所示:
八、view的尺寸限制
设置view的大小除了传统的wrap_content、指定尺寸、match_parent(虽然官方不推荐使用match_parent)外,还可以设置为0dp(官方取名叫MATCH_CONSTRAINT),0dp在constraint可不是指大小是0dp,而是有特殊含义的。他的作用会随着不同的设置有不同的含义:
通过layout_constraintWidth_default 或者layout_constraintHeight_default 可以对view宽度或者高度尺寸进行限制, 以layout_constraintWidth_default为例,它有三个取值,分别如下:
- spread : 默认值,意思是占用所有的符合约束的空间
如下布局将宽度设置为0, 左右和parent对齐
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
...>
<Button
android:id="@+id/a"
android:layout_width="0dp"
...
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintLeft_toLeftOf="parent"/>
</android.support.constraint.ConstraintLayout>
效果图如下, 可以看不到不设置layout_constraintWidth_default的时候, 默认效果就是spread的
- percen: 意思是按照父布局的百分比设置,需要layout_constraintWidth_percent设置百分比例
如下布局将A的宽度设为0.4,则其宽度为父布局的0.4倍。另外,设置了layout_constraintWidth_percent属性,可以不用指定layout_constraintWidth_default,他会自动设置为percent
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout >
<android.support.constraint.ConstraintLayout
android:layout_width="300dp"
android:layout_height="400dp"
app:layout_constraintHorizontal_bias="0.3"
>
<Button
android:id="@+id/a"
android:layout_width="0dp"
...
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintWidth_default="percent"
app:layout_constraintWidth_percent="0.4" />
</android.support.constraint.ConstraintLayout>
</android.support.constraint.ConstraintLayout>
效果图如下:
- wrap: 意思匹配内容大小但不超过约束限制,注意和直接指定宽度为wrap_content的区别就是不超过约束限制, 类似layout_constrainedWidth的效果.
如下布局所示, b和d都是左右和a与c对齐,但是b设置了layout_constraintWidth_default=“wrap”
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
...>
<Button
android:id="@+id/a"
...
app:layout_constraintLeft_toLeftOf="parent" />
<Button
android:id="@+id/c"
...
app:layout_constraintRight_toRightOf="parent" />
<Button
android:id="@+id/b"
android:layout_width="0dp"
...
app:layout_constraintWidth_default="wrap"
app:layout_constraintLeft_toRightOf="@id/a"
app:layout_constraintRight_toLeftOf="@id/c"/>
<Button
android:id="@+id/d"
android:layout_width="wrap_content"
...
app:layout_constraintTop_toBottomOf="@id/b"
app:layout_constraintLeft_toRightOf="@id/a"
app:layout_constraintRight_toLeftOf="@id/c"/>
</android.support.constraint.ConstraintLayout>
结果如下, 可以看到第一行绿色button也就是控件b超出约束范围的内容是不被显示的, 而第二行由于没有强制wrap, 所以内容会超出约束的范围.