ConstraintLayout 布局应用

ConstrainLayout官方文档

https://developer.android.google.cn/reference/android/support/constraint/ConstraintLayout.html

目录

ConstraintLayout常用标签

1、相对位置约束

2、Circular positioning (Added in 1.1) 圆形定位

3、Dimensions constraints (尺寸约束)

4、Chains (链)

5、Barrier (屏障)

6、Group

7、placeholder 占位

8、优化器

9、ConstraintSet运用


ConstraintLayout常用标签

1、相对位置约束

上图标明了控件的边框,以及文字的基线

可用的约束列表

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

以最后一个下划线区分,layout_constraintXXX 代表当前控件 toXXXOf代表的是相比较的控件/父布局

举个简单的例子

A位于父布局的中间位置,四条边都约束于parent

B控件 左边约束于A控件扽左边,右边约束于A控件的右边,上边约束于A控件的下边。

 

    <Button
            android:text="A"
            android:layout_width="151dp"
            android:layout_height="120dp"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            android:id="@+id/button"
    />
    <Button
            android:text="B"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/button2"
            app:layout_goneMarginTop="20dp"
            app:layout_constraintEnd_toEndOf="@+id/button"
            app:layout_constraintStart_toStartOf="@+id/button"
            app:layout_constraintTop_toBottomOf="@+id/button"
            android:layout_marginTop="144dp"
            app:layout_constraintHorizontal_bias="1.0"/>

 

细心的你可能看到了B设置了marginTop,144dp,那 layout_goneMarginTop代表什么意思呢?

它的意义在于如果A控件可见行设为Gone了,那么B设置的margin值全部失效,这个layout_goneMargin可以重新为B控件设置新的margin值,可以把它当作layout_margin的备胎,不信你可以试试看哦。

左右拖动B控件,可调节 app:layout_constraintHorizontal_bias 大小,控制B控件所处位置,默认值是0.5,位于A控件中间的位置。

其他的约束都好理解,那layout_constraintBaseline_toBaselineOf是什么鬼呢?

这个标签是用来设置文字对齐的,看图说话

<TextView
            android:text="文字1"
            android:layout_width="99dp"
            android:layout_height="107dp"
            android:id="@+id/textView"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            />
    <TextView
            android:text="文字2"
            android:layout_width="109dp"
            android:layout_height="79dp"
            android:id="@+id/textView2"
            app:layout_constraintEnd_toEndOf="parent"
            android:layout_marginRight="92dp"
            android:layout_marginEnd="92dp" 
            app:layout_constraintBaseline_toBaselineOf="@+id/textView"/>

2、Circular positioning (Added in 1.1) 圆形定位

官方解释 You can constrain a widget center relative to another widget center, at an angle and a distance. 

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

看图说话

有下面3个属性可用

  • layout_constraintCircle : 所引入的控件id
  • layout_constraintCircleRadius : 圆半径
  • layout_constraintCircleAngle : 偏移角度(in degrees, from 0 to 360)

大家看下面这个用户头像布局怎么做?

<ImageView
            android:id="@+id/image"
            android:layout_width="60dp"
               android:layout_height="60dp"
               android:src="@mipmap/img_logo_personal_center"
               app:layout_constraintEnd_toEndOf="parent"
               app:layout_constraintStart_toStartOf="parent"
               app:layout_constraintTop_toTopOf="parent"
               android:layout_marginTop="120dp"
               />

     <TextView
              android:id="@+id/vip"
              android:layout_width="30dp"
              android:text="VIP"
              android:textColor="#f00"
              android:textStyle="bold"
              android:textSize="18sp"
              android:layout_height="30dp"
              app:layout_constraintCircle ="@id/image"
              app:layout_constraintCircleRadius="35dp"
              app:layout_constraintCircleAngle="135"
     />

3、Dimensions constraints (尺寸约束)

  • android:minWidth set the minimum width for the layout
  • android:minHeight set the minimum height for the layout
  • android:maxWidth set the maximum width for the layout
  • android:maxHeight set the maximum height for the layout

当控件的dimensions(宽高维度)设置为WRAP_CONTENT时,可使用上面的标签,限定最大、最小尺寸。

1、 控件尺寸约束

