资讯专栏INFORMATION COLUMN

ConstraintLayoutDemo【约束性布局知识梳理】【基于1.1.3】

番茄西红柿 / 1533人阅读

摘要:但是能对已经设置属性的控件进行特殊处理。这同样适用于垂直约束。尺寸在中添加当维度设置为时,默认行为是使结果大小占用所有可用空间。

版权声明:本文为HaiyuKing原创文章,转载请注明出处!

前言

在较新版本的Android Studio中新建项目默认使用 ConstraintLayout进行布局的。

ConstraintLayout是一个允许您以灵活的方式定位和调整小部件的ViewGroup。

注意: ConstraintLayout作为支持库提供,您可以在API级别9(Gingerbread)开始的Android系统上使用。

开发者指南梳理

以下内容参考《ConstraintLayout开发者指南》

一、相对定位【Relative positioning】

相对定位是在ConstraintLayout中创建布局的基本构建块之一。这些约束允许您将指定的控件(源控件)相对于另一个控件(目标控件)进行定位。您可以在水平和垂直轴上约束控件:

  • 水平方向: left、right、start、end
  • 垂直方向: top、bottom、text baseline

备注:start,end,left,right的区别

1、其中left/right代表一种绝对的对齐,start/end表示基于阅读顺序的对齐。 

说到阅读顺序又不得不提目前存在的主要阅读方式: 从左向右(LTR)和从右向左(RTL);

当使用left/right的时候,无论是LTR还是RTL,总是左/右对齐的;而使用start/end,如阅读顺序是从左到右(LTR)的国家,start在左边,在阅读顺序是从右到左(RTL)的国家(比如阿拉伯),start在右边。

2、当minSdkVersion>=17时,建议使用start/end来代替left/right;

当minSdkVersion<17时,旧的平台不支持RTL(从右到左--Right To Left),start/end属性是未知的,会被忽略,所以需要同时使用start/end和left/right。

以下是可用约束属性的列表

  • app:layout_constraintLeft_toLeftOf
  • app:layout_constraintLeft_toRightOf
  • app:layout_constraintRight_toLeftOf
  • app:layout_constraintRight_toRightOf
  • app:layout_constraintTop_toTopOf
  • app:layout_constraintTop_toBottomOf
  • app:layout_constraintBottom_toTopOf
  • app:layout_constraintBottom_toBottomOf
  • app:layout_constraintBaseline_toBaselineOf
  • app:layout_constraintStart_toEndOf
  • app:layout_constraintStart_toStartOf
  • app:layout_constraintEnd_toStartOf
  • app:layout_constraintEnd_toEndOf

用法解析:

1、上面的约束属性一般写在源控件上;

2、约束属性引用的id或者parent代表目标控件;

3、约束属性含义解读:将源控件的指定侧约束到目标控件的其中一侧。

比如:app:layout_constraintLeft_toLeftOf——当前源控件的左侧被约束(constraintLeft)到目标控件的左侧(toLeftOf)

例子1:将按钮B定位在按钮A的右侧,意味着系统将尝试让双方共享相同的位置。 

 例子2:按钮A和按钮B文本基线对齐,且按钮B在按钮A右侧




    

 

二、外边距【Margins】

如果设置了边距,则它们将应用于相应的约束(如果存在约束),系统将边距强制为目标和源边之间的空间。

什么叫边距应用于相应的约束(如果存在约束)?可以简单理解为android:layout_marginLeft和app:layout_constraintLeft_toLeftOf、app:layout_constraintLeft_toRightOf配合使用才会生效!保证设置边距的方向(leftrighttopbottomstartend)和相对定位约束的源控件的方向(leftrighttopbottomstartend)一致!剩下的以此类推!见例子2。

以下是布局边距属性的列表:

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

用法解析:

1、一般写在源控件上;

2、约束属性含义解读:当前控件(源控件)的指定侧距离与其具有约束关系的控件(目标控件)的其中一侧的空间值;

3、属性值必须是大于或者等于0;

4、当目标控件设置为可见性为gone的时候,源控件的边距仍有效;

例子1:将按钮B定位在按钮A的右侧,并且设置相距8dp

例子2:按钮B和按钮A文本基线对齐,且按钮B的左侧和按钮A的左侧对齐,且边距为8dp




    

如果去掉app:layout_constraintLeft_toLeftOf属性的话,设置的边距值是无效的,效果如下:

例子3:按钮A隐藏的情况下,按钮B在按钮A右侧,且边距为8dp【此时按钮B的外边距8dp仍是有效的】

