ConstraintLayout常用属性

ConstraintLayout就是常说的约束性布局,所谓约束性就是通过一些特定“条件”来控制View的位置。既然是约束View,那么就必须有一个“相对点”,就是不变的,这样我们才能进行约束,个人认为ConstraintLayout的这个“相对点”就是父布局(ConstraintLayout)。

就像我们在一个空房子里面一样,怎么确定你站在那个位置?我们可以说在左上角、右下角、横向中间偏下多少米等这样的术语来确定自己的位置。ConstraintLayout也是如此。

要确定ConstraintLayout里面View的位置,可以设置在父布局的左上角,那么这个左上角怎么指定呢?首先要知道是那个父布局(ConstraintLayout),通常我们会给父布局设置一个id,在Constraintlayout系统已经帮我们设置了父布局的id,就是parent。但是我们也可以自己设置,多此一举没必要。明白这一点我们就开始看一下怎么确定View在房间的那个位置。

1.重叠位置属性
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"

这里所说的重叠是在不设置margin的前提下,也就是当前View的上下左右都和目标View重叠,相当于常用布局RelativeLayout的功能。

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@color/colorPrimary"
    android:text="左上角"
    android:textSize="30dp"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@color/colorPrimary"
    android:text="右下角"
    android:textSize="30dp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintRight_toRightOf="parent" />
2.基线对齐
app:layout_constraintBaseline_toBaselineOf="@id/tv_2"

在做涉及数字显示的时候经常遇到,数字和其前面/后面的文件字体不一样大,视觉小姐姐要求文本“底部”对齐,当我们按照自己觉得正确的方式设置后,小姐姐总是不满意,这就涉及到文本基线的问题了。在之前我们需要自己重写TextView去处理这个“bug”,有了ConstraintLayout就用我们自己处理了。

通过设置Guideline预览看到数字和文字是内容在一个水平线上,完美达到小姐姐的要求。

TextView
    android:id="@+id/tv_8"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="金额:"
    app:layout_constraintTop_toTopOf="parent"
    android:layout_marginTop="100dp"
    app:layout_constraintLeft_toLeftOf="parent" />

<TextView
    android:id="@+id/tv_9"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="889.98"
    android:textSize="50dp"
    app:layout_constraintLeft_toRightOf="@id/tv_8"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintBaseline_toBaselineOf="@id/tv_8"/>

<TextView
    android:id="@+id/tv_1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="8.5"
    android:textSize="50dp"
    app:layout_constraintTop_toTopOf="parent"
    android:layout_marginTop="200dp"
    app:layout_constraintLeft_toLeftOf="parent" />

<TextView
    android:id="@+id/tv_2"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="折"
    app:layout_constraintLeft_toRightOf="@id/tv_1"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintBaseline_toBaselineOf="@id/tv_1"/>

<androidx.constraintlayout.widget.Guideline
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    app:layout_constraintGuide_percent="0.16" />

<androidx.constraintlayout.widget.Guideline
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    app:layout_constraintGuide_percent="0.35" />
3.相对位置属性
app:layout_constraintLeft_toRightOf="@id/tv_3"
app:layout_constraintRight_toLeftOf="@id/tv_3"
app:layout_constraintTop_toBottomOf="@id/tv_3"
app:layout_constraintBottom_toTopOf="@id/tv_3"
app:layout_constraintStart_toEndOf="@id/cl_3"
app:layout_constraintEnd_toStartOf="@id/cl_3"

所谓相对位置就是当前View在目标View的上下左右方向位置,相当于LinearLayout的功能,但是功能比其更强大。

<TextView
    android:id="@+id/tv_1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@color/colorPrimary"
    android:text="左上角"
    android:textSize="30dp"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@color/colorPrimary"
    android:text="在tv_1右下角"
    android:textSize="30dp"
    app:layout_constraintTop_toBottomOf="@id/tv_1"
    app:layout_constraintLeft_toRightOf="@id/tv_1" />
4.View居中

在ConstraintLayout中没有LinearLayout中的gravity="center_vertical | center_horizontal | center"这样的控制内部View居中属性,也没有RelativeLayout中的layout_centerHorizontal="true"layout_centerVertical="true"layout_centerInParent="true"控制View自身内部居中属性。

