笔记74 | 学习掌握ConstraintLayout的基本属性

最近一个礼拜业余时间都在搞我的淘宝店铺,有兴趣的都可搜一下:吉安车品,主营汽车脚垫/后备箱垫/座垫,还在打基础阶段,不急,慢慢搞,当业余爱好去买卖;当然吃饭手艺功夫自然也不能丢,为下个月的变数准备,今天开始复习/学习一些基础内容,今天的笔记是ConstraintLayout的几个属性。

1、Circular positioning(圆形定位)

标题后面的中文是自己翻译的,可能不是很准确。

官方文档是这么介绍的:

You can constrain a widget center relative to another widget center, at an angle and a distance. This allows you to position a widget on a circle

我是这么理解的,您可以将一个控件的中心以一定的角度和距离约束到另一个控件的中心,相当于在一个圆上放置一个控件。

示例代码如下:

<Button android:id="@+id/buttonA" ... />
  <Button android:id="@+id/buttonB" ...
      //引用的控件ID
      app:layout_constraintCircle="@+id/buttonA"
      //圆半径
      app:layout_constraintCircleRadius="100dp"
      //偏移圆角度  水平右方向为0逆时针方向旋转
      app:layout_constraintCircleAngle="45" />

效果图:

图文并茂,理解起来较容易些。圆形定位使用其他布局是很难实现的(除自定义外),该功能在实际的开发中用的并不多,可以用来实现类似钟表的效果。该功能只不过是约束布局的冰山一角,且往下看。

2、WRAP_CONTENT : enforcing constraints(强制约束)

官方文档是这么介绍的:

If a dimension is set to WRAP_CONTENT, in versions before 1.1 they will be treated as a literal dimension -- meaning, constraints will not limit the resulting dimension. While in general this is enough (and faster), in some situations, you might want to use WRAP_CONTENT, yet keep enforcing constraints to limit the resulting dimension. In that case, you can add one of the corresponding attribute

英文一直是我的弱项,我是这么理解的,1.1.0 版本之前是没有这个功能的,说的是控件的宽设置为 WRAP_CONTENT (包裹内容)时,如果实际宽度超过了约束的最大宽度,那么约束会失效(高同理),为了防止约束失效,增加了以下属性:

  • app:layout_constrainedWidth=”true|false” //默认false
  • app:layout_constrainedHeight=”true|false” //默认false

官网并没有过多说明,那么怎么去理解呢,接下来以 app:layout_constrainedWidth属性来看两个例子。

a、例子

B 控件位于 A 控件右侧与屏幕右侧的中间。代码如下:

<Button
        android:id="@+id/bt_1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="16dp"
        android:text="A"
        app:layout_constraintLeft_toLeftOf="parent"/>

    <Button
        android:id="@+id/bt_2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="B"
        app:layout_constraintLeft_toRightOf="@+id/bt_1"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/bt_1"/>

那么我改变 B 控件的内容,使宽度增大:

通过效果图可以得出,给 B 控件添加的左右约束失效。为了防止约束失效,在 1.1.0 版本中新增了 app:layout_constrainedWidth="true"属性。注意控件的左右都应该有约束条件, 如下:

app:layout_constraintLeft_toRightOf="@+id/bt_1" //控件的左边位于xx控件的右边
app:layout_constraintRight_toRightOf="parent"   //控件的右边位于xx控件的右边

效果图如下:

app:layout_constrainedWidth=”true” 会导致渲染变慢,变慢时长可忽略不计。

b、例子

产品部的美女提出了这样的一个需求,看图:

AB 两控件, BA 的右侧,随着 AB 宽度的增加, B 始终在 A 的右侧,当 AB 控件的宽度之和大于父控件的宽度时, B 要求被完全显示,同时 A 被挤压。我相信大家肯定也遇到过类似的需求,使用线性布局,相对布局会增加层级的嵌套,影响渲染效率,那么 ConstraintLayout又是怎么去实现的呢?

代码如下:

<Button
        android:id="@+id/bt_1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
        app:layout_constrainedWidth="true" // 设置为true
        app:layout_constraintHorizontal_bias="0" // 设置水平偏好为0
        app:layout_constraintHorizontal_chainStyle="packed" //设置链样式
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@+id/bt_2"
        app:layout_constraintTop_toTopOf="parent"/>

    <Button
        android:id="@+id/bt_2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="BBBBBBBBBBB"
        app:layout_constrainedWidth="true"
        app:layout_constraintLeft_toRightOf="@+id/bt_1"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>

