Android ConstraintLayout:以编程方式更改约束

Android ConstraintLayout:以编程方式更改约束,android,android-layout,android-view,android-constraintlayout,Android,Android Layout,Android View,Android Constraintlayout,我需要有关约束集的帮助。我的目标是在代码中更改视图的约束,但我不知道如何正确执行 我有4个TextViews和一个ImageView。我需要将ImageView约束设置为TextViews之一 check_answer4 = (TextView) findViewById(R.id.check_answer4); check_answer1 = (TextView) findViewById(R.id.check_answer1); check_answer2 = (TextView) find

我需要有关约束集的帮助。我的目标是在代码中更改视图的约束,但我不知道如何正确执行

我有4个
TextView
s和一个
ImageView
。我需要将
ImageView
约束设置为
TextView
s之一

check_answer4 = (TextView) findViewById(R.id.check_answer4);
check_answer1 = (TextView) findViewById(R.id.check_answer1);
check_answer2 = (TextView) findViewById(R.id.check_answer2);
check_answer3 = (TextView) findViewById(R.id.check_answer3);

correct_answer_icon = (ImageView) findViewById(R.id.correct_answer_icon);
如果第一个答案正确,我需要将
ImageView
的约束设置为

app:layout_constraintRight_toRightOf="@+id/check_answer1"
app:layout_constraintTop_toTopOf="@+id/check_answer1"
app:layout_constraintRight_toRightOf="@+id/check_answer2"
app:layout_constraintTop_toTopOf="@+id/check_answer2"
如果第二个答案正确,我需要将
ImageView
的约束设置为

