Android

ConstraintLayout基本使用

2021-08-24  本文已影响0人  全球顶尖伪极客

ConstraintLayout官方文档 | 郭霖托拉拽 | 代码实现

image.png

一、相对位置、相对定位Relative positioning

水平和垂直方向至少得有一个约束

image.png

1.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 基线,参考1-3
  • layout_constraintStart_toEndOf
  • layout_constraintStart_toStartOf
  • layout_constraintEnd_toStartOf
  • layout_constraintEnd_toEndOf

1.2图例解析

image.png image.png image.png

1-1 1-2 1-3

1-1
<Button android:id="@+id/buttonA" ... />
         <Button android:id="@+id/buttonB" ...
                 app:layout_constraintLeft_toRightOf="@+id/buttonA" />
                     
                     
  1-2                   
    <TextView
        android:id="@+id/TextView1"
        ...
        android:text="TextView1" />

    <TextView
        android:id="@+id/TextView2"
        ...
        app:layout_constraintLeft_toRightOf="@+id/TextView1" />

    <TextView
        android:id="@+id/TextView3"
        ...
        app:layout_constraintTop_toBottomOf="@+id/TextView1" />
            
  1-3       
  <TextView
        android:id="@+id/TextView1"
        .../>

    <TextView
        android:id="@+id/TextView2"
        ...
        app:layout_constraintLeft_toRightOf="@+id/TextView1" 
        app:layout_constraintBaseline_toBaselineOf="@+id/TextView1"/>

二、边距Margins

注意事项:控件在ConstraintLayout里面要实现margin,必须先约束该控件在ConstraintLayout里的位置。在使用margin的时候要注意两点:控件必须在布局里约束一个相对位置,margin只能大于等于0

image.png

2.1常用属性

  • android:layout_marginStart

  • android:layout_marginEnd

  • android:layout_marginLeft

  • android:layout_marginTop

  • android:layout_marginRight

  • android:layout_marginBottom

<android.support.constraint.ConstraintLayout 
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/TextView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:layout_marginTop="10dp" 
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>
        //需要下面的约束
        //app:layout_constraintLeft_toLeftOf="parent"
        //app:layout_constraintTop_toTopOf="parent"/>
</android.support.constraint.ConstraintLayout>

2.2 goneMargin,连接到 GONE 小部件时的边距

说明:goneMargin主要用于约束的控件可见性被设置为gone的时候使用的margin值

常用属性:

  • layout_goneMarginStart

  • layout_goneMarginEnd

  • layout_goneMarginLeft

  • layout_goneMarginTop

  • layout_goneMarginRight

  • layout_goneMarginBottom

假设TextView2的左边约束在TextView1的右边,并给TextView2设一个app:layout_goneMarginLeft="10dp",代码如下:

<android.support.constraint.ConstraintLayout 
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/TextView1"
        .../>

    <TextView
        android:id="@+id/TextView2"
        ...
        app:layout_constraintLeft_toRightOf="@+id/TextView1"
        app:layout_goneMarginLeft="10dp"
        />

</android.support.constraint.ConstraintLayout>

效果如下2-1,TextView2在TextView1的右边,且没有边距。这个时候把TextView1的可见性设为gone,TextView1消失后,TextView2有一个距离左边10dp的边距。效果如下:2-2

image.png 2-1 image.png

2-2

三、居中和偏移Centering positioning and bias

居中:

image.png
<android.support.constraint.ConstraintLayout ...>
             <Button android:id="@+id/button" ...
                 app:layout_constraintLeft_toLeftOf="parent"
                 app:layout_constraintRight_toRightOf="parent
                 app:layout_constraintBottom_toBottomOf="parent
                app:layout_constraintTop_toTopOf="parent"/>
         </>
         居中

偏移:

说明:赋一个范围为 0-1 的值,假如赋值为0,则TextView1在布局的最左侧,假如赋值为1,则TextView1在布局的最右侧,假如假如赋值为0.5,则水平居中,水平竖直方向value="0.3"相当于weight百分比占比

常见属性:

  • layout_constraintHorizontal_bias
  • layout_constraintVertical_bias

image.png
<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/>
         </>

写上具体的偏移值:

上面TextView1在水平居中后使用layout_marginLeft="100dp"向右偏移了100dp

