Android ConstraintLayout图文并茂详解(二)

来源:互联网 发布:泰安房产每日成交数据 编辑:程序博客网 时间:2024/06/01 21:53

在上篇博文Android ConstraintLayout图文并茂详解(一)中,我们已经知道了如何在ConstraintLayoput中如何定位视图、对齐视图等。在本文中,将继续深入了解ConstraintLayoput。

  1. 修改视图属性
  2. 带有链的线性视图组

修改视图属性

我们将视图从Palette推动到布局后,视图各种属性都是默认值,这必然不能满足界面需求。我们还得根据UI设计图修改视图属性,以满足UI需求。修改视图的属性,当然可以在xml中code实现。另外,在Layout Editor中的属性(Attributes)窗口中一样可以便捷的更改属性。对于更改视图常用属性必然信手拈来。在这里,为了了解在inspector中如何更改约束相关的属性。如果有对inspector界面不了解的,可以参考博文Android ConstraintLayout图文并茂详解(一)中的 “视图的inspector”部分。接下来,先从bias说起…

bias

在Android ConstraintLayout图文并茂详解(一)中提到了,视图有两个相反的约束时,则像弹簧一样,约束变得像一个弹簧一样表示相反的力。当视图大小设置为“fixed”或“wrap_content”时,效果最为明显.在这种情况下,视图以约束为中心。这时,又有新的概念 - 约束偏差。


视图和布局边界之间的可用空间被称为约束偏差,实际上就是控件的约束与布局之间的间距。约束偏差又存在于视图拥有两个相反的约束时,故而约束偏差是是两个边距之和。比如,视图A的左右两侧各有一个约束,边距分别为X和Y,那么约束偏差为 X + Y。

这里写图片描述

也就是说,如果元素居中,这意味着该元素位于两个边界之间的中间位置,也就是说边距值应为(X+Y)/2,其约束偏差值为50%。那么,如果对于水平约束将偏差改为30%,则元素将被放置得更靠近左边界。如果更改为70%,元素将被放置在靠近右边界的位置。对于纵向约束而言,约束偏差是控制视图距离其顶部和底部约束边界的距离。

需要注意的是,当视图添加两个相反的约束后,只有当视图相应的width/height类型设置为“fixed”或“wrap_content”时,约束偏差才有意义。如果其类型为MATCH_CONSTRAINT时,视图本身是充满整个可用的控件,约束偏差是失效的。

当视图添加两个相反的约束后,视图将在两个约束之间居中,也就是说,偏移量默认为50%。如何修改约束偏差呢?

我们可以在拖动属性(Attributes)窗口 - inspector中的偏置滑块或拖动视图来调整偏差,比如,下图的中的Button的约束偏差为50%,我们现在采用这两种方式修改约束偏差:

当然,在ConstraintLayout中,针对于约束偏差,支持库为其定义了相应的偏差属性,我们可以在xml中设置偏差比例属性,使其偏向另一侧:

  • layout_constraintHorizontal_bias
  • layout_constraintVertical_bias

例如,以下代码中,将使视图的约束偏差值为30%,而不是默认的50%,这样左侧边距将会更短,从而视图靠近左侧:

<android.support.constraint.ConstraintLayout ...>    <Button         android:id="@+id/button"         ...        app:layout_constraintHorizontal_bias="0.3"        app:layout_constraintLeft_toLeftOf="parent"        app:layout_constraintRight_toRightOf="parent/></>

这里写图片描述

使用视图大小控键

在Android ConstraintLayout图文并茂详解(一)中,我们已经了解到如何使用视图的约束控键来添加一个约束。现在,我们要来了解拖动调整大小控键来修改视图的大小。

  • 调整大小控键:可以拖动方形调整大小的句柄来调整元素的大小。 拖动时,手柄变成角度变角。
  • 约束控键:单击约束句柄,在元素的每一侧显示为圆形,然后拖动到另一个约束句柄或父边界以创建约束。 约束由Z字形线表示。