三、连接到GONE控件时的边距【Margins when connected to a GONE widget】

 当约束目标控件的可见性为View.GONE时,可以配合使用以下属性设置不同边距值:

  • app:layout_goneMarginStart
  • app:layout_goneMarginEnd
  • app:layout_goneMarginLeft
  • app:layout_goneMarginTop
  • app:layout_goneMarginRight
  • app:layout_goneMarginBottom

和android:layout_MarginLeft等的区别就在于,当目标控件隐藏(GONE)的时候,android:layout_MarginLeft设置的外边距值还生效,而app:layout_goneMarginLeft设置的外边距值则会失效!

例子1:按钮A隐藏的情况下,按钮B在按钮A右侧,且边距为8dp【此时按钮B的外边距8dp是无效的】




    

 

四、可见性行为【Visibility behavior】

一般情况下,A控件设置 GONE属性后,A控件就不会出现在布局中了,B控件对A控件的android:layout_MarginXXX属性也就没有作用了。但是 ConstraintLayout 能对已经设置 GONE属性的控件进行特殊处理。当A控件设置 GONE之后,A控件相当于变成了一个点,B控件相对于对A的约束仍然是起作用的,B控件的android:layout_MarginXXX属性还是有作用的。

  • 对于gone的控件,它们的尺寸将被视为零(基本上,它们将被解析为一个点);
  • 如果已gone的控件对其他控件有约束,他们仍然会受到尊重,但已gone的控件任何边距都会等于零;

有时候,B控件是不希望相对于隐藏控件A的属性还起作用。这时候可以用到上面提到的app:layout_goneMarginXXX属性。

例子1:按钮A隐藏后,按钮A的外边距失效,均等于0

初始状态:



    

设置按钮A的外边距值为5dp:

设置按钮A隐藏状态GONE(可以发现按钮A的外边距5dp失效了):

    

 

五、居中定位【Centering positioning】

水平居中(parent表示相对于父节点):

app:layout_constraintLeft_toLeftOf="parent"

app:layout_constraintRight_toRightOf="parent"

垂直居中(parent表示相对于父节点):

app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"

上图是水平居中的示意图。

ConstraintLayout是如何处理“相反”的约束,比如下面的代码,除非ConstraintLayout恰好具有Button与之完全相同的大小,否则两个约束不能同时满足;在这种情况下发生的事情是,约束的作用就像是相反的力量将控件拉平; 这样控件最终将在父容器中居中。这同样适用于垂直约束。

例子1:按钮A水平居中



    

例子2:按钮B居中在按钮A中(如果按钮A和按钮B大小一致,那么按钮B就会和按钮A重叠)




    
五、偏差【Bias】

遇到这种相反的约束时的默认设置是使控件居中(也就是默认偏差50%); 但是您可以使用偏差属性调整定位以使一侧偏向另一侧:

可以使用的属性:

  • layout_constraintHorizontal_bias(水平偏差,取值范围:0.0~1.0)
  • layout_constraintVertical_bias(垂直偏差,取值范围:0.0~1.0)

所以,可以得知,偏差属性是需要和“反约束”属性一起使用的。那么什么是“反约束”属性呢?个人简单理解为下面的是反约束属性(仅供参考):

  • app:layout_constraintLeft_toLeftOf【反约束属性】
  • app:layout_constraintLeft_toRightOf
  • app:layout_constraintRight_toLeftOf
  • app:layout_constraintRight_toRightOf【反约束属性】
  • app:layout_constraintTop_toTopOf【反约束属性】
  • app:layout_constraintTop_toBottomOf
  • app:layout_constraintBottom_toTopOf
  • app:layout_constraintBottom_toBottomOf【反约束属性】
  • app:layout_constraintBaseline_toBaselineOf
  • app:layout_constraintStart_toEndOf
  • app:layout_constraintStart_toStartOf【反约束属性】
  • app:layout_constraintEnd_toStartOf
  • app:layout_constraintEnd_toEndOf【反约束属性】

例子1:按钮A水平居偏移30%,按钮B水平居中




    

 

六、圆形定位(1.1中增加)【Circular positioning (Added in 1.1)】

您可以以角度和半径距离约束控件中心相对于另一个控件中心。这允许您将控件放在圆上(如下图所示)。

     

可以使用以下属性:

  • app:layout_constraintCircle :引用的另一个控件(目标控件)ID值
  • app:layout_constraintCircleRadius :源控件的中心到其他控件(目标控件)中心的距离
  • app:layout_constraintCircleAngle :源控件应该处于哪个角度(以度为单位,从0到360)

例子1、按钮B在按钮A的30度角半径为100dp的位置上




    

 

