ConstraintLayout从简单使用到详细解剖(一)

849 阅读7分钟

ConstraintLayout出来以后逐渐收到越来越多的Android开发者的青睐,我自己也上手使用了一年多,现在xml父布局基本都是他了。所以特开此贴聊聊ConstraintLayout。

ConstraintLayout的主要属性

这是一个用ConstraintLayout为父布局的简单页面,让我们来了解一下ConstraintLayout的主要属性。

app:layout_constraintLeft_toLeftOf=""//控件的left和父布局(parent)或者其他控件的left(@+id/控件id)形成约束

app:layout_constraintRight_toRightOf=""//控件的Right和父布局(parent)或者其他控件的Right(@+id/控件id)形成约束

app:layout_constraintTop_toTopOf=""//控件的Top和父布局(parent)或者其他控件的Top(@+id/控件id)形成约束

app:layout_constraintBottom_toBottomOf=""//控件的Bottom和父布局(parent)或者其他控件的Bottom(@+id/控件id)形成约束

app:layout_constraintLeft_toRightOf=""//控件的left和父布局(parent)或者其他控件的Right(@+id/控件id)形成约束

app:layout_constraintRight_toLeftOf=""//控件的Right和父布局(parent)或者其他控件的Left(@+id/控件id)形成约束

app:layout_constraintTop_toBottomOf=""//控件的Top和父布局(parent)或者其他控件的Bottom(@+id/控件id)形成约束

app:layout_constraintBottom_toTopOf=""//控件的Bottom和父布局(parent)或者其他控件的Top(@+id/控件id)形成约束

所谓的约束就是指的是控件的相对定位。例如,控件视图1 app:layout_constraintLeft_toLeftOf="parent" ,则是表示控件视 图1的左边相对父布局左边形成定位,此时再加上 android:layout_marginLeft="50dp"则表示控件视图1左边相对父布局左边距离50dp, 同样,以上其他属性就不难理解了。

贴上布局代码

<Button
        android:id="@+id/btn_one"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:text="视图1"
        android:layout_width="0dp"
        android:layout_height="180dp"/>


<Button
        android:id="@+id/btn_two"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@+id/bth_three"
        app:layout_constraintTop_toBottomOf="@+id/btn_one"
        android:text="视图2"
        android:layout_width="0dp"
        android:layout_height="180dp"/>


<Button
        android:id="@+id/bth_three"
        app:layout_constraintLeft_toRightOf="@+id/btn_two"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/btn_one"
        android:text="视图3"
        android:layout_width="0dp"
        android:layout_height="180dp"/>


<Button
        android:id="@+id/btn_four"
        app:layout_constraintLeft_toLeftOf="@+id/btn_two"
        app:layout_constraintRight_toRightOf="@+id/bth_three"
        app:layout_constraintTop_toBottomOf="@+id/btn_two"
        app:layout_constraintBottom_toBottomOf="parent"
        android:text="视图4"
        android:layout_width="0dp"
        android:layout_height="0dp"/>

控件本身left和right都形成约束的时候,用0dp表示match,top和bottom也是同理。

来看下面这一组属性

app:layout_goneMarginTop=""//表示该控件top约束的目标控件的visibility=gone时,MarginTop的距离
app:layout_goneMarginBottom=""//表示该控件Bottom约束的目标控件的visibility=gone时,MarginBottom的距离
app:layout_goneMarginLeft=""//表示该控件Left约束的目标控件的visibility=gone时,MarginLeft的距离
app:layout_goneMarginRight=""//表示该控件Right约束的目标控件的visibility=gone时,MarginRight的距离

如图,当视图4所约束的视图2visibility=gone,那么视图4和视图2形成的top_toBottomof则无效,视图3和视图2的right_toleftof也失效,此时加入属性

app:layout_goneMarginTop="180dp"

属性chainStyle

app:layout_constraintHorizontal_chainStyle="packed"//如下图

app:layout_constraintHorizontal_chainStyle="spread_inside"//如下图

app:layout_constraintHorizontal_chainStyle="spread"//如下图

layout_constraintVertical_chainStyle 同理

属性Circle

主要是这三个属性,大家看代码和示意图,因为作图工具一直down不下来,所以先简单粗暴一些

    app:layout_constraintCircle=""
    app:layout_constraintCircleAngle=""
    app:layout_constraintCircleRadius=""

 <Button
        android:id="@+id/btn"
        android:background="#ff78D5"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        android:layout_width="50dp"
        android:layout_height="50dp"/>


    <Button
        android:id="@+id/btn_cir"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintCircle="@id/btn"
        app:layout_constraintCircleAngle="25"
        app:layout_constraintCircleRadius="100dp"
        android:background="@color/colorPrimary"
        android:layout_width="50dp"
        android:layout_height="50dp"/>

