jack_the_beast
jack_the_beast

Reputation: 1971

Android: ConstraintLayout: createHorizontalChain() not working

I'm trying to create a view which contains a variable number of views evenly spread horizontally. I think the best option is a ConstraintLayout, however I tried implementing this on a clean project:

fragment.xml:

<androidx.constraintlayout.widget.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"
    tools:context=".FirstFragment">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/cl"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

myFragment.kt:

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        container = view.findViewById(R.id.cl)
        buildViews()
    }

    private val views = mutableListOf<AppCompatImageView>()
    private lateinit var container: ConstraintLayout

    private fun buildViews() {

        val viewLp =
            ConstraintLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT)

        repeat(6) {
            val view = AppCompatImageView(context)
            //I used a random vector drawable here
            view.setImageDrawable(ContextCompat.getDrawable(requireContext(), R.drawable.ic_baseline_account_circle_10))
            view.layoutParams = viewLp
            view.id = RelativeLayout.generateViewId()
            container.addView(view)
            views.add(view)
        }

        val set = ConstraintSet()
        set.clone(container)

        val ids = views.mapTo(mutableListOf(), { it.id }).toIntArray()

        set.createHorizontalChain(
            ConstraintSet.PARENT_ID,
            ConstraintSet.LEFT,
            ConstraintSet.PARENT_ID,
            ConstraintSet.RIGHT,
            ids,
            null,
            ConstraintSet.CHAIN_SPREAD
        )
        set.applyTo(container)
    }

but this gives me the following result: screen

I expect an horizontal chain like this:

Note that the ImageViews are all correctly drawn, they're just all in the same spot. From the debug, I can see that the constraints in the set are all correct (first view is connected to parent and second view, second view to first and third and so on...). Also, the ConstraintLayout is correctly stretching to the whole screen width, so the views should fit. I also tried to manually assign constraints to each view and I got the same result.

What am I missing here?

Upvotes: 1

Views: 463

Answers (1)

Cheticamp
Cheticamp

Reputation: 62851

There may be other problems, but one issue that your code has is that it shares one set of layout params among the views. Each view needs its own set of layout params to store its layout constraints. Move

 val viewLp =
        ConstraintLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT)

inside the repeat(6) loop and you will get a better result.

Upvotes: 2

Related Questions