七、尺寸约束【Dimensions constraints】 7.1、ConstraintLayout上的最大、最小尺寸约束【Minimum dimensions on ConstraintLayout】

你可以给ConstraintLayout设置以下最大、最小尺寸约束:

  • android:minWidth 设置布局的最小宽度
  • android:minHeight 设置布局的最小高度
  • android:maxWidth 设置布局的最大宽度
  • android:maxHeight 设置布局的最大高度

当 ConstraintLayout宽高设置为 wrap_content时,以上属性可以起作用。

按照字面的理解是在ConstraintLayout布局控件上设置这些属性,而不是控件上(比如Button、TextView等)设置这些属性。可能这些属性更适合用在ConstraintLayout布局控件上吧。普通控件上也是可以使用的,但是有问题。

例子1:文本A所在的ConstraintLayout区域设置最小宽高,文本B所在的ConstraintLayout区域设置最大宽高



    

        

    

    

        

    

例子2:直接设置文本A的最小宽高,设置文本B的最大宽高【问题:文本B的展现不符合预期】



    

    

例子3:按钮A设置最小宽高,按钮B设置最大宽高(注意:Button控件系统默认设置了最小宽高:比如宽88dp,高48dp,去style.xml中AppTheme的父主题里面查看)



    
7.2、控件尺寸约束【Widgets dimension constraints】

我们可以通过以下3种不同方式设置android:layout_width和android:layout_height属性值指定控件的尺寸。

  • 使用指定数值(例如52dp或@dimens/toolbarheight);
  • 使用wrap_content,这将要求控件自己计算自己的大小;
  • 使用0dp,相当于match_constraint(在1.1.3版本中,使用match_constraint找不到,所以还是使用0dp,注意不能使用match_parent,有些地方0dp和match_parent是不一样的)