结合了以下两个属性来达到了需求的效果:

  • app:layoutconstraintHorizontalchainStyle=”packed” //设置链样式
  • app:layoutconstraintHorizontalbias=”0” // 设置水平偏好为0

接下来简单介绍下 chainbias 在后续的百分比布局中会讲到。

Chains(链)

Chains provide group-like behavior in a single axis (horizontally or vertically). The other axis can be constrained independently.

链使我们能够对一组在水平或竖直方向互相关联的控件的属性进行统一管理。成为链的条件:一组控件它们通过一个双向的约束关系链接起来。 并且链的属性是由一条链的头结点控制的,如下:

代码如下:

<Button
        android:id="@+id/bt_1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="A"
        //默认样式
        app:layout_constraintHorizontal_chainStyle="spread"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@+id/bt_2" />

    <Button
        android:id="@+id/bt_2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="B"
        app:layout_constraintLeft_toRightOf="@+id/bt_1"
        app:layout_constraintRight_toRightOf="parent" />

那么链有哪些样式,以下图来诠释:

Weighted 样式下,宽或高的维度应设置为 match_parent(0dp)

3、MATCH_CONSTRAINT dimensions(填充父窗体约束)

官方文档是这么介绍的:

When a dimension is set to MATCH_CONSTRAINT, the default behavior is to have the resulting size take all the available space. Several additional modifiers are available

在约束布局中宽高的维度 match_parent0dp 代替,默认生成的大小占所有的可用空间。那么有以下几个属性可以使用:

  • layoutconstraintWidthmin and layoutconstraintHeightmin //设置最小尺寸
  • layoutconstraintWidthmax and layoutconstraintHeightmax //设置最大尺寸
  • layoutconstraintWidthpercent and layoutconstraintHeightpercent //设置相对于父类的百分比

开发中有这样一个需求,位于父控件的中间且宽度为父控件的一半,那么我们可以这么去实现:

4、goneMargin(隐藏边距)

当约束目标的可见性为 View.GONE时,还可以通过以下属性设置不同的边距值:

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

如以下例子:

Margins and chains (in 1.1), Optimizer (in 1.1) 略。

5、约束之百分比布局

百分比布局大家肯定不会陌生,由于 Android的碎片化非常严重,那么屏幕适配将是一件非常令人头疼的事情,百分比适配也就应运而生,约束布局同样也可以实现百分比的功能,并且更加强大,灵活。

经常我们会遇到这样的需求,个人主页要求顶部的背景图宽高 16:9 来适配,如下图:

约束布局的实现方式如下:

<!-- "W,9:16" 同样的效果 -->
    <ImageView
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:scaleType="centerCrop"
        android:src="@mipmap/icon"
        app:layout_constraintDimensionRatio="H,16:9"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>

新增了如下属性:

app:layout_constraintDimensionRatio="H,16:9"

官网的介绍是这样的:

You can also define one dimension of a widget as a ratio of the other one. In order to do that, you need to have at least one constrained dimension be set to 0dp (i.e., MATCH_CONSTRAINT), and set the attribute layout_constraintDimensionRatio to a given ratio

意思是说约束布局支持子控件设置宽高比,前提条件是至少需要将宽高中的一个设置为 0dp。为了约束一个特定的边,基于另一个边的尺寸,可以预先附加W,或H以逗号隔开。

然后需求变动,需要将宽度调整为屏幕的一半:

只需要新增 app:layout_constraintWidth_percent="0.5" 属性。

接着需要控件左对齐:

同时新增了 app:layout_constraintHorizontal_bias="0"属性。

官网的介绍如下:

The default when encountering such opposite constraints is to center the widget; but you can tweak the positioning to favor one side over another using the bias attributes:

具有相反方向约束的控件,我们可以改变偏好值,来调整位置偏向某一边。有点类似 LinearLayoutweight属性。

最后需要调整控件距离顶部的高度为父控件高度的20%:

这里用到了虚拟辅助类 Guideline ,同时 1.1.0版本还添加了两个虚拟类 BarrierGroup。它们是虚拟对象,并不会占用实际的空间,但可以帮助我们更好更精细地控制布局。综上的需求变化我们可以相对于父控件任意改变控件大小,控件的位置,从而能够更好的适配各大屏幕。

5、Guideline