image.png
<TextView
        android:id="@+id/TextView1"
        ...
        android:layout_marginLeft="100dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent" />

四、角度定位Circular positioning (Added in 1.1)

说明:您可以相对于另一个小部件中心以某个角度和距离约束小部件中心。这允许您将一个小部件放置在一个圆圈上(见图 6)。

角度从垂直方向顺时针,类似钟表。

相关属性:

  • layout_constraintCircle : references another widget id
  • layout_constraintCircleRadius : the distance to the other widget center
  • layout_constraintCircleAngle : which angle the widget should be at (in degrees, from 0 to 360)
image.png

<Button android:id="@+id/buttonA" ... />
  <Button android:id="@+id/buttonB" ...
      app:layout_constraintCircle="@+id/buttonA"
      app:layout_constraintCircleRadius="100dp"
      app:layout_constraintCircleAngle="45" 
      app:layout_constraintLeft_toLeftOf="parent"
      app:layout_constraintRight_toRightOf="parent"
      app:layout_constraintTop_toTopOf="parent"
      app:layout_constraintBottom_toBottomOf="parent"
          />
         
     

Visibility behavior

尺寸约束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

The dimension of the widgets can be specified by setting the android:layout_width and android:layout_height attributes in 3 different ways:

<TextView
            android:id="@+id/TextView4"
            android:layout_width="0dp"
            android:layout_height="110dp"
            android:background="@color/black"
            android:layout_marginLeft="30dp"
            app:layout_constraintDimensionRatio="w,1:1"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
image.png

宽高比

当宽或高至少有一个尺寸被设置为0dp时(并且当一个0为0时另外一个至少是一个具体的数值,不能为****wrap_content,不然看着没有啥效果),可以通过属性layout_constraintDimensionRatio设置宽高比

<TextView
        android:id="@+id/TextView4"
        android:layout_width="0dp"
        android:layout_height="110dp"
        android:background="@color/black"
        app:layout_constraintDimensionRatio="w,1:1"  正方形
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

链:Chains

image

链头:Chain heads

链由设置在链的第一个元素(链的“头”)上的属性控制:头部是水平链最左边的小部件,垂直链是最顶部的小部件。

image

链中的边距Margins in chains

 <TextView
        android:id="@+id/TextView11"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="#685454"
        android:text="ff0000"
        app:layout_constraintHorizontal_chainStyle="spread_inside"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@+id/TextView12"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/TextView12"
        app:layout_constraintTop_toTopOf="parent"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="#00ff00"
        android:text="00ff00"
        app:layout_constraintLeft_toRightOf="@+id/TextView11"
        app:layout_constraintRight_toLeftOf="@+id/TextView13"
        app:layout_constraintRight_toRightOf="parent" />

    <TextView
        android:id="@+id/TextView13"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="#0000ff"
        android:text="0000ff"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toRightOf="@+id/TextView12"
        app:layout_constraintRight_toRightOf="parent" />
image.png image.png image.png image

权重:Weighted chains

image.png
<Button
        android:id="@+id/sbBtn"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="xxxx"
        app:layout_constraintEnd_toStartOf="@+id/sbBtn01"
        app:layout_constraintHorizontal_weight="2"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/sbBtn01"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
        app:layout_constraintEnd_toStartOf="@+id/sbBtn02"
        app:layout_constraintHorizontal_weight="1"
        app:layout_constraintStart_toEndOf="@+id/sbBtn"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/sbBtn02"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="xxxxxxxxxxxxxxxxxxxx"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_weight="1"
        app:layout_constraintStart_toEndOf="@+id/sbBtn01"
        app:layout_constraintTop_toTopOf="parent" />

Barrier屏障

使用场景:假设有3个控件ABC,C在AB的右边,但是AB的宽是不固定的,这个时候C无论约束在A的右边或者B的右边都不对。当出现这种情况可以用Barrier来解决。Barrier可以在多个控件的一侧建立一个屏障,如下所示:

image.png

属性说明:其中,app:constraint_referenced_ids="btn_a,btn_b"这句指定这个Barrier是用来控制idbtn_a和btn_b的两个控件。而app:barrierDirection="end"这句等于在这两个控件的右端设置一道“屏障”。

