0

I am new to MotionLayout. I followed a simple example where the MotionLayout contains a single element say Button and this was quite easy to generate a MotionScene for it. However I have a MotionLayout which has several elements in it.

The layout looks like this -

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.motion.widget.MotionLayout 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"
    app:layoutDescription="@xml/details_view_scene">

    <ScrollView
        android:id="@+id/scroll_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fillViewport="true">

        <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <ImageView
                android:id="@+id/details_image"
                style="@style/detailsImage"
                app:layout_constraintDimensionRatio="h,16:9"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent" />

            <com.google.android.material.textview.MaterialTextView
                android:id="@+id/name_label"
                style="@style/textTitle"
                android:text="@string/name"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/details_image" />

            <com.google.android.material.textview.MaterialTextView
                android:id="@+id/name_value"
                style="@style/textSubTitle"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/name_label" />

            <com.google.android.material.floatingactionbutton.FloatingActionButton
                android:id="@+id/like_button"
                style="@style/floatingButton"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:srcCompat="@drawable/ic_profile_like" />

            <ImageView
                android:id="@+id/like_image"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:src="@drawable/ic_profile_like"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                android:visibility=“invisible”/>
        </androidx.constraintlayout.widget.ConstraintLayout>
    </ScrollView>
</androidx.constraintlayout.motion.widget.MotionLayout>

The problem is when the floating action button with id like_button is pressed, I want the imageview with id like_image to be visible and should transition from the floating action button to the top image view with id details_image.

Is this possible with MotionLayout?

Ma2340
  • 647
  • 2
  • 17
  • 34

2 Answers2

2

For the 1st question:

After the transition to the end, I want the image to be invisible.

You should read KeyFrameSet: Specifies location and attributes for views over the course of the motion sequence.

At frame 0, set alpha (or visibility) of image to 0.0 (invisible), At near last frame 99, set alpha (or visibility) of image to 1.0 (visible), At frame 100, set alpha (or visibility) of image to 0.0 (invisible),

So when you click button, the alpha of image will be from 0 -> 1 -> 0.

For the 2nd question:

On first button click, the image moves from bottom to top which is expected. On second button click, the image still stays at the top and clicking on the image moves it down. Is there a way to reset the transition on every start -> end transition

Add a MotionLayout.TransitionListener to your MotionLayout, so when transition is complete, set progress to 0 (start state).

1

Note: MotionLayout works only with its direct children. It does not support nested layout hierarchies or activity transitions. Read more here

So put your MotionLayout inside ScrollView

File: layout_test_like_button.xml

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/scroll_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fillViewport="true">

    <androidx.constraintlayout.motion.widget.MotionLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layoutDescription="@xml/layout_test_like_button_scene">

        <ImageView
            android:id="@+id/details_image"
            android:layout_width="0dp"
            android:layout_height="300dp"
            android:background="@color/colorAccent"
            android:src="@drawable/ic_baseline_broken_image_24"
            app:layout_constraintDimensionRatio="h,16:9"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <TextView
            android:id="@+id/name_label"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="name"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/details_image" />

        <com.google.android.material.textview.MaterialTextView
            android:id="@+id/name_value"
            style="textSubTitle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/name_label" />

        <com.google.android.material.floatingactionbutton.FloatingActionButton
            android:id="@+id/like_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:srcCompat="@drawable/ic_baseline_check_24" />

        <ImageView
            android:id="@+id/like_image"
            android:layout_width="200dp"
            android:layout_height="200dp"
            android:background="@color/colorPrimary"
            android:src="@drawable/ic_baseline_image_24" />
    </androidx.constraintlayout.motion.widget.MotionLayout>
</ScrollView>

You want when button press, the imageView move -> use onClick action. Set the targetId to the Button and change the layout of ImageView in constraintSetStart & constraintSetEnd

File: layout_test_like_button_scene.xml

<?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/like_image"
            android:layout_width="200dp"
            android:layout_height="200dp"
            android:visibility="invisible"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent" />
    </ConstraintSet>

    <ConstraintSet android:id="@+id/end">
        <Constraint
            android:id="@+id/like_image"
            android:layout_width="200dp"
            android:layout_height="200dp"
            android:visibility="visible"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    </ConstraintSet>

    <Transition
        app:constraintSetEnd="@+id/end"
        app:constraintSetStart="@+id/start"
        app:duration="1000">
        <OnClick
            app:clickAction="toggle"
            app:targetId="@id/like_button" />
    </Transition>
</MotionScene>

  • That works like a charm. But 2 questions I have - 1. After the transition to the end, I want the image to be invisible. How do I do it? 2. On first button click, the image moves from bottom to top which is expected. On second button click, the image still stays at the top and clicking on the image moves it down. Is there a way to reset the transition on every start -> end transition – Ma2340 Jan 03 '21 at 16:17
  • Two ways: 1. add a jumpToStart in the transition or add second transtion that auto animates to the start start... ] motion:autoTransition="animateToEnd" /> – hoford Jan 18 '21 at 15:53