Search code examples
androidandroid-constraintlayoutandroid-motionlayout

MotionLayout create transition programatically


I have a created simple MotionLayout which looks like a custom BottomNavigationView.

I'm using MotionLayout for animating the "selector". So imagine view which looks like bottom bar, inside it has 4 "tab views" and one selector.

What I'm trying to do is to create Transition programmatically since the view is custom and you may set different IDs, count of tabs, etc.

But first, I've made an XML version to see if it actually works and this is XML example"

<ConstraintSet android:id="@+id/startFromFirstTabToSecondTab">
        <Constraint
            android:id="@+id/selector"
            android:layout_width="48dp"
            android:layout_height="36dp"
            motion:layout_constraintBottom_toBottomOf="@+id/tabFirst"
            motion:layout_constraintEnd_toEndOf="@+id/tabFirst"
            motion:layout_constraintStart_toStartOf="@+id/tabFirst"
            motion:layout_constraintTop_toTopOf="@+id/tabFirst">
            <CustomAttribute
                motion:attributeName="ColorFilter"
                motion:customColorValue="@color/blue" />

           <CustomAttribute
                ...

        </Constraint>
    </ConstraintSet>

    <ConstraintSet android:id="@+id/endFromFirstTabToSecond">
        <Constraint
            android:id="@+id/selector"
            android:layout_width="48dp"
            android:layout_height="36dp"
            motion:layout_constraintBottom_toBottomOf="@+id/tabSecond"
            motion:layout_constraintEnd_toEndOf="@+id/tabSecond"
            motion:layout_constraintStart_toStartOf="@+id/tabSecond"
            motion:layout_constraintTop_toTopOf="@+id/tabSecond">
            <CustomAttribute
                motion:attributeName="ColorFilter"
                motion:customColorValue="@color/purple" />

             <CustomAttribute
                ...
        </Constraint>
    </ConstraintSet>

Now this I'm trying to convert to programmatic way, but since there is not a lot of documentation, this is what I've created :

private fun createAndSetTransition(fromTab: Tab, toTab: Tab): Int {

        val startSetId = View.generateViewId()
        val startSet = ConstraintSet()
        startSet.clone(this)
        startSet.clear(selectorId)
        startSet.connect(selectorId, ConstraintSet.START, fromTab.id, ConstraintSet.START)
        startSet.connect(selectorId, ConstraintSet.END, fromTab.id, ConstraintSet.END)
        startSet.connect(selectorId, ConstraintSet.TOP, fromTab.id, ConstraintSet.TOP)
        startSet.connect(selectorId, ConstraintSet.BOTTOM, fromTabI.id, ConstraintSet.BOTTOM)
        startSet.setColorValue(selectorId, "ColorFilter", ContextCompat.getColor(context, fromTab.color))
        startSet.apply {
            constrainWidth(selectorId, selectorWidth)
            constrainHeight(selectorId, selectorHeight)
        }

        val endSetId = View.generateViewId()
        val endSet = ConstraintSet()
        endSet.clone(this)
        endSet.clear(selectorId)
        endSet.connect(selectorId, ConstraintSet.START, toTab.id, ConstraintSet.START)
        endSet.connect(selectorId, ConstraintSet.END, toTab.id, ConstraintSet.END)
        endSet.connect(selectorId, ConstraintSet.TOP, toTab.id, ConstraintSet.TOP)
        endSet.connect(selectorId, ConstraintSet.BOTTOM, toTab.id, ConstraintSet.BOTTOM)
        endSet.setColorValue(selectorId, "ColorFilter", ContextCompat.getColor(context, toTab.color))
        endSet.apply {
            constrainWidth(selectorId, selectorWidth)
            constrainHeight(selectorId, selectorHeight)
        }

        val transitionId = View.generateViewId()
        val transition = TransitionBuilder.buildTransition(
                motionScene,
                transitionId,
                startSetId, startSet,
                endSetId, endSet)

        motionScene.addTransition(transition)

        return transitionId
    }

Afterwards, I'm running animation programmatically when user click on a Tab. From what I see, animation works, but the only thing that is animating is the color of the selector. The selector itself should move from position where it was (fromTab), to selected tab. So looks like Constraints are not animating and I cannot figure out why.


Solution

  • Make sure that your Tabs, which are created dynamically, are added to the layout and have a measured size/position in the layout, before you create the ConstriantSets.