设置android:layout_width and android:layout_height attributes in 3 different ways:

1、固定尺寸    (eg:20dp)

2、WRAP_CONTENT   (它要求控件计算自己的大小)

3、 0dp, 也就是  "MATCH_CONSTRAINT"

a:wrap_content

b: 0dp

c:设置了边距的 0dp

官方不建议使用MATCH_PARENT,可以用MATCH_CONSTRAINT代替。

2、 enforcing constraints (强约束)

当一个控件设为wrap_content时,再添加约束尺寸是不起效果的。如需生效,需要设置如下属性为true:

  • app:layout_constrainedWidth=”true|false”
  • app:layout_constrainedHeight=”true|false”

3、MATCH_CONSTRAINT dimensions (Added in 1.1)

当维度设置为时MATCH_CONSTRAINT,默认行为是让生成的大小占用所有可用空间。有几个额外的修饰符可用:

  • layout_constraintWidth_minlayout_constraintHeight_min:将设置此维度的最小尺寸
  • layout_constraintWidth_maxlayout_constraintHeight_max:将设置此维度的最大尺寸
  • layout_constraintWidth_percentlayout_constraintHeight_percent:将设置此维度的大小为父级的百分比

     

<Button
            android:text="Button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintWidth_min="200dp"
            app:layout_constraintHeight_min="200dp"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constrainedWidth="true"
            app:layout_constrainedHeight="true"
            android:id="@+id/button4"/>

   <Button
            android:text="Button"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            app:layout_constraintWidth_max="200dp"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            android:id="@+id/button4"/>

4、Percent dimension

要使用百分比,您需要设置以下内容:

  • 维度应该设置为 MATCH_CONSTRAINT (0dp)
  • 默认值设置百分比percent app:layout_constraintWidth_default="percent" or app:layout_constraintHeight_default="percent"
  • 设置占用父布局百分比 layout_constraintWidth_percent or layout_constraintHeight_percent 设置为介于0和1之间的值

 

5、Ratio (可设置控件宽高比例)

使用这个属性有个条件 :您至少需要将一个约束维度设置为0dp(即MATCH_CONSTRAINT),并将该属性layout_constraintDimensionRatio设置为给定比率。

下面我们设置一个Button的宽高比为3:1


   <Button
            android:text="Button"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            app:layout_constraintDimensionRatio="3:1"
            android:id="@+id/button5"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"/>

 

比例可以表示为:

  • 浮点值,表示宽度和高度之间的比率
  • “宽度:高度”形式的比率

如果两个维都设置为MATCH_CONSTRAINT(0dp),您也可以使用比率。在这种情况下,系统设置满足所有约束条件的最大尺寸并保持指定的宽高比。为了约束一个基于另一个维的特定边,你可以预先附加W,“或者H,分别限制宽度或者高度。

<Button
            android:text="Button"
            android:layout_width="0dp"
            android:layout_height="0dp"
            app:layout_constraintDimensionRatio="H,4:1"
            android:id="@+id/button5"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"/>

这里限定高度,为宽度的的1/4

4、Chains (链)

有两种链,水平或垂直

一个链包含了多个视图,它允许链中的视图共享空间,并控制可用空间在它们之间如何分配。该效果与 LinearLayout 的 Weiget 类似,但是链的作用远远超过它。

<Button
            android:text="Button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            tools:layout_editor_absoluteY="137dp"
            android:id="@+id/button9"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintEnd_toStartOf="@+id/button10"/>
    <Button
            android:text="Button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            tools:layout_editor_absoluteY="137dp"
            android:id="@+id/button10"
            app:layout_constraintStart_toEndOf="@+id/button9"
            app:layout_constraintEnd_toStartOf="@+id/button11"/>
    <Button
            android:text="Button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            tools:layout_editor_absoluteY="137dp"
            android:layout_marginRight="16dp"
            android:layout_marginEnd="16dp"
            app:layout_constraintEnd_toEndOf="parent"
            android:id="@+id/button11"
            app:layout_constraintStart_toEndOf="@+id/button10"
            />

链头是指链中第一个控件 ,头是水平链最左边的部件,也是垂直链最顶端的部件。

设置链式Style