从上图中,我们清楚的看到,在我们拖动调整大小控键时,视图的大小虽然可以变化,但是数值并不能实时的显示出来,只有在停止拖动以后,才可以在属性(Attributes)窗口 - inspector中看到视图修改后的大小值。这就有一个问题,拖动的不准确性,肯定不能满足UI的需求。如果是将width/height类型设置为fixed,还不如在属性(Attributes)窗口 - inspector中修改尺寸大小,不仅准确而且效率高。不由得觉得拖动调整大小控键好鸡肋。。。

height/width类型

在传统布局中,我们习惯了使用wrap_content或者match_parent以使用视图的内容或者布局的尺寸来确定视图的大小,甚至是精确地指定视图范围。ConstraintLayout与传统布局类似,而又有所不同。在ConstraintLayout中,可以通过以下3种不同的方式设置android:layout_width和android:layout_height属性来指定控件的尺寸:

  • 这里写图片描述:即fixed,表示固定值,也就是给视图指定了一个固定的长度或者宽度值
  • 这里写图片描述:表示MATCH_CONSTRAINT,或者是any size。对于ConstraintLayout中的任何视图,不应使用match_parent。在XML文件中, 臫0dp表示layout_width或layout_height属性的MATCH_CONSTRAINT值。
  • 这里写图片描述:表示wrap_content

对于fixed和wrap_content,这里不必多说,值得注意的一点是,是当视图的尺寸类型为wrap_content,尤其要注意视图的内容长度是否大于约束之间的距离,以避免出现视图内容覆盖的现象。与传统布局不一样的是,在ConstraintLayout中并不支持MATCH_PARENT,尽管类似的行为可以通过使用MATCH_CONSTRAINT来定义,相应ConstraintLayout的左/右或顶部/底部约束被设置为“parent”。它们最大的区别在于,match parent是用于填充满当前视图的父布局的可用空间,而MATCH_CONSTRAINT是用于填充满当前视图的约束的可用空间,而且在此情况下,可以通过设置尺寸比例来指定视图的尺寸

如果要修改视图的height/width类型,我们可以这么做

  • 在属性(Attributes)窗口 - inspector中,单击可以循环遍历height/width类型
  • 在属性(Attributes)窗口的 layout_width和layout_height中直接设置

将尺寸设置为比例

在height/width类型中提到,当height/width类型为MATCH_CONSTRAINT时,可以通过设置尺寸比例来指定视图的尺寸。这是什么意思呢?就是,我们可以将视图的尺寸维度(宽度/高度)基于视图的另一个维度,可以将视图的高度基于视图的宽度的比例来定义,也可以将视图的宽度基于视图的高度的比例来定义。

对于比例,我们可以这么表示:

  • 浮点数,表示宽度和高度之间的比例
  • “width:height”形式的比例

比如,视图的宽度为160dp,高度为0dp(即MATCH_CONSTRAINT),并将属性layout_constraintDimentionRatio设置为16:9,那么视图的高度为90dp,在属性(Attributes)窗口 - inspector中我们可以看到:

如果在xml中定义,可以这么做:

<Button    android:layout_width="160dp"    android:layout_height="0dp"    app:layout_constraintDimensionRatio="16:9" />

又有一种特殊情况,那就是,宽度和高度均设置为0dp(即MATCH_CONSTRAINT),这也可以使用比率。在这种情况下,其计算方式与Bitmap压缩类似,默认的是满足所有的约束的最大尺寸,并保持指定的宽高比。如果你想指定按比例计算的尺寸维度,可以这么做,可以通过在比例前面添加字幕表示:

  • W:用于约束宽度,此时视图的高度将与约束调节匹配:

    将按照4:9的比例设置ImageView的宽度,而ImageView的高度将与约束条件匹配。

    XML代码:

    <ImageView    android:layout_width="0dp"    android:layout_height="0dp"    app:layout_constraintDimensionRatio="w,4:9"    ... />

    UI效果图:

    在属性(Attributes)窗口 - inspector效果图:

    这里写图片描述

  • H:用于约束高度,此时视图的宽度将与约束调节匹配

    将按照16:9的比例设置ImageView的高度,而ImageView的宽度将与约束条件匹配。

    XML代码:

    <ImageView    android:layout_width="0dp"    android:layout_height="0dp"    app:layout_constraintDimensionRatio="h,16:9"    ... />

    UI效果图:

    在属性(Attributes)窗口 - inspector:效果图:

    这里写图片描述

    <Button    android:layout_width="0dp"    android:layout_height="0dp"    app:layout_constraintDimensionRatio="H,16:9"    ... />