上图中,(a)是wrap_content,(b)是0dp,如果设置了边距,则在计算中将考虑它们(图8,(c)中的0dp。

重要提示: match_parent不建议用于ConstraintLayout中的控件。可以通过使用match_constraint设置为相应的left/right或top/bottom 约束来定义类似的行为——"parent"。

但是在com.android.support.constraint:constraint-layout:1.1.3中,android:layout_width和android:layout_height属性没有这个match_constraint值。

7.3、wrap_content:强制约束(在1.1中添加)【WRAP_CONTENT : enforcing constraints (Added in 1.1)】

如果将维度设置为WRAP_CONTENT,则在1.1之前的版本中,它们将被视为文字维度 - 这意味着约束不会限制生成的维度。虽然通常这足够(并且更快),但在某些情况下,您可能希望使用WRAP_CONTENT,但仍然强制执行约束以限制生成的维度。在这种情况下,您可以添加一个相应的属性:

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

例子1:文本B在文本A的下方,并且文本B的左侧约束文本A的右侧,文本B的右侧约束parent的右侧(这样可以保证文本全部显示出来)



    

    

 如果去掉app:layout_constrainedWidth="true",效果如下:文本B的左右约束失效,且文本显示不全!



    

 如果继续去掉app:layout_constraintRight_toRightOf="parent",效果如下:文本B的左右约束还在,但是文本显示不全



    

 

7.4、match_constraint(0dp)尺寸(在1.1中添加)【MATCH_CONSTRAINT dimensions (Added in 1.1)】

 当维度设置为时match_constraint(0dp),默认行为是使结果大小占用所有可用空间。还有几个额外的修饰符:

  • app:layout_constraintWidth_min和app:layout_constraintHeight_min:将设置最小宽高值【可以是数值,比如100dp,也可以是“wrap”——它将使用与其相同的值WRAP_CONTENT】
  • app:layout_constraintWidth_max和app:layout_constraintHeight_max:将设置最大宽高值【可以是数值,比如100dp,也可以是“wrap”——它将使用与其相同的值WRAP_CONTENT】
  • app:layout_constraintWidth_percent和app:layout_constraintHeight_percent:宽高相对于父容器的百分比【数值是0~1之间的数字,比如0.3】

 注意:使用上面的min、max和percent属性的时候,需要一个方向下只含有一个约束,不能含有两个约束(percent属性可以两个约束)。

比如,app:layout_constraintWidth_min、app:layout_constraintWidth_max,想要生效的话,控件只需要app:layout_constraintLeft_toLeftOf(隐形声明也可以)即可,不能同时含有app:layout_constraintRight_toRightOf="parent"。

例子1:设置文本A的最小宽度值,设置文本B的最大宽度值【可以理解为从左侧开始,设置最小、最大宽度值】



    

    

例子2:设置文本A、文本B的宽度占父容器的百分比【可以理解为从左侧开始,文本占百分比】



    

    

 

八、设置宽高比例【Ratio】

当 android:layout_width或者 android:layout_height设置为0dp时,还可以通过 app:layout_constraintDimensionRatio设置宽高比例。该比例表示 width:height的值。

该比率可表示为:

  • 浮点值,表示宽度和高度之间的比率(比如:1.0F)
  • “宽度:高度”形式的比率(比如:1:1)

注意:使用app:layout_constraintDimensionRatio属性的时候还是需要至少一个约束,比如可能会忽略的app:layout_constraintLeft_toLeftOf="parent"。

例子1:文本A、文本B宽高比是1:1



    

    

如果两个尺寸都设置为MATCH_CONSTRAINT(0dp),您也可以使用比率。

在这种情况下,系统设置满足所有约束的最大尺寸并保持指定的纵横比。要根据另一个特定边的尺寸限制一个特定边,可以预先附加W,“或” H,表示想要约束的宽度或高度。

例如,如果一个尺寸受两个目标约束,则可以指示应该约束哪一边,通过 在比率前添加字母W(用于约束宽度)或H(用于约束高度),用逗号分隔。

例子2:文本A宽度全屏,根据16:9的比率设置高度(要约束的是H)



    

九、链【Chains】

在横轴或或者竖轴上的控件相互约束时,可以组成一个链式约束。链在单个轴(水平或垂直)上提供类似行的行为。另一个轴可以独立约束。

创建一个链

如果一组控件通过双向连接链接在一起,则它们被视为链。

链头
链由链的第一个元素(链的“头部”)上设置的属性控制:

链头是水平链的最左侧控件,垂直链的最顶部控件。

链的样式

可以通过 app:layout_constraintHorizontal_chainStyleapp:layout_constraintVertical_chainStyle设置链式控件的样式。这个属性有点像 LinearLayout中的 weight 属性平分布局。

  • spread模式:元素将展开(默认样式);
  • spread_inside模式: 类似spread模式,但链的端点不会分散;
  • 含有权重spread模式:如果设置了某个或某些控件MATCH_CONSTRAINT(0dp),这个或这些控件将分割可用空间;
  • packed模式:链条的元素将被包装在一起。然后,子项的水平或垂直偏差属性将影响打包元素的定位;

例子1:spread模式



    

    

    

例子2:spread_inside模式



    

    

    

例子3:含有权重spread模式

加权链
链的默认行为是在可用空间中平均分布元素。如果使用了一个或多个元素MATCH_CONSTRAINT(0dp),它们将使用可用的空白空间(在它们之间平均分配)。

属性app:layout_constraintHorizontal_weight和app:layout_constraintVertical_weight 将控制如何将空间利用的元素之间进行分配MATCH_CONSTRAINT(0dp)。例如,在包含两个元素的链上使用MATCH_CONSTRAINT,第一个元素使用权重2,第二个元素使用权重1,第一个元素占用的空间将是第二个元素占用的空间的两倍。

例子3.1:文本B和文本C平分可用空白空间



    

    

    

 例子3.2:文本B占2份可用空白空间,文本C占1份可用空白空间



    

    

    

 例子4:packed模式

 



    

    

    

例子5:含有边距的packed模式

链中的边距
如果在链上指定了边距,则会考虑它们。在扩散链的情况下,将从分配的空间中扣除边距。

边距和链条(1.1)
在链中的元素上使用边距时,边距是相加的。

例如,在水平链上,如果一个元素定义了10dp的右边距而下一个元素定义了5dp的左边距,则这两个元素之间产生的边距为15dp。

在计算链用于定位项目的剩余空间时,会同时考虑项目及其边距。剩余空间不包含已设置的边距。



    

    

    

 十、辅助布局【Virtual Helper objects】

Guideline对象允许您创建相对于ConstraintLayout容器定位的水平和垂直指南。然后可以通过将小部件约束到这样的指导来定位小部件。在1.1中,Barrier也Group被添加了。

10.1、 Guideline

参考《https://developer.android.google.cn/reference/android/support/constraint/Guideline》

Guideline表示约束布局的指导帮助对象的实用工具类。Guideline不显示在设备上(它们被标记为View.GONE),并且仅用于布局目的,它们只在ConstraintLayout中工作。

Guideline可以设置类似于LinearLayout中的orientation属性,设置垂直方向或者水平方向,若设置垂直方向,则水平方向的高度为0,若设置为水平方向,则垂直方向的宽度为0。

Guideline可以是水平的,也是可以是竖直的。通过设置android:orientation属性:

  • 垂直Guideline的宽度为0,高度为父级ConstraintLayout的高度。
  • 水平Guideline的高度为0,宽度为父级ConstraintLayout的宽度。

Guideline 具有以下的三种定位方式:

  • app:layout_constraintGuide_begin【距离父容器起始位置的距离(左侧或顶部)】
  • app:layout_constraintGuide_end【距离父容器结束位置的距离(右侧或底部)】
  • app:layout_constraintGuide_percent【距离父容器宽度或高度的百分比,取值范围:0.0~1.0】

例子1:按钮A和按钮B分别在屏幕一半区域的中间



    

    

 

10.2、 Barrier(Added in 1.1)

参考《https://developer.android.google.cn/reference/android/support/constraint/Barrier》

Barrier,直译为障碍、屏障。在约束布局中,可以使用app:constraint_referenced_ids属性来引用多个带约束的组件,从而将它们看作一个整体。设置app:barrierDirection属性指定方向。

Barrier是一个虚拟的辅助控件,它可以阻止一个或者多个控件越过自己,就像一个屏障一样。当某个控件要越过自己的时候,Barrier会自动移动,避免自己被覆盖。

例子1:app:barrierDirection="start"效果【注意:建议添加上app:layout_constraintRight_toRightOf="@id/barrier"




    


    

    

例子2:app:barrierDirection="end"效果【注意:建议添加上app:layout_constraintRight_toRightOf="@id/barrier"】




    


    

    

例子3:表单样式,左侧标签,右侧输入框




    

    

    

    

    
            
                     
             
               

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/2342.html

相关文章

  • Android开发 - 掌握ConstraintLayout(十一)复杂动画!如此简单!

    摘要:动画我们这里通过一个示例来说明动画的创建。效果代码评分分无敌破坏王这个页面是我们执行动画结束后的样子。如果需要复杂布局的动画切换,这种方式的优势就非常明显。显然这样会大大增加复杂度和代码量。 介绍 本系列我们已经介绍了ConstraintLayout的基本用法。学习到这里,相信你已经熟悉ConstraintLayout的基本使用了,如果你对它的用法还不了解,建议您先阅读我之前的文章。 ...

    LuDongWei 评论0 收藏0
  • Flutter中的布局绘制流程简析(二)

    摘要:所以这里为时把指向自身,因为自身的肯定符合约束的条件,也是提高布局效率的一个关键点。举一个栗子,在中先让布局之后,根据的,来设置自身的。意味着父控件要依赖子控件的,可能父控件的布局要根据子控件的来做调整。 布局约束 刚才所说的改变一个控件的高度,有时候并不像刚才所说只是改变一下属性就能起作用,这里涉及到一个布局约束规则。直接看BoxConstraints的实现,这个类主要定义了minW...

    icattlecoder 评论0 收藏0
  • 安卓组件控件

    摘要:优点这样做的好处是无需适配,不用担心便宜问题缺点是不同的界面要写不同的基本使用学习记录开车指南之最全实用案例学习整理,很全安卓约束控件扁平化布局入门好棒的干货一个强悍而优美的视频播放器最近项目中有需要用在线视频播放。 ExpandableListView一点点 学习ExpandableListView简单用法 FloatingDragButton:炫酷的拖拽浮动按钮 IOS的Assis...

    tainzhi 评论0 收藏0
  • PHP基础知识梳理

    摘要:双引号单引号区别双引号解释变量,单引号不解释变量双引号里插入单引号,其中单引号里如果有变量的话,变量解释双引号的变量名后面必须要有一个非数字字母下划线的特殊字符,或者用讲变量括起来,否则会将变量名后面的部分当做一个整体,引起语法错误能使单引 双引号单引号区别 双引号解释变量,单引号不解释变量双引号里插入单引号,其中单引号里如果有变量的话,变量解释双引号的变量名后面必须要有一个非数字、字...

    luoyibu 评论0 收藏0
  • PHP基础知识梳理

    摘要:双引号单引号区别双引号解释变量,单引号不解释变量双引号里插入单引号,其中单引号里如果有变量的话,变量解释双引号的变量名后面必须要有一个非数字字母下划线的特殊字符,或者用讲变量括起来,否则会将变量名后面的部分当做一个整体,引起语法错误能使单引 双引号单引号区别 双引号解释变量,单引号不解释变量双引号里插入单引号,其中单引号里如果有变量的话,变量解释双引号的变量名后面必须要有一个非数字、字...

    wemallshop 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<