为链条的第一个元素设置属性layout_constraintHorizontal_chainStylelayout_constraintVertical_chainStyle

链条的行为将根据指定的样式(默认为CHAIN_SPREAD)更改。

  • CHAIN_SPREAD - 元素将被分散(默认样式)
  • CHAIN_SPREAD_INSIDE - 与CHAIN_SPREAD类似,但链条的端点不会被分散
  • Weighted chain - 在CHAIN_SPREAD模式下,如果某些小部件设置为MATCH_CONSTRAINT,它们将拆分可用空间
  • CHAIN_PACKED - 链条的元素将被包装在一起。子的水平或垂直偏向属性将影响打包元素的位置

加权链(Weighted chain)

与LinearLayout的权重基本一致

链的默认行为是在可用空间中均匀分布元素。如果一个或多个元素正在使用MATCH_CONSTRAINT,他们将填充可用的空白区域(在它们之间平均分配)。属性layout_constraintHorizontal_weightlayout_constraintVertical_weight 将控制如何将空间利用的元素之间进行分配MATCH_CONSTRAINT。例如,在包含两个使用MATCH_CONSTRAINT元素的链中,第一个元素的权重为2,第二个权重为1,第一个元素占用的空间将是第二个元素的两倍。

在链中设置边距

在链中的元素上使用边距时,边距是可加的:

  • 例如在水平链上,如果一个元素定义了10dp的右边距,而下一个元素的左边距为5dp,则这两个元素之间的结果边距将为15dp
  • 在计算链条用于放置物品的剩余空间时,会将物品加上其边距一起考虑,剩余空间不包含边距。

 

5、Guideline

Guidelines 是一条对实际显示界面不可见的线。用处是帮助我们的控件增加约束,可以设置水平或垂直方向。

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

layout_constraintGuide_begin 距离父容器起始位置的距离(左侧或顶部)
layout_constraintGuide_end 距离父容器结束位置的距离(右侧或底部)
layout_constraintGuide_percent 距离父容器宽度或高度的百分比

比如我们想让Button位置位于右下角,举例底部和容器右边 只有20%距离

<androidx.constraintlayout.widget.Guideline android:layout_width="wrap_content"
                                                android:layout_height="wrap_content"
                                                android:id="@+id/guideline1"
                                                android:orientation="vertical"
                                                app:layout_constraintGuide_percent="0.8"/>
    <androidx.constraintlayout.widget.Guideline android:layout_width="wrap_content"
                                                android:layout_height="wrap_content"
                                                android:id="@+id/guideline2"
                                                android:orientation="horizontal"
                                                app:layout_constraintGuide_percent="0.8"/>
    <Button
            android:text="Button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/button7"
            app:layout_constraintRight_toRightOf="@+id/guideline1"
            app:layout_constraintLeft_toLeftOf="@+id/guideline1"
            app:layout_constraintTop_toTopOf="@id/guideline2"
            app:layout_constraintBottom_toBottomOf="@+id/guideline2"
            />

5、Barrier (屏障)

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

对 Barrier 可以使用的属性有:

barrierDirection:设置 Barrier 所创建的位置。可设置的有:bottom、end、left、right、start、top。
constraint_referenced_ids:设置 Barrier 引用的控件。可设置多个,设置的方式是:id, id。(无需加 @id/)
barrierAllowsGoneWidgets:默认为 true,即当 Barrier 引用的控件被 GONE 掉时,则 Barrier 默认的创建行为是在已 GONE 掉控件的已解析位置上进行创建。如果设置为 false,则不会将 GONE 掉的控件考虑在内。

当在 TextView1和TextView2 控件的大小都不确定的情况下, TextView3 以谁作为约束对象都不对。如果以 TextView1 作为约束对象,那么当 TextView2 的宽度过宽时就会被遮挡,同理以 TextView2 作为约束也是如此。

那么此时,Barrier(屏障)就派上用场了。这是个非常好用的东东,和 GuideLine 一样,它是一个虚拟的 View,对界面是不可见的。目的就是辅助布局。