在ConstraintLayou中2个相对方向的重叠属性就是居中,例如左右居中可以这样设置:layout_constraintLeft_toLeftOf="parent",同时layout_constraintRight_toRightOf="parent",当前View左侧和右侧在父布局的左侧和右侧,那就是居中,相当于你的位置距离房子的左侧和右侧一样的距离,那这样你就是左右居中的。同样上下居中需要同时设置layout_constraintBottom_toBottomOf="parent"layout_constraintTop_toTopOf="parent"

<TextView
    android:background="@color/colorPrimary"
    android:id="@+id/tv_1"
    android:layout_height="wrap_content"
    android:layout_width="wrap_content"
    android:text="水平居中"
    android:textSize="30dp"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent" />

<TextView
    android:background="@color/colorPrimary"
    android:layout_height="wrap_content"
    android:layout_width="wrap_content"
    android:text="垂直居中"
    android:textSize="30dp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintTop_toTopOf="parent" />
5.间距goneMargin
app:layout_goneMarginStart="10dp"
app:layout_goneMarginEnd="10dp"
app:alayout_goneMarginLeft="10dp"
app:layout_goneMarginTop="10dp"
app:layout_goneMarginRight="10dp"
app:layout_goneMarginBottom="10dp"

实际开发中会遇到当前View在目标View的右侧并存在margin间距,当目标View隐藏之后,这个margin会根据目标View左侧的View为准,左侧没有其他View就会以父布局为准。但是这不一定是我们想要的效果,我们想要当目标View隐藏之后重新设置一个间距,也就是目标View显示和隐藏2个状态下都设置好间距,这个时候goneMargin就派上用场了。

<TextView
    android:id="@+id/tv_1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@color/colorPrimary"
    android:text="左上角"
    android:textSize="30dp"
    android:visibility="visible"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@color/colorPrimary"
    android:text="在tv_1右边"
    android:textSize="30dp"
    android:layout_marginLeft="20dp"
    app:layout_goneMarginLeft="100dp"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintLeft_toRightOf="@id/tv_1" />
6.View居中偏移量
app:layout_constraintVertical_bias="0.3" 0~1
app:layout_constraintHorizontal_bias="0.9" 0~1

ConstraintLayout的强大不止如此,在设置居中后,还可以通过设置属性layout_constraintHorizontal_bias="0.9"或者layout_constraintVertical_bias="0.3"修改当前View距离两个边缘的比例。

<TextView
    android:id="@+id/tv_1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@color/colorPrimary"
    android:text="水平居中"
    android:textSize="30dp"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintHorizontal_bias="0.3"/>

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@color/colorPrimary"
    android:text="垂直居中"
    android:textSize="30dp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintVertical_bias="0.3"/>
7.目标View周围扇形分布
app:layout_constraintCircle="@id/tv_4" 圆心点View
app:layout_constraintCircleAngle="70" 偏移角度(正上方为0度)
app:layout_constraintCircleRadius="100dp" 圆半径
<TextView
    android:id="@+id/tv_1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="•"
    android:textSize="30dp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginLeft="20dp"
    android:text="12"
    android:textSize="30dp"
    app:layout_constraintCircle="@id/tv_1"
    app:layout_constraintCircleAngle="0"
    app:layout_constraintCircleRadius="100dp" />

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginLeft="20dp"
    android:text="3"
    android:textSize="30dp"
    app:layout_constraintCircle="@id/tv_1"
    app:layout_constraintCircleAngle="90"
    app:layout_constraintCircleRadius="100dp" />

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginLeft="20dp"
    android:text="6"
    android:textSize="30dp"
    app:layout_constraintCircle="@id/tv_1"
    app:layout_constraintCircleAngle="180"
    app:layout_constraintCircleRadius="100dp" />

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginLeft="20dp"
    android:text="9"
    android:textSize="30dp"
    app:layout_constraintCircle="@id/tv_1"
    app:layout_constraintCircleAngle="270"
    app:layout_constraintCircleRadius="100dp" />
8.百分比效果
android:layout_width="0dp"
app:layout_constraintWidth_default="percent"
app:layout_constraintWidth_percent="0.5" 设置百分比,默认是1(100%)