Guideline 与 LinearLayout 类似可以设置水平或垂直方向, android:orientation="horizontal"android:orientation="vertical",水平方向高度为 0,垂直方向宽度为 0。Guideline 具有以下的三种定位方式:

  • layoutconstraintGuidebegin 距离父容器起始位置的距离(左侧或顶部)
  • layoutconstraintGuideend 距离父容器结束位置的距离(右侧或底部)
  • layoutconstraintGuidepercent 距离父容器宽度或高度的百分比

例如,设置一条垂直方向距离父控件左侧为100dp的Guideline:

<android.support.constraint.Guideline
        android:layout_width="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_begin="100dp"
        android:layout_height="wrap_content"/>

效果图如下:

6、Barrier

Barrier,直译为障碍、屏障。在约束布局中,可以使用属性 constraint_referenced_ids属性来引用多个带约束的组件,从而将它们看作一个整体,Barrier 的介入可以完成很多其他布局不能完成的功能,如下:

开发中有这样的一个需求,看下图:

姓名,联系方式位于 A 区域(随着文本的宽度变化 A 区域的宽度也随之变化),B 区域在 A 区域的右侧。使用传统的布局方式实现嵌套过多,布局不够优雅。那么我们一起来看看约束布局是怎么去实现的:

<TextView
        android:id="@+id/tv_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="姓名:"
        app:layout_constraintBottom_toBottomOf="@+id/et_name"
        app:layout_constraintTop_toTopOf="@+id/et_name"/>

    <TextView
        android:id="@+id/tv_contract"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:text="联系方式:"
        app:layout_constraintBottom_toBottomOf="@+id/et_contract"
        app:layout_constraintTop_toTopOf="@+id/et_contract"/>

    <EditText
        android:id="@+id/et_name"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:hint="请输入姓名"
        app:layout_constraintLeft_toLeftOf="@+id/barrier"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>

    <EditText
        android:id="@+id/et_contract"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:hint="请输入联系方式"
        app:layout_constraintLeft_toLeftOf="@+id/barrier"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/et_name"/>

    <android.support.constraint.Barrier
        android:id="@+id/barrier"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:barrierDirection="right"
        app:constraint_referenced_ids="tv_name,tv_contract"/>

barrierDirection 指定方向, constraint_referenced_ids引用的控件 id(多个id以逗号隔开)。

7、Group

Group用于控制多个控件的可见性。

e.g:

android:visibility="gone" 那么 A,B 控件都会隐藏。

原文发布于微信公众号 - 项勇(xiangy_life)

原文发表时间:2018-05-23

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Sorrower的专栏

界面无小事(九): 做个好看的伸缩头部

742
来自专栏哈雷彗星撞地球

(译)快速指南:用UIViewPropertyAnimator做动画

翻译自:QUICK GUIDE: ANIMATIONS WITH UIVIEWPROPERTYANIMATOR 译者:Haley_Wong

453
来自专栏腾讯社交用户体验设计

实现下划线的N个姿势

1404
来自专栏Java3y

十道算法题[二]

前言 清明不小心就拖了两天没更了~~ 这是十道算法题的第二篇了~上一篇回顾:十道简单算法题 最近在回顾以前使用C写过的数据结构和算法的东西,发现自己的算法和数据...

3179
来自专栏编程

小白必知什么是css和盒模型

CSS盒模型概念 CSS 盒模型也叫框模型 (Box Model) ,包含了元素内容(content)、内边距(padding,也叫填充)、边框(border)...

1837
来自专栏阿凯的Excel

Excel的匹配函数全应用

今天会和大家分享日常使用频率最高匹配函数用法,谈到匹配函数,首先想到的就是Vlookup,嗯,今天就是要分享Vlookup和他的小伙伴们的应用。 ? ...

3154
来自专栏守候书阁

个人总结(css3新特性)

css3这个相信大家不陌生了,是个非常有趣,神奇的东西!有了css3,js都可以少写很多!我之前也写过关于css3的文章,也封装过css3的一些小动画。个人觉得...

1241
来自专栏deepcc

emmet(Zen coding)前端写代码神器

3557
来自专栏北京马哥教育

Python 算法实战系列:栈

学Python最简单的方法是什么?推荐阅读:Python开发工程师成长魔法 栈(stack)又称之为堆栈是一个特殊的有序表,其插入和删除操作都在栈顶进行操作,并...

3078
来自专栏葡萄城控件技术团队

响应式设计(Response Web Design)实践

前一篇响应式设计(Response Web Design)浅谈提到了响应式设计的由来和应用场景。本文聊一聊如何实现。 如何让自己的网站也响应式Web设计,可以响...

2187

扫码关注云+社区