ConstranitLayout的一些简单动画效果

android.support.constraint包里提供了一个ConstraintSet类 这个类可以设置constraintLayout的约束条件并且配合TransitionManager.beginDelayedTransition(),可以实现简单动画效果。

首先定义一个布局文件

<Button
    android:id="@+id/btn_two"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toLeftOf="@+id/btn_three"
    app:layout_constraintTop_toBottomOf="@+id/btn_one"
    app:layout_constraintBottom_toTopOf="@+id/btn_four"
    android:background="@color/colorPrimary"
    android:text="视图2"
    android:layout_width="0dp"
    android:layout_height="0dp" />


<Button
    android:id="@+id/btn_three"
    app:layout_constraintLeft_toRightOf="@+id/btn_two"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/btn_one"
    app:layout_constraintBottom_toTopOf="@+id/btn_four"
    android:background="@color/colorPrimaryDark"
    android:text="视图3"
    android:layout_width="0dp"
    android:layout_height="0dp" />


<Button
    android:id="@+id/btn_four"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/btn_two"
    app:layout_constraintBottom_toBottomOf="parent"
    android:text="视图4"
    android:gravity="center"
    android:layout_width="0dp"
    android:layout_height="0dp" />

这是作为首次进入加载的布局。然后在定义想要切换调整的布局文件,这里我定义了两个activity布局文件

activity3

<Button
    android:id="@+id/btn_one"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toLeftOf="@+id/btn_three"
    app:layout_constraintTop_toBottomOf="@+id/btn_two"
    app:layout_constraintBottom_toTopOf="@+id/btn_four"
    android:background="@color/colorAccent"
    android:text="视图1"
    android:layout_width="0dp"
    android:layout_height="0dp" />


<Button
    android:id="@+id/btn_three"
    app:layout_constraintLeft_toRightOf="@+id/btn_one"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/btn_two"
    app:layout_constraintBottom_toTopOf="@+id/btn_four"
    android:background="@color/colorPrimaryDark"
    android:text="视图3"
    android:layout_width="0dp"
    android:layout_height="0dp" />


<Button
    android:id="@+id/btn_four"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/btn_one"
    app:layout_constraintBottom_toBottomOf="parent"
    android:text="视图4"
    android:gravity="center"
    android:layout_width="0dp"
    android:layout_height="0dp" />

activity4

<Button
    android:id="@+id/btn_three"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toLeftOf="@+id/btn_one"
    app:layout_constraintTop_toBottomOf="@+id/btn_two"
    app:layout_constraintBottom_toTopOf="@+id/btn_four"
    android:background="@color/colorPrimaryDark"
    android:text="视图3"
    android:layout_width="0dp"
    android:layout_height="0dp" />


<Button
    android:id="@+id/btn_one"
    app:layout_constraintLeft_toRightOf="@+id/btn_three"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/btn_two"
    app:layout_constraintBottom_toTopOf="@+id/btn_four"
    android:background="@color/colorAccent"
    android:text="视图1"
    android:layout_width="0dp"
    android:layout_height="0dp" />


<Button
    android:id="@+id/btn_four"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/btn_one"
    app:layout_constraintBottom_toBottomOf="parent"
    android:text="切换"
    android:gravity="center"
    android:layout_width="0dp"
    android:layout_height="0dp" />

activity逻辑代码奉上

private val conStrainSet = ConstraintSet()
private val conStrainSet1 = ConstraintSet()
private val conStrainSet2 = ConstraintSet()
private var caseType: Int = 0
private var conStrainlayout : ConstraintLayout? = null


override fun onCreate(savedInstanceState: Bundle?){
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main2)

    conStrainSet.clone(this,R.layout.activity_main2)
    conStrainSet1.clone(this,R.layout.activity_main3)
    conStrainSet2.clone(this,R.layout.activity_main4)

    btn_four.setOnClickListener {
        swichBtn(caseType)
    }
}

private fun swichBtn(case:Int){
    when(case){
        0 ->{
            conStrainlayout = findViewById(R.id.conStrain)
            TransitionManager.beginDelayedTransition(conStrainlayout)
            conStrainSet1.applyTo(conStrainlayout)
            caseType = 1
        }
        1 ->{
            conStrainlayout = findViewById(R.id.conStrain)
            TransitionManager.beginDelayedTransition(conStrainlayout)
            conStrainSet2.applyTo(conStrainlayout)
            caseType = 2
        }
        2 ->{
            conStrainlayout = findViewById(R.id.conStrain)
            TransitionManager.beginDelayedTransition(conStrainlayout)
            conStrainSet.applyTo(conStrainlayout)
            caseType = 0
        }
    }
}

看看效果

特别要注意的是:这个activity的xml文件的父布局都需要设置id,否则ConstraintSet的clone方法就会找不到对应的资源id而报错