在属性(Attributes)窗口 - inspector中,可以快速的设置尺寸比例。首先先单击切换纵横比约束,下图中红色框标注的,然后在出现的输入框中输入width:height比例。

这里写图片描述

如果要想切换指定按比例计算的尺寸维度,再次点击红色框标注的即可。如果多点,会照成约束偏差混乱,还需要自己重新调,并且约束比例又变成1:1,感觉这里好操蛋,你可以感受下~~~


值得注意的是,如果尺寸比例设置有误,会造成其超出约束条件,类似于之前提到的视图覆盖现象…尺寸比例的设置尤其要慎重,慎重,再慎重…

调整边距

对于Margin属性,跟传统布局的margin属性没啥区别,就是用来表明间隔的距离。

这里写图片描述

在XML中,用以下属性来设置margin属性值:

  • android:layout_marginStart
  • android:layout_marginEnd
  • android:layout_marginLeft
  • android:layout_marginTop
  • android:layout_marginRight
  • android:layout_marginBottom

我们早已熟悉在XML设置margin,这里不用多说。这里我们来看看在Layout Editor中如何快速的设置margin。

默认边距

我们可以在工具栏中设置默认边距。为什么说这是默认边距呢?

在工具栏中,我们只需修改这里写图片描述的值,此值便是约束的默认边距值。在设置此值以后的所有约束的边距值便是它。这样,便于我们统一设置边距。如下所示,将边距值修改为24dp,以后所有的约束的边距都是24dp:

在Design窗口中拖动视图

尽管,我不太习惯在Design窗口中拖动视图,但,其也是修改边距的一种方式,这里也了解下。视图默认的边距为24dp,然后选择视图后,通过拖动的方式修改视图的边距:

在属性(Attributes)窗口 - inspector中

在属性(Attributes)窗口 - inspector中,显示着视图的种种约束值,当然,margin也是包含在其中。

当我们选择某一个视图后,在属性(Attributes)窗口 - inspector中,我们也可以单击属性值,然后进行修改:

goneMargin

对于标记View.GONE的视图,ConstraintLayout有特殊的处理机制。有这么一个情况,A距离容器的侧面有32dp边距,而B距离A有32dp,当将A标记为GONE,而B到容器侧面的边距为16dp:


标记为View.GONE的视图,通常是不显示的,并且不是布局本身的一部分。但是,在布局计算方面,其仍然是布局的一部分,不一样的是:

  • 对于布局,它们的尺寸将被视为0(基本上,它们将被认为是一个点)
  • 如果它约束其他控件,那么仍认为其存在,但任何margins视为0

这里写图片描述

这样就造成了上图所示的情况。假如即使A被标记为View.GONE,仍然想保持住在当前的位置,该怎么办?针对这种情况,ConstraintLayout专门设立了一个goneMargin,当约束视图的可见性为View.GONE时,可以使用不同的边距值:

  • layout_goneMarginStart
  • layout_goneMarginEnd
  • layout_goneMarginLeft
  • layout_goneMarginTop
  • layout_goneMarginRight
  • layout_goneMarginBottom

假如A的宽度为72dp,即使A被标记为View.GONE,B的位置仍不变,如下所示:

即使A被标记为View.GONE,计算时A仍然是布局的一部分,那么,我们应该这么计算B的左侧距离容器侧面的长度为:A距离容器的侧面的长度+A的宽度+B距A的长度,为136dp。该值应该就是goneMargin的值,那么在XML中,可以这么做:

<android.support.constraint.ConstraintLayout     ...>    ...    <Button        android:layout_width="72dp"        android:layout_height="wrap_content"        android:layout_marginStart="32dp"        android:text="A"        ... />    <Button        app:layout_goneMarginLeft="136dp"        android:layout_marginStart="32dp"        android:text="B"        ... />    ...</android.support.constraint.ConstraintLayout>