app:layout_constraintRight_toRightOf="@+id/check_answer1"
app:layout_constraintTop_toTopOf="@+id/check_answer1"
app:layout_constraintRight_toRightOf="@+id/check_answer2"
app:layout_constraintTop_toTopOf="@+id/check_answer2"
等等

  • 要将图像视图的约束设置为:

     app:layout_constraintRight_toRightOf="@+id/check_answer1"
     app:layout_constraintTop_toTopOf="@+id/check_answer1"
    
     app:layout_constraintRight_toRightOf="@+id/check_answer2"
     app:layout_constraintTop_toTopOf="@+id/check_answer2"
    
    使用:

  • 要将图像视图的约束设置为:

     app:layout_constraintRight_toRightOf="@+id/check_answer1"
     app:layout_constraintTop_toTopOf="@+id/check_answer1"
    
     app:layout_constraintRight_toRightOf="@+id/check_answer2"
     app:layout_constraintTop_toTopOf="@+id/check_answer2"
    
    使用:


  • 假设我们希望在运行时更改约束,使button1在单击时与button2对齐:

    然后,有这样的布局:

    <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/root"
        android:paddingBottom="@dimen/activity_vertical_margin"
        android:paddingLeft="@dimen/activity_horizontal_margin"
        android:paddingRight="@dimen/activity_horizontal_margin"
        android:paddingTop="@dimen/activity_vertical_margin">
    
    
        <Button
            android:id="@+id/button1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Button 1"
            app:layout_constraintTop_toTopOf="@+id/button3"
            app:layout_constraintBottom_toBottomOf="@+id/button3"
            app:layout_constraintStart_toEndOf="@+id/button3"
            android:layout_marginStart="0dp"
            app:layout_constraintEnd_toEndOf="parent"
            android:layout_marginEnd="0dp" />
    
        <Button
            android:id="@+id/button2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="16dp"
            android:text="Button 2"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            android:layout_marginStart="8dp"
            app:layout_constraintEnd_toEndOf="parent"
            android:layout_marginEnd="8dp"
            app:layout_constraintBottom_toBottomOf="parent"
            android:layout_marginBottom="8dp"
            app:layout_constraintTop_toTopOf="parent"
            android:layout_marginTop="8dp"
            app:layout_constraintHorizontal_bias="0.0"
            app:layout_constraintVertical_bias="0.5" />
    
        <Button
            android:id="@+id/button3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="16dp"
            android:text="Button 3"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            android:layout_marginStart="8dp"
            app:layout_constraintEnd_toEndOf="parent"
            android:layout_marginEnd="8dp"
            app:layout_constraintTop_toTopOf="parent"
            android:layout_marginTop="8dp"
            app:layout_constraintBottom_toBottomOf="parent"
            android:layout_marginBottom="8dp"
            app:layout_constraintHorizontal_bias="0.0"
            app:layout_constraintVertical_bias="0.223" />
    </android.support.constraint.ConstraintLayout>
    

    在Kotlin中,您可以简单地扩展
    ConstraintSet
    类并添加一些方法来利用Kotlin中的dsl并生成更可读的代码。 像这样

    class KotlinConstraintSet : ConstraintSet() {
    
        companion object {
            inline fun buildConstraintSet(block:KotlinConstraintSet.()->Unit) =
                KotlinConstraintSet().apply(block)
        }
        //add this if you plan on using the margin param in ConstraintSet.connect
        var margin: Int? = null
            get() {
                val result = field
                margin = null //reset it to work with other constraints
                return result
            }
    
        inline infix fun Unit.and(other: Int) = other // just to join two functions
    
        inline infix fun Int.topToBottomOf(bottom: Int) =
            margin?.let {
                connect(this, TOP, bottom, BOTTOM, it)
            } ?: connect(this, TOP, bottom, BOTTOM)
    
        inline fun margin(margin: Int) {
            this.margin = margin
        }
    
        inline infix fun Int.bottomToBottomOf(bottom: Int) =
            margin?.let {
                connect(this, BOTTOM, bottom, BOTTOM, it)
            } ?: connect(this, BOTTOM, bottom, BOTTOM)
    
        inline infix fun Int.topToTopOf(top: Int) =
            margin?.let {
                connect(this, TOP, top, TOP, it)
            } ?: connect(this, TOP, top, TOP)
    
        inline infix fun Int.startToEndOf(end: Int) =
            margin?.let {
                connect(this, START, end, END, it)
            } ?: connect(this, START, end, END)
    
                ...
        //TODO generate other functions depending on your needs
    
        infix fun Int.clear(constraint: Constraints) =
            when (constraint) {
                Constraints.TOP -> clear(this, TOP)
                Constraints.BOTTOM -> clear(this, BOTTOM)
                Constraints.END -> clear(this, END)
                Constraints.START -> clear(this, START)
            }
    
        //inline infix fun clearTopCon
        inline infix fun appliesTo(constraintLayout: ConstraintLayout) =
            applyTo(constraintLayout)
    
        inline infix fun clones(constraintLayout: ConstraintLayout) =
            clone(constraintLayout)
    
        inline fun constraint(view: Int, block: Int.() -> Unit) =
            view.apply(block)
    }
    
    enum class Constraints {
        TOP, BOTTOM, START, END //you could add other values to use with the clear fun like LEFT
    }
    
    像这样使用它

            buildConstraintSet {
                this clones yourConstraintLayout
                constraint(R.id.view1) {
                    margin(value:Int) and this topToBottomOf R.id.view2
                    margin(30) and this bottomToBottomOf ConstraintSet.PARENT_ID
                }
                constraint(R.id.view2) {
                    this clear Constraints.BOTTOM
                    margin(0) and this topToTopOf R.id.topGuide
                }
                constraint(R.id.view4) {
                    this topToTopOf R.id.view2
                    this bottomToBottomOf R.id.view3
                    this startToEndOf R.id.view2
                }
                //or you could simply do
                R.id.view1 startToEndOf R.view2
                R.id.view1 toptToBottomOf R.view3
                R.id.view3 bottomtToBottomOf R.view2
                R.id.view3 clear Constraints.END
    
                // and finally call applyTo()
                this appliesTo yourConstraintLayout
            }
    

    我知道我的答案已经很晚了,但我相信这会对来这里的其他人有很大帮助。 这篇文章不是我写的,但我做了一些修改,也就是说,你应该努力查看整篇文章

    约束集 在Java代码中使用约束集的关键是ConstraintSet类。此类包含一系列方法,这些方法允许创建、配置约束以及将约束应用于ConstraintLayout实例等任务。此外,ConstraintLayout实例的当前约束可以复制到ConstraintSet对象中,并用于将相同的约束应用于其他布局(有修改或无修改)

    ConstraintSet实例的创建与任何其他Java对象一样:

    ConstraintSet set = new ConstraintSet();
    
    一旦创建了约束集,就可以在实例上调用方法来执行广泛的任务。 以下代码配置一个约束集,其中按钮视图的左侧连接到EditText视图的右侧,边距为70dp:

    set.connect(button1.getId(), ConstraintSet.LEFT, 
            editText1.getId(), ConstraintSet.RIGHT, 70);
    
    将约束应用于布局 配置约束集后,必须将其应用于ConstraintLayout实例,约束集才会生效。通过调用applyTo()方法应用约束集,并传递对要应用设置的布局对象的引用:

    set.applyTo(myLayout);
    
    您可以使用
    ConstraintSet
    API执行更多操作,设置水平和垂直偏移、水平和垂直居中、操纵链等等

    读得真不错

    同样,这只是一种改编。

    此外,让我指出两件事:

  • 如果左/右不起作用,请尝试如下开始/结束:
  • params.startToEnd=button2.id

  • 如果要删除约束,请使用如下未设置标志:

  • params.startToEnd=ConstraintLayout.LayoutParams.UNSET
    @vishakha yeolekar的解决方案对我不起作用

    要更改约束,我们需要遵循以下步骤:

    • 克隆父布局
    • 清除以前的约束
    • 连接约束
    • 将约束应用于父布局
    解决方案代码(以Kotlin为单位)
    val clParent=findviewbyd(R.id.parent\u布局)
    val mConstraintSet=ConstraintSet()
    mConstraintSet.clone(clParent)
    mConstraintSet.clear(R.id.imageView,ConstraintSet.END)
    mConstraintSet.connect(R.id.imageView,ConstraintSet.END,R.id.check\u answer,ConstraintSet.END)
    mConstraintSet.applyTo(clParent)
    

    以下是ConstraintSet-的更多信息和方法的链接。

    另一种方法是像这样更新视图的布局参数(不请求布局):

    yourView.updateLayoutParams{
    startToEnd=otherView.id
    toptoop=otherView.id
    bottomToBottom=otherView.id
    //如果需要,添加其他约束
    }
    
    为此,您必须动态更改约束。@shweta我正是在问这个问题,如何通过友好的方式进行?获取。发布您的答案.constraintSet.clone(constraintLayout);在这一行中,constraintLayout是父布局吗?@Pang
    .clone(constraintLayout)
    这个变量是什么,从哪里获得它?@ReejeshPK@MiXT4PE是的,它是父布局,即
    constraintLayout constraintLayout=findViewById(R.id.parent\u布局)
    @leonheess我认为这应该是一个引用约束布局视图组的变量尝试了10种不同的方法,效果很好。非常感谢。我的朋友,我不明白你的密码。。什么是
    layoutParams
    val
    ?这是Java吗?先生,这是kotlin编程语言。Java等价物将是
    ConstraintLayout.LayoutParams=(ConstraintLayout.LayoutParams)button1.getLayoutParams()我想你忘了写button1.layoutParams=params@sumitsonawane,它是不需要的,因为我们正在变异该实例,然后执行
    button1.requestLayout()
    ,然后将检查我们变异的
    LayoutParams
    的实例。@azizbekian,是的,对我来说,最终的解决方案是将
    requestLayout()
    调用替换为
    setLayoutParams()
    ,然后它就可以工作了。简单地改变
    layoutParams
    并自己请求布局似乎并不能奏效。
    yourView.updateLayoutParams<ConstraintLayout.LayoutParams> {
            startToEnd = otherView.id
            topToTop = otherView.id
            bottomToBottom = otherView.id
            //add other constraints if needed
          }