1

I have a constraint layout with a number of views and I wanted to sort them programmatically. I tried using ConstraintSet but it's not working as expected.

I created a sample app to demonstrate the problem Here's the activity_main.xml file.

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/grid"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingTop="5dp"
    android:theme="@style/Theme.MaterialComponents.DayNight">
    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/leftGuide"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.02" />
    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/rightGuide"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:orientation="vertical"
        app:layout_constraintGuide_percent="0.98" />
    <androidx.constraintlayout.widget.Guideline
        android:id="@+id/topGuide"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:orientation="horizontal"
        app:layout_constraintGuide_percent="0.02" />
    <com.google.android.material.card.MaterialCardView
        android:id="@+id/myApp"
        android:layout_width="0dp"
        android:layout_height="117dp"
        app:cardBackgroundColor="#FFFDE7"
        app:cardCornerRadius="22dp"
        app:cardElevation="3dp"
        app:layout_constraintEnd_toStartOf="@id/cat"
        app:layout_constraintHorizontal_chainStyle="spread_inside"
        app:layout_constraintStart_toEndOf="@id/leftGuide"
        app:layout_constraintTop_toBottomOf="@id/topGuide"
        app:layout_constraintWidth_percent="0.3">
        <ImageView
            android:layout_width="60dp"
            android:layout_height="60dp"
            android:layout_gravity="center"
            android:layout_marginBottom="8dp"
            android:contentDescription="@string/app_name"
            android:src="@drawable/ic_launcher_background" />
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|center"
            android:layout_marginBottom="3dp"
            android:maxWidth="100dp"
            android:maxHeight="60dp"
            android:text="@string/app_name"
            android:textAppearance="@style/TextAppearance.AppCompat.Medium"
            android:textColor="#EB2B2313"
            android:textSize="14sp" />
    </com.google.android.material.card.MaterialCardView>
    <com.google.android.material.card.MaterialCardView
        android:id="@+id/cat"
        android:layout_width="0dp"
        android:layout_height="117dp"
        app:cardBackgroundColor="#FFFDE7"
        app:cardCornerRadius="22dp"
        app:cardElevation="3dp"
        app:layout_constraintEnd_toStartOf="@id/kicks"
        app:layout_constraintStart_toEndOf="@id/myApp"
        app:layout_constraintTop_toTopOf="@id/topGuide"
        app:layout_constraintWidth_percent="0.3">

        <ImageView
            android:layout_width="57dp"
            android:layout_height="57dp"
            android:layout_gravity="center"
            android:layout_marginBottom="6dp"
            android:contentDescription="@string/app_name"
            android:src="@drawable/ic_launcher_foreground" />
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|center"
            android:layout_marginBottom="3dp"
            android:maxWidth="100dp"
            android:maxHeight="60dp"
            android:text="cat"
            android:textAppearance="@style/TextAppearance.AppCompat.Medium"
            android:textColor="#EB2B2313"
            android:textSize="14sp" />
    </com.google.android.material.card.MaterialCardView>
    <com.google.android.material.card.MaterialCardView
        android:id="@+id/kicks"
        android:layout_width="0dp"
        android:layout_height="117dp"
        app:cardBackgroundColor="#FFFDE7"
        app:cardCornerRadius="22dp"
        app:cardElevation="3dp"
        app:layout_constraintEnd_toStartOf="@id/rightGuide"
        app:layout_constraintStart_toEndOf="@id/cat"
        app:layout_constraintTop_toTopOf="@id/topGuide"
        app:layout_constraintWidth_percent="0.3">
        <ImageView
            android:layout_width="60dp"
            android:layout_height="60dp"
            android:layout_gravity="center"
            android:layout_marginBottom="6dp"
            android:contentDescription="@string/app_name"
            android:src="@drawable/ic_launcher_foreground" />
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom|center"
            android:layout_marginBottom="3dp"
            android:maxWidth="100dp"
            android:maxHeight="60dp"
            android:text="kicks"
            android:textAppearance="@style/TextAppearance.AppCompat.Medium"
            android:textColor="#EB2B2313"
            android:textSize="14sp" />
    </com.google.android.material.card.MaterialCardView>
</androidx.constraintlayout.widget.ConstraintLayout>

Here's how it looks like.

But i want to change the constraints programmatically to look like this

This is what I've tried

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        myApp.setOnClickListener {
           val constrain = ConstraintSet()
           constrain.apply {
               clone(this@MainActivity,R.layout.activity_main)
               connect(myApp.id,ConstraintSet.END,rightGuide.id,ConstraintSet.START,0)
               connect(myApp.id,ConstraintSet.START,kicks.id,ConstraintSet.END,0)
               connect(cat.id,ConstraintSet.START,leftGuide.id,ConstraintSet.END,0)
               connect(cat.id,ConstraintSet.END,kicks.id,ConstraintSet.START,0)
               connect(kicks.id,ConstraintSet.END,myApp.id,ConstraintSet.START,0)
               connect(kicks.id,ConstraintSet.START,cat.id,ConstraintSet.END,0)

               applyTo(grid)
            }
        }
    }
}

But this is what I get

Kofi
  • 525
  • 6
  • 15
  • Checkout this answer, it is in java but you can make the conversion: https://stackoverflow.com/questions/42844776/add-a-view-programmatically-in-constraintlayout/42846520#42846520 – Juan Dec 22 '19 at 16:37
  • I've already tried that but it doesn't work. It doesn't produce the desired output. Look at the links – Kofi Dec 22 '19 at 17:04
  • Have you tried cloning `grid` directly? `clone(grid)` instead of `clone(this@MainActivity,R.layout.activity_main)` – Christilyn Arjona Dec 22 '19 at 21:35
  • Yes I have. It produces the same effect – Kofi Dec 22 '19 at 22:59

1 Answers1

0

It seems it's a bug with constraint layout 2.0.0.beta2. After upgrading to beta 4 (latest version currently), it produces the expected outcome.

Kofi
  • 525
  • 6
  • 15