当前情况是约束A视图的尺寸是已知的,如果约束视图的width/height类型为wrap_content时,就不能再xml中设置,需要在代码中,动态设置。对于如何动态设置约束,后续介绍…

带有链的线性视图组

在ConstraintLayout中,对线性试图组采用链的方式来处理,它们之间是彼此约束的。而,链又分为水平链和垂直链两种。例如,下图示出了两个彼此具有约束的视图,从而创建了水平链。

这里写图片描述

链头

在整个视图链中,尤其重要的是链头,其实际上是链中的第一个视图,即水平链中最左侧的视图和垂直链中的最顶端视图。

这里写图片描述

为什么说链头尤其重要呢?那是因为整体链的属性,在链头中设置,比如链的样式。

链的样式

所谓链的样式,就是链中的所有视图展开方式。在ConstraintLayout中允许以下几种方式展开链:

这里写图片描述

  1. Spread:视图均匀分布(占用余量之后)。这是默认值。
  2. Spread inside:第一个和最后一个视图贴在链的每一端的约束上,其余的都是均匀分布的。
  3. Weighted:当链样式设置为Spread或Spread inside时,可以通过将一个或多个视图设置为“match constraints”(0dp)来填充剩余空间。默认情况下,空间在设置为“match constraints”的每个视图之间均匀分布,但可以使用layout_constraintHorizo​​ntal_weight和layout_constraintVertical_weight属性为每个视图分配一个分布的权重,其与线性布局中layout_weight类似。所以权重最大的观点得到最大的空间;具有相同权重的视图获得相同的空间量。
  4. Packed:视图放置在一起(在边距计算之后)。然后,可以通过更改链的头部视图偏差来调整整个链条的偏差(左/右或上/下)

前面已经提到了,在链头中,设置属性layout_constraintHorizontal_chainStyle或layout_constraintVertical_chainStyle时,链的元素将根据指定的样式(默认为CHAIN_SPREAD)而排列。比如:

<android.support.constraint.ConstraintLayout     ...>    <Button        android:id="@+id/button25"        app:layout_constraintHorizontal_chainStyle="spread_inside"        app:layout_constraintEnd_toStartOf="@+id/button26"         .../>    <Button        android:id="@+id/button26"        app:layout_constraintStart_toEndOf="@+id/button25"        ..../></android.support.constraint.ConstraintLayout>

效果图:

这里写图片描述

快速创建链

前面,我们已经在XML中定义了一个水平链,只需要将链中的视图相互约束即可。在Layout Editor中,可以快速的创建一个链:

  1. 选择所有链中的视图
  2. 右键单击其中一个视图,然后选择Center Horizontally或Center Vertically,以分别创建水平链或垂直链

    这里写图片描述

另外一方面,对于链的样式,是在XML中定义的,我们也可以在Layout Editor中修改:

  1. 选择链中的任何视图
  2. 单击视图下方的链接按钮来切换Spread,Spread inside和Packed

这里写图片描述


值得注意的是:

  • 如果视图指定了链接约束边距,那么计算可用空间时,边距会考虑在内。在展开链时,边距将从自动可分配的空间中去除。
  • 链只有在链的每个端部被约束到同一轴线上的不同对象时才正常工作
  • 虽然,链的方向可以是垂直,的还可以是水平的,但是使用一个方向不会使所有视图在该方向上对齐。 因此,需要确保包含其他约束以实现链中每个视图的正确位置,例如对齐约束。
  • 链的默认在可用空间中平均分配给元素。如果一个或多个元素设置MATCH_CONSTRAINT,那么它们将使用可用的剩余空间(在它们之间相等)。属性layout_constraintHorizontal_weight和layout_constraintVertical_weight用来标明可用剩余空间的分配比例。
  • 由于ConstraintLayout并不支持ScrollLayout,尤其要注意链的空间分配,以避免视图被覆盖

到这里,ConstraintLayoput的基本使用以Layout Editor快速添加和修改约束已经讲解完了。

参考文档

  1. User ConstraintLayout to design your Android Views
  2. ConstraintLayout官方文档
  3. 使用 ConstraintLayout 构建自适应 UI
  4. 使用 Layout Editor 构建 UI
原创粉丝点击