Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to smoothly change drawable resource during MotionLayout transition?

I want to change image in fab button during transition, but i haven't found how to do it with xml because CustomAttribute tag supports only drawable colors as values. My solution is to set TransitionAdapter to MotionLayout and change drawable in onTransitionChange function.

motionLayout.setTransitionListener(object : TransitionAdapter() {
            var fromStart = true
            var wasChanged = false

            override fun onTransitionChange(
                motionLayout: MotionLayout?,
                startId: Int,
                endId: Int,
                progress: Float
            ) {
                if (!wasChanged) {
                    if (fromStart && progress >= 0.5f) {
                        fab.setImageResource(R.drawable.ic_done_black_24dp)
                        wasChanged = true
                    }
                    if (!fromStart && progress <= 0.5f) {
                        fab.setImageResource(R.drawable.ic_add_black_24dp)
                        wasChanged = true
                    }
                }
            }

            override fun onTransitionCompleted(motionLayout: MotionLayout?, currentId: Int) {
                wasChanged = false
                fromStart = !fromStart
            }

        })

But in this case image changes immediately. Is there any way to make the transition smooth like in regular transition in MotionLayout?

like image 678
Shmuser Avatar asked Mar 04 '20 18:03

Shmuser


1 Answers

There is a great way to animate the change between two images in MotionLayout. However, it may be a little tricky with the Fab interaction. As shown in this blog post, you can use an ImageFilterView and set the source and alternate source, then crossfade between them. Grabbing code directly from the blog post linked above, here's an example of what an ImageFilterView looks like in your MotionLayout

<android.support.constraint.utils.ImageFilterView
        android:id="@+id/image"
        android:background="@color/colorAccent"
        android:src="@drawable/roard"
        app:altSrc="@drawable/hoford"
        android:layout_width="64dp"
        android:layout_height="64dp"/>

Where android:src is your first image that you want and the app:altSrc is the second image that you want to crossfade to. Below, also grabbed directly from the blog post, is what the constraints will look like in your motionScene.

<ConstraintSet android:id="@+id/start">
        <Constraint
            android:id="@+id/image"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:layout_marginStart="8dp"
            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintStart_toStartOf="parent"
            motion:layout_constraintTop_toTopOf="parent">
            <CustomAttribute
                motion:attributeName="crossfade"
                motion:customFloatValue="0" />
        </Constraint>
    </ConstraintSet>

    <ConstraintSet android:id="@+id/end">
        <Constraint
            android:id="@+id/image"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:layout_marginEnd="8dp"
            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintEnd_toEndOf="parent"
            motion:layout_constraintTop_toTopOf="parent">
            <CustomAttribute
                motion:attributeName="crossfade"
                motion:customFloatValue="1" />
        </Constraint>
    </ConstraintSet>

Where you set the crossfade value as a custom attribute. Not sure how this will play with the Fab but this is the best way I know how to animate between two images.

like image 67
kjanderson2 Avatar answered Oct 14 '22 00:10

kjanderson2