0

When animating a motion layout(expand animation) inside a HorizontalScrollView at the end of the animation the scroll view jumps to the start(see attached video). Tried to use the following code to move scroll view back:

 motion.setTransitionListener(object : MotionLayout.TransitionListener {
            override fun onTransitionCompleted(motionLayout: MotionLayout, currentId: Int) {
                motionLayout.post {
                    scrollView.fullScroll(HorizontalScrollView.FOCUS_RIGHT)
                }
            }
        }

But the experience is not seamless, I actually see it jumping back. What I want is the layout to stay still after the expand animation without the scroll view jump.

My layout:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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=".MainActivity">

    <HorizontalScrollView
        android:id="@+id/horizontalScrollView"
        android:layout_width="match_parent"
        android:layout_gravity="bottom|end"
        android:fillViewport="true"
        android:layout_height="64dp">

        <androidx.constraintlayout.motion.widget.MotionLayout
            android:id="@+id/motion"
            android:layout_width="wrap_content"
            android:layout_height="64dp"
            app:layoutDescription="@xml/activity_main_scene">

            <com.google.android.material.imageview.ShapeableImageView
                android:id="@+id/sms"
                android:layout_width="40dp"
                android:layout_height="40dp"
                android:layout_gravity="center_vertical"
                android:background="@color/teal_200"
                app:shapeAppearanceOverlay="@style/CameraActionView"
                app:srcCompat="@drawable/ic_launcher_foreground" />

            <com.google.android.material.imageview.ShapeableImageView
                android:id="@+id/sting"
                android:layout_width="40dp"
                android:layout_height="40dp"
                android:layout_gravity="center_vertical"
                android:background="@color/teal_200"
                app:shapeAppearanceOverlay="@style/CameraActionView"
                app:srcCompat="@drawable/ic_launcher_foreground" />

            <com.google.android.material.imageview.ShapeableImageView
                android:id="@+id/soundMode"
                android:layout_width="40dp"
                android:layout_height="40dp"
                android:layout_gravity="center_vertical"
                android:background="@color/teal_200"
                app:shapeAppearanceOverlay="@style/CameraActionView"
                app:srcCompat="@drawable/ic_launcher_foreground" />

            <com.google.android.material.imageview.ShapeableImageView
                android:id="@+id/natureSound"
                android:layout_width="40dp"
                android:layout_height="40dp"
                android:layout_gravity="center_vertical"
                android:background="@color/teal_200"
                app:shapeAppearanceOverlay="@style/CameraActionView"
                app:srcCompat="@drawable/ic_launcher_foreground" />

            <com.google.android.material.imageview.ShapeableImageView
                android:id="@+id/light"
                android:layout_width="40dp"
                android:layout_height="40dp"
                android:layout_gravity="center_vertical"
                android:background="@color/teal_200"
                app:shapeAppearanceOverlay="@style/CameraActionView"
                app:srcCompat="@drawable/ic_launcher_foreground" />

            <com.google.android.material.imageview.ShapeableImageView
                android:id="@+id/twoWaySound"
                android:layout_width="40dp"
                android:layout_height="40dp"
                android:layout_gravity="center_vertical"
                android:background="@color/teal_200"
                app:shapeAppearanceOverlay="@style/CameraActionView"
                app:srcCompat="@drawable/ic_launcher_foreground" />

            <com.google.android.material.imageview.ShapeableImageView
                android:id="@+id/photo"
                android:layout_width="40dp"
                android:layout_height="40dp"
                android:layout_gravity="center_vertical"
                android:background="@color/teal_200"
                app:shapeAppearanceOverlay="@style/CameraActionView"
                app:srcCompat="@drawable/ic_launcher_foreground" />

            <com.google.android.material.imageview.ShapeableImageView
                android:id="@+id/handle"
                android:layout_width="40dp"
                android:layout_height="40dp"
                android:layout_gravity="center_vertical"
                android:background="@color/teal_200"
                app:shapeAppearanceOverlay="@style/CameraActionView"
                app:srcCompat="@drawable/ic_launcher_foreground" />

        </androidx.constraintlayout.motion.widget.MotionLayout>

    </HorizontalScrollView>

</FrameLayout>


<?xml version="1.0" encoding="utf-8"?>
<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <ConstraintSet android:id="@+id/start">

        <Constraint
            android:id="@+id/sms"
            android:layout_width="@dimen/live_button_size"
            android:layout_height="@dimen/live_button_size"
            android:alpha="0"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:visibilityMode="ignore" />

        <Constraint
            android:id="@+id/sting"
            android:layout_width="@dimen/live_button_size"
            android:layout_height="@dimen/live_button_size"
            android:alpha="0"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:visibilityMode="ignore" />

        <Constraint
            android:id="@+id/soundMode"
            android:layout_width="@dimen/live_button_size"
            android:layout_height="@dimen/live_button_size"
            android:alpha="0"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:visibilityMode="ignore" />

        <Constraint
            android:id="@+id/natureSound"
            android:layout_width="@dimen/live_button_size"
            android:layout_height="@dimen/live_button_size"
            android:alpha="0"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:visibilityMode="ignore" />

        <Constraint
            android:id="@+id/light"
            android:layout_width="@dimen/live_button_size"
            android:layout_height="@dimen/live_button_size"
            android:alpha="0"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:visibilityMode="ignore" />

        <Constraint
            android:id="@+id/twoWaySound"
            android:layout_width="@dimen/live_button_size"
            android:layout_height="@dimen/live_button_size"
            android:alpha="0"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:visibilityMode="ignore" />

        <Constraint
            android:id="@+id/photo"
            android:layout_width="@dimen/live_button_size"
            android:layout_height="@dimen/live_button_size"
            android:alpha="0"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:visibilityMode="ignore" />

        <Constraint
            android:id="@+id/handle"
            android:layout_width="@dimen/live_button_size"
            android:layout_height="@dimen/live_button_size"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:visibilityMode="ignore" />

    </ConstraintSet>

    <ConstraintSet android:id="@+id/end">

        <Constraint
            android:id="@+id/sms"
            android:layout_width="@dimen/live_button_size"
            android:layout_height="@dimen/live_button_size"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:visibilityMode="ignore" />

        <Constraint
            android:id="@+id/sting"
            android:layout_width="@dimen/live_button_size"
            android:layout_height="@dimen/live_button_size"
            android:layout_marginEnd="12dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@+id/sms"
            app:layout_constraintTop_toTopOf="parent"
            app:visibilityMode="ignore" />

        <Constraint
            android:id="@+id/soundMode"
            android:layout_width="@dimen/live_button_size"
            android:layout_height="@dimen/live_button_size"
            android:layout_marginEnd="12dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@+id/sting"
            app:layout_constraintTop_toTopOf="parent"
            app:visibilityMode="ignore" />

        <Constraint
            android:id="@+id/natureSound"
            android:layout_width="@dimen/live_button_size"
            android:layout_height="@dimen/live_button_size"
            android:layout_marginEnd="12dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@+id/soundMode"
            app:layout_constraintTop_toTopOf="parent"
            app:visibilityMode="ignore" />

        <Constraint
            android:id="@+id/light"
            android:layout_width="@dimen/live_button_size"
            android:layout_height="@dimen/live_button_size"
            android:layout_marginEnd="12dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@+id/natureSound"
            app:layout_constraintTop_toTopOf="parent"
            app:visibilityMode="ignore" />

        <Constraint
            android:id="@+id/twoWaySound"
            android:layout_width="@dimen/live_button_size"
            android:layout_height="@dimen/live_button_size"
            android:layout_marginEnd="12dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@+id/light"
            app:layout_constraintTop_toTopOf="parent"
            app:visibilityMode="ignore" />

        <Constraint
            android:id="@+id/photo"
            android:layout_width="@dimen/live_button_size"
            android:layout_height="@dimen/live_button_size"
            android:layout_marginEnd="12dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@+id/twoWaySound"
            app:layout_constraintTop_toTopOf="parent"
            app:visibilityMode="ignore" />

        <Constraint
            android:id="@+id/handle"
            android:layout_width="@dimen/live_button_size"
            android:layout_height="@dimen/live_button_size"
            android:layout_marginEnd="12dp"
            android:rotation="180"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@+id/photo"
            app:layout_constraintTop_toTopOf="parent"
            app:visibilityMode="ignore" />

    </ConstraintSet>

    <Transition
        app:constraintSetEnd="@id/end"
        app:constraintSetStart="@+id/start"
        app:duration="250"
        app:motionInterpolator="easeInOut">
        <OnClick app:targetId="@+id/handle" />
    </Transition>
</MotionScene>

video link: https://streamable.com/6t0oa0

Evgeni Roitburg
  • 1,958
  • 21
  • 33
  • Without the MotionScene we can only guess at what the animation is doing. You should provide the MotionScene file (xml/activity_main_scene) – hoford Jun 08 '22 at 22:58
  • Also remove or include the style stuff – hoford Jun 08 '22 at 23:17
  • You can see the animation and the described behavior in the link.. Anyway I'm attaching the scene as well – Evgeni Roitburg Jun 09 '22 at 09:35
  • Thanks for the sample. I can't get it to not flash ScrollView reposition its self and draws with out any way to intercept before the draw. If that was to total of your UI in the ScrollView you could do the whole thing in MotionLayout. If you are interested in that solution I can build an implementation. – hoford Jun 13 '22 at 20:36

0 Answers0