android:layout_height="0dp"
app:layout_constraintHeight_default="percent"
app:layout_constraintHeight_percent="0.5" 设置百分比,默认是1(100%)
<TextView
    android:id="@+id/tv_1"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    app:layout_constraintWidth_default="percent"
    app:layout_constraintWidth_percent="0.5"
    android:background="@color/colorPrimary"
    android:text="水平50%"
    android:textSize="30dp" />

<TextView
    android:layout_width="wrap_content"
    android:layout_height="0dp"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintHeight_default="percent"
    app:layout_constraintHeight_percent="0.5"
    android:background="@color/colorPrimary"
    android:text="垂直50%"
    android:textSize="30dp" />
9.设置宽高比
app:layout_constraintDimensionRatio="1:2"
app:layout_constraintDimensionRatio="H,16:2"
app:layout_constraintDimensionRatio="W,2:16"

当一直View的宽/高即:layout_height="0dp"/layout_width="0dp",其高/宽是按照某一个比例进行显示的,那么就可以使用此属性进行实现。

如果宽和高都无法确定即:layout_width="0dp"layout_height="0dp",可以根据父布局的宽/高设置比例。layout_constraintDimensionRatio="H,16:2"layout_constraintDimensionRatio="W,2:16"有着同样的效果,只是书写方式不同而已,而且里面的HW可以换成小写字母hw

<TextView
    android:id="@+id/tv_1"
    android:layout_width="wrap_content"
    android:layout_height="0dp"
    android:background="@color/colorPrimary"
    app:layout_constraintDimensionRatio="1:3"
    android:text="宽已知1:3"
    android:textSize="30dp" />

<TextView
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    app:layout_constraintRight_toRightOf="parent"
    android:background="@color/colorPrimary"
    android:text="高已知4:1"
    android:textSize="30dp"
    app:layout_constraintDimensionRatio="4:1"/>

至于layout_width="0dp"layout_height="0dp"的情况个人感觉不是很好理解,要想有效果必须设置相对2个方向的属性:layout_constraintLeft_toLeftOf="parent"layout_constraintRight_toRightOf="parent",或者layout_constraintTop_toTopOf="parent"layout_constraintBottom_toBottomOf="parent",否则没有效果,即便这样同样的layout_constraintDimensionRatio="W,1:1"属性,设置不同方向之后效果也会不同,建议根据自己实际情况自己测试一下,这种宽高都不确定的情况基本也不会有。

10.链chain
 layout_constraintHorizontal_chainStyle="packed | spread | spread_inside"
 layout_constraintHorizontal_weight="0.1"

上图为官网图,使用此属性的前提是有多个View有所依赖关联,例如下面布局:

<TextView
    android:id="@+id/tv_5"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_marginTop="450dp"
    android:background="@color/colorAccent"
    android:text="左边"
    app:layout_constraintHorizontal_chainStyle="spread_inside"
    app:layout_constraintHorizontal_weight="1"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toLeftOf="@id/tv_6"
    app:layout_constraintTop_toTopOf="parent" />

<TextView
    android:id="@+id/tv_6"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_marginTop="450dp"
    android:background="@color/colorPrimaryDark"
    android:text="中间"
    app:layout_constraintHorizontal_weight="1"
    app:layout_constraintLeft_toRightOf="@id/tv_5"
    app:layout_constraintRight_toLeftOf="@id/tv_7"
    app:layout_constraintTop_toTopOf="parent" />

<TextView
    android:id="@+id/tv_7"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_marginTop="450dp"
    android:background="@color/colorAccent"
    android:text="右边"
    app:layout_constraintHorizontal_weight="1"
    app:layout_constraintLeft_toRightOf="@id/tv_6"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

1.

android:layout_width="0dp"
layout_constraintHorizontal_chainStyle="packed"
layout_constraintHorizontal_weight="0.1"

packed/spread/spread_inside都是根据layout_constraintHorizontal_weight比例设置。

2.

android:layout_width="固定值"
layout_constraintHorizontal_chainStyle="packed"
layout_constraintHorizontal_weight 失效

View紧挨在中间,保留各自的原始width,两边剩余间距平分。

3.

android:layout_width="固定值"
layout_constraintHorizontal_chainStyle="spread"
layout_constraintHorizontal_weight 失效

View保留各自的原始width,两边剩余间距以及两两之间间距平分。

