13

While playing with MotionLayouts in a RecyclerView I noticed that the MotionLayouts would not animate the wrapping around their children if these happened to change in height.

A simple way to reproduce that behaviour would be with the following layout :

<FrameLayout 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.support.constraint.motion.MotionLayout
        android:id="@+id/motion_container"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/colorPrimary"
        app:layoutDescription="@xml/scene">

        <View
            android:id="@+id/child"
            android:layout_width="0dp"
            android:layout_height="200dp"
            android:background="@color/colorAccent"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"/>

    </android.support.constraint.motion.MotionLayout>

</FrameLayout>

And the associated MotionScene with the OnClick trigger :

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

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

        <OnClick
            motion:target="@id/child"
            motion:mode="toggle"/>

    </Transition>

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

        <Constraint
            android:id="@id/child"
            android:layout_height="200dp"/>

    </ConstraintSet>

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

        <Constraint
            android:id="@id/child"
            android:layout_height="400dp"/>

    </ConstraintSet>

</MotionScene>

Which would give the following result :

Behaviour demonstration

As you can see, the MotionLayout's height is set to the final expected height as soon as the transition begins, making its blue background visible until the child view finishes its own height transition and fully overlaps it.

The same thing happens in a RecyclerView if you try to implement an expending item animation.

Would there be a way to make the MotionLayout fit exactly the height of it's children during transitions or would that just be too much cost efficient?

krow
  • 166
  • 1
  • 5
  • Have you ever tried wrapping layout into a MotionLayout instead of FrameLayout? If you replace your root element with MotionLayout and arrange transition depending on replacement, you can achieve what you want. – ycagri Sep 21 '18 at 11:52
  • @krow Did you ever find a proper solution for this issue? – Sean Barbeau Nov 06 '18 at 18:54

1 Answers1

1

Avoid resizing the boundaries of the MotionLayout. Instead, make it bigger and only animate the size of your child objects. You can make the empty area transparent and pass touch events to the underlying views.

Source and example: https://medium.com/vrt-digital-studio/picture-in-picture-video-overlay-with-motionlayout-a9404663b9e7

RWIL
  • 6,629
  • 1
  • 24
  • 32
  • 3
    This is a decent hack. However it is not an approriate solution if I'm using the MotionLayout as a RecyclerView list item. – krow Oct 03 '18 at 12:55
  • If you need to change the size of the recyclerview element this is more tricky. You can take a look at this post https://stackoverflow.com/questions/27446051/recyclerview-animate-item-resize. But I'm not sure how this woud cooperate with MotionLayout – RWIL Oct 03 '18 at 14:45
  • For a simple expand animation on a root list item view, a LayoutTransition with matching interpolator and duration to the MotionLayout does work on the expanding state. However, on the collapsing state, the MotionLayout height is changed only once the SceneTransition has ended thus causing a delayed LayoutTransition. Manually changing the height of a MotionLayout causes SceneTransition inconsistencies. – krow Oct 04 '18 at 08:53