Adam
Adam

Reputation: 3013

Creating constraintset from layout with merge

I want to do a Changebounds() animation from one constraintSet to another.

Normally I do this by creating two constraint sets:

private val originalState = ConstraintSet().apply {
    clone(context, R.layout.layout_meta_syntactic)
}

private val expandedState = ConstraintSet().apply {
    clone(context, R.layout.layout_meta_syntactic)
    // Change some constraints
    connect(
        R.id.button, ConstraintSet.END,
        R.id.foo_text, ConstraintSet.START
    )
}

And animate back and forth with:

TransitionManager.beginDelayedTransition(id_of_my_component_in_fragment, transition)
originalState.applyTo(id_of_my_component_in_fragment)

But now I'm stuck with a <merge> tag in the layout I want to clone from. The merge layout is the base for a compound component which extends ConstraintLayout.

Compound component:

class MyCompoundView : ConstraintLayout {

// Omissions
inflate(context, R.layout.layout_meta_syntactic, this)

inflating:

<merge xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/some_id"
    tools:parentTag="androidx.constraintlayout.widget.ConstraintLayout">

    // Views 

When trying to clone the layout into a constraint set programatically I get:

 Caused by: android.view.InflateException: Binary XML file line #2: <merge /> can be used only with a valid ViewGroup root and attachToRoot=true
 Caused by: android.view.InflateException: <merge /> can be used only with a valid ViewGroup root and attachToRoot=true

How do I go about creating constraint sets from such a layout?

Upvotes: 0

Views: 1169

Answers (2)

Adam
Adam

Reputation: 3013

The solution is to clone the compound component which is a ConstraintLayout

class MyCompoundView : ConstraintLayout {

    // make sure to clone after inflating the layout to the component

    originalState = ConstraintSet().apply {
        clone(this@MyCompoundView)
    }

    expandedState = ConstraintSet().apply {
        clone(this@MyCompoundView)
        // Change some constraints
         connect(
             R.id.button, ConstraintSet.END,
             R.id.foo_text, ConstraintSet.START
        )
    }
}

Upvotes: 0

Pawel
Pawel

Reputation: 17288

You have two options:

  1. Create another (dummy) layout file with ConstraintLayout root that holds your layout reference with include tag.
  2. Clone layout params from new instance of your custom view: ConstraintSet.clone(context, MyCompoundView(context)).

ConstraintSet.clone(context, layoutRes) is actually pretty crude under the hood (source), it essentially inflates new ConstraintLayout from provided layout file including all child views before resolving their layout params to build ConstraintSet.

Upvotes: 1

Related Questions