4.

android:layout_width="固定值"
layout_constraintHorizontal_chainStyle="spread_inside"
layout_constraintHorizontal_weight 失效

View保留各自的原始width,两边(上下)在端点,中间的View平分,两两之间间距平分。

5.

android:layout_width="固定值"
layout_constraintHorizontal_chainStyle="packed"
layout_constraintHorizontal_weight 失效
layout_constraintHorizontal_bias="0.3"

View保留各自的原始width,所有View紧挨在一起,左右间距按照比例分配。和情况2相似,两边间距是按照比例。(注意:layout_constraintHorizontal_bias="0.3"只在第一个/最左边的View上生效)

11.Group组
app:constraint_referenced_ids="tv_a, tv_b, tv_c" 

在实际开发中会经常根据条件设置View的GONEVISIBLE,单个View只需要设置一个就可以,如果是需要操作多个View的GONE或者VISIBLE,就需要为每一个View设置,这样代码就会很多,而且可能这些View没有其他任何操作,引入没有必要的View。

有没有办法可以统一设置呢?当然有,在不采用ConstraintLayou时,我们可以把相关View放在一个ViewGroup,前提是这几个View存在某种关联允许放在一个ViewGroup可以完成实际的效果,但现实这个样的情况很少,基本都是没有关联,那就无法实现统一实现GONE或者VISIBLE

在使用ConstraintLayout之后就可以使用Group来实现统一控制一组View的GONE或者VISIBLE了,而且无须这些View存在某种关联。

<androidx.constraintlayout.widget.Group
    android:id="@+id/group"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:constraint_referenced_ids="tv_a, tv_b, tv_c" />

代码中设置就会把3个View隐藏。

group.visibility = GONE
12.屏障Barrier

在开发中我们经常遇到类似的布局,右边的图片在2个文本内容的右侧,不管“标题”和“描述”宽度多少。那么这种情况就采用LinearLayout嵌套的方式,这样就会出现层级过多;RelativeLayout也可以实现,但是也存在问题:我们设置图片在“标题”View的右侧并设置间距,当“标题”内容过短,“描述”内容过长的时候就会出现图片遮挡“描述”的情况。

ConstraintLayout就给我提供了一个好的办法:在2个文本右侧设置一个屏障,然后通过设置图片在屏障的右侧并设置间距就可以了,这样无论2个文本长度如何都不会影响显示。

<TextView
    android:id="@+id/tv_8"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="这个标题有点长长长长长长长长呀"
    app:layout_constraintLeft_toLeftOf="parent" />

<TextView
    android:id="@+id/tv_9"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="10dp"
    android:text="描述"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintTop_toBottomOf="@id/tv_8" />

<ImageView
    android:id="@+id/tv_10"
    android:layout_width="50dp"
    android:layout_height="50dp"
    android:layout_marginLeft="20dp"
    android:src="@mipmap/ic_launcher"
    android:background="@color/colorPrimary"
    app:layout_constraintStart_toEndOf="@id/barrier" />

<androidx.constraintlayout.widget.Barrier
    android:id="@+id/barrier"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:barrierDirection="end"
    app:constraint_referenced_ids="tv_8,tv_9" />
13.辅助线Guideline

在实际开发中,经常遇到在布局中2个距离较远的View是否在一个水平线或者垂直线上而话费较多时间去判断,毕竟肉眼看到的存在视觉上失误,这个时候Guideline就会帮到我们,此View只会在Xml布局预览中显示,运行之后是不存在的,辅助我们判断View是否在一个水平或者垂直线上。

<androidx.constraintlayout.widget.Guideline
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    app:layout_constraintGuide_percent="0.4" />

<androidx.constraintlayout.widget.Guideline
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    app:layout_constraintGuide_percent="0.4" />
14.绝对位置
app:layout_editor_absoluteX="300dp"
app:layout_editor_absoluteY="400dp"

设置目标View在布局中的绝对位置,运行之后失效。实际中暂无发现实际作用

注意点

margin属性只有在设置了1和2情况中的属性时才会有效,例如:设置了属性app:layout_constraintTop_toTopOf="parent"或者app:layout_constraintTop_toBottomOf="@id/tv_3"android:layout_marginTop="30dp"才会有效果。其他margin属性也是同理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值