<TextView
            android:text="你好"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/textView1"
            app:layout_constraintTop_toTopOf="parent" 
            android:layout_marginTop="16dp"
            />
    <TextView
            android:text="它是一个虚拟的 View"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintStart_toStartOf="parent"
            android:id="@+id/textView2" 
            app:layout_constraintTop_toBottomOf="@+id/textView1"
            android:layout_marginTop="44dp"/>

    <TextView
            android:text="看我的位置在哪里啊"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintLeft_toRightOf="@+id/barrier"
            android:id="@+id/textView3"/>

    <androidx.constraintlayout.widget.Barrier
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/barrier"
            app:constraint_referenced_ids="textView1,textView2"
            app:barrierDirection="right"/>

6、Group

Group 的作用就是控制一组控件的可见性。其可使用到的属性为:

  • constraint_referenced_ids:指定所引用控件的 id。
    <androidx.constraintlayout.widget.Group
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:visibility="gone"
            app:constraint_referenced_ids="textView1, textView2" />


 

7、placeholder 占位

Placeholder(占位符)是一个虚拟对象,作用和它的名字一样,就是占位。

当放置好 Placeholder 后,可以通过 setContentId() 方法将占位符变为有效的视图。如果视图已经存在于屏幕上,那么视图将会从原有位置消失。配合过度动画,可达到很好的视觉效果。

<ImageView
            android:id="@+id/imageHead"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@mipmap/img_logo_personal_center"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

    <androidx.constraintlayout.widget.Placeholder
            android:id="@+id/placeholder"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

点击头像,图片出现在占位图中

imageHead.setOnClickListener {
            placeholder.setContentId(R.id.imageHead)
        }

 

8、优化器

可以通过将标签app:layout_optimizationLevel元素添加到ConstraintLayout来决定应用哪些优化。

  • none:不应用优化
  • standard:默认。仅优化直接和障碍约束
  • direct:优化直接约束
  • barrier:优化障碍约束
  • chain:优化链条约束
  • dimensions: 优化维度测量,减少匹配约束元素的度量数量在设置值时,

可以设置多个,如:

app:layout_optimizationLevel="direct|barrier|dimensions"

 

9、ConstraintSet运用

This class contains the different attributes specifying how a view want to be laid out inside a ConstraintLayout. For building up constraints at run time, using ConstraintSet is recommended.

上面英文出自官方解释,运行中如何更改布局中控件的约束,建议使用ConstraintSet。
  首先看下ConstraintSet是如何运用的

1、写一个简单布局,两个Button

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
                                                   android:layout_width="match_parent"
                                                   android:layout_height="match_parent"
                                                   android:id="@+id/constraintLayout"
                                                   xmlns:app="http://schemas.android.com/apk/res-auto">



    <Button
            android:text="Button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/button1"
            app:layout_constraintTop_toTopOf="parent"
            android:layout_marginTop="40dp"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"/>

    <Button
            android:text="我要移动了"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/button2"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"/>

</androidx.constraintlayout.widget.ConstraintLayout>

                                

对上面的Button设置一个点击事件,我们要改变下面Button的位置。

 val set = ConstraintSet()
        button1.setOnClickListener {
            set.clone(this, R.layout.activity_main)//复制一份父布局的约束
//            设置组件之间的约束
            set.connect(R.id.button2, ConstraintSet.LEFT, R.id.button1, ConstraintSet.LEFT)
            set.connect(R.id.button2, ConstraintSet.RIGHT, R.id.button1, ConstraintSet.RIGHT)
            set.connect(R.id.button2, ConstraintSet.TOP, R.id.button1, ConstraintSet.BOTTOM)

//            set.centerHorizontally(R.id.button15, ConstraintSet.PARENT_ID) //设置btn水平剧中于父布局parent
//            设置btn的高度,宽度
            set.constrainHeight(R.id.button2, 100)
            set.constrainWidth(R.id.button2, 400)

            TransitionManager.beginDelayedTransition(constraintLayout)//设置一个动画
            set.applyTo(constraintLayout)//.最后一步 ,apply一下使设置生效

效果图

                          

 

这里就介绍完了,深夜撸码,实属不易,感谢收看!

参考

 https://developer.android.google.cn/reference/android/support/constraint/ConstraintLayout.html

https://blog.csdn.net/airsaid/article/details/79052011

https://blog.csdn.net/guolin_blog/article/details/53122387

 

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值