最后,我们让控件C依赖于这个Barrier。注意这句:app:layout_constraintLeft_toLeftOf="@id/barrier"

** app:barrierDirection="right",值有多个可调节,比如start,bottom , top**

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

    <Button
        android:id="@+id/btn_a"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="30dp"
        android:layout_marginTop="200dp"
        android:text="这是控件A,我比较宽"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/btn_b"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="30dp"
        android:text="这是控件B"
        app:layout_constraintLeft_toLeftOf="@id/btn_a"
        app:layout_constraintTop_toBottomOf="@id/btn_a" />

    <Button
        android:id="@+id/btn_c"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="30dp"
        android:layout_marginTop="200dp"
        android:text="这是控件C"
        app:layout_constraintLeft_toLeftOf="@id/barrier"
        app:layout_constraintTop_toTopOf="parent" />

Group:控制一系列id相关控件的显示隐藏状态

在xml文件中设置 android:visibilitys属性

androidx.constraintlayout.widget.Group中使用****app:constraint_referenced_ids="btn_a,btn_b,btn_c" 可将相关id可见属性****android:visibility="visible"****进行显示隐藏显示。

 <!--计数Group-->
    <androidx.constraintlayout.widget.Group
        android:id="@+id/count_group"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:visibility="visible"
        app:constraint_referenced_ids="btn_a,btn_b,btn_c" />

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

    <Button
        android:id="@+id/btn_a"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="30dp"
        android:layout_marginTop="200dp"
        android:text="这是控件A,我比较宽我比较宽我比较宽"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/btn_b"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="30dp"
        android:text="这是控件B"
        app:layout_constraintLeft_toLeftOf="@id/btn_a"
        app:layout_constraintTop_toBottomOf="@id/btn_a" />

    <Button
        android:id="@+id/btn_c"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="30dp"
        android:layout_marginTop="200dp"
        android:text="这是控件C"
        app:layout_constraintLeft_toLeftOf="@id/barrier"
        app:layout_constraintTop_toTopOf="parent" />

     

代码控制:****在代码中通过group.setVisibility()方法来设置

但是我在实践中发现,当我在代码中调用group.setVisibility()来显示或隐藏group中的一组控件时,这个方法并没有生效。通过查看源码发现,Group更新他成员的可见性状态是在 updatePreLayout(),而这个方法最终是在ConstraintLayout中通过updateHierarchy()方法调用的

那么我们就可以在设置可见性之后再调用group.requestLayout(),而requestLayout()方法会导致View的onMeasure、onLayout、onDraw方法被调用,这样我们就可以立即改变group中控件的可见性了。


if (recIsClick) {
    countGroup.setVisibility(View.VISIBLE);
 
} else if (recIsClick) {
    countGroup.setVisibility(View.INVISIBLE);
}
 
countGroup.requestLayout();

Placeholder占位符

Placeholder指的是占位符。在Placeholder中可使用setContent()设置另一个控件的id,使这个控件移动到占位符的位置。新建一个Placeholder约束在屏幕的左上角,新建一个TextView约束在屏幕的右上角,在Placeholder中设置 app:content="@+id/textview",这时TextView会跑到屏幕的左上角。举个例子:

<androidx.constraintlayout.widget.Placeholder
        android:id="@+id/placeholder"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:content="@+id/textview"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintBottom_toBottomOf="parent" />

    <TextView
        android:id="@+id/textview"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="#cccccc"
        android:padding="16dp"
        android:text="TextView"
        android:textColor="#000000"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintBottom_toBottomOf="parent" />

Guideline

说明:Guildline像辅助线一样,在预览的时候帮助你完成布局(不会显示在界面上)。

使用属性:

   <androidx.constraintlayout.widget.Guideline
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/guideline"
        app:layout_constraintGuide_begin="250dp"
        android:orientation="vertical"/>
    <androidx.constraintlayout.widget.Guideline
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/guideline2"
        app:layout_constraintGuide_percent="0.1"
        android:orientation="vertical"/>

    <Button
        android:text="Button_guideline"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/button"
        android:background="#ff0000"
        app:layout_constraintLeft_toLeftOf="@+id/guideline"
        android:layout_marginTop="16dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"/>
   
效果图: image.png
上一篇 下一篇

猜你喜欢

热点阅读