Android MotionLayout Transition Listener not called
Asked Answered
E

2

11

I'm trying to make a slide animation. For it I use a MotionLayout with a MotionScene containing two ConstraintSet.

The slide animation works fine. However I get an error in the LogCat:

E/MotionLayout: WARNING NO app:layoutDescription tag

view_slider.xml

<androidx.constraintlayout.motion.widget.MotionLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/motion_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
app:layoutDescription="@xml/scene_slider"
app:showPaths="true">

<View
    android:id="@+id/btn_slide"
    android:layout_width="64dp"
    android:layout_height="64dp"
    android:background="@color/grey26" />
</androidx.constraintlayout.motion.widget.MotionLayout>

scene_slider.xml:

<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:motion="http://schemas.android.com/apk/res-auto">

    <Transition
        motion:constraintSetStart="@+id/start"
        motion:constraintSetEnd="@+id/end"
        motion:duration="1000">

        <OnSwipe
            motion:touchAnchorId="@+id/btn_slide"
            motion:touchAnchorSide="right"
            motion:dragDirection="dragRight"/>

    </Transition>

    <ConstraintSet android:id="@+id/start">
        <Constraint
            android:id="@+id/btn_slide"
            android:layout_width="64dp"
            android:layout_height="64dp"
            android:layout_marginStart="8dp"
            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintStart_toStartOf="parent"
            motion:layout_constraintTop_toTopOf="parent" />
    </ConstraintSet>

    <ConstraintSet android:id="@+id/end">
        <Constraint
            android:id="@+id/btn_slide"
            android:layout_width="64dp"
            android:layout_height="64dp"
            android:layout_marginEnd="8dp"
            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintEnd_toEndOf="parent"
            motion:layout_constraintTop_toTopOf="parent" />
    </ConstraintSet>

</MotionScene>

SliderView.kt:

class SliderView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : MotionLayout(context, attrs, defStyleAttr) {

    init {
        LayoutInflater.from(context).inflate(R.layout.view_slider, this)
    }

    override fun onFinishInflate() {
        super.onFinishInflate()

        motion_layout.setTransitionListener(object : MotionLayout.TransitionListener {
            override fun onTransitionCompleted(motionLayout: MotionLayout?, currentId: Int) {
                debug(javaClass.simpleName, "transition completed")
            }

            override fun onTransitionChange(motionLayout: MotionLayout?, startId: Int, endId: Int, progress: Float) {
                debug(javaClass.simpleName, "progress = $progress")
            }
        })
    }
}

fragment.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="@color/red">

    <com.myapp.utils.views.SliderView
        android:id="@+id/slider"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</LinearLayout>

I might be missing something because there is a layoutDescription to the MotionLayout in code.

How to fix this error and why the TransitionListener callbacks are now called?

Eclosion answered 11/4, 2019 at 11:0 Comment(8)
I had also an issue where the TransitionListener was not called when i changed the scene from code, does the animation play/work ? Can We see the code where you set or inflate the ViewOlenolin
Yes the animation work. I can slide the btn_slide. The path is also correclty displayed. I edited my question to show the full code of my custom view.Eclosion
Try to replace motion_layout.setTransitionListener() By this.setTransitionListener(), also, You probable have a reference from an Activity/Fragment, Try to set the TransitionListener from thereOlenolin
I just tryed your two suggestions but unforntunatly there is the same error in the LogCat and the listener is not calledEclosion
Putting the MotionLayout directly into my Fragment doesn't display the error message however the listener is still not called...Eclosion
Try to put the addTransitionListener() code in the init block, after the inflateOlenolin
Also, can you post your layout where you have your SliderView ?Olenolin
Let us continue this discussion in chat.Eclosion
O
1
var motionLayout:MotionLayout?=null
 init {
       motionLayout =  LayoutInflater.from(context).inflate(R.layout.view_slider, this)
    }

The line above should be equated to a named view..eg val motionLayout.

This named variable should be used in onFinish inflate..i.e

  override fun onFinishInflate() {
        super.onFinishInflate()

        motionLayout?.setTransitionListener(object : MotionLayout.TransitionListener {
            override fun onTransitionCompleted(motionLayout: MotionLayout?, currentId: Int) {
                debug(javaClass.simpleName, "transition completed")
            }

            override fun onTransitionChange(motionLayout: MotionLayout?, startId: Int, endId: Int, progress: Float) {
                debug(javaClass.simpleName, "progress = $progress")
            }
        })
    }
Oxalis answered 10/3, 2021 at 17:41 Comment(0)
R
0

MotionLayout did not worked properly in fragments. Try upgrading to beta-2 version.

Rapallo answered 19/6, 2019 at 5:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.