简体   繁体   中英

Bottom sheet + Android MotionLayout implementation

I am trying to implement Bottom sheet using MotionLayout. It works in a trivial case - when bottom sheet should be visible only in a half of screen (for example). But I can't make it work in a scenario when bottom sheet expands and fills whole screen.

在此处输入图像描述

So here can be 3 states:

  1. Bottom sheet hidden
  2. Bottom sheet fills half screen
  3. Bottom sheet fills whole screen

Here is layout:

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

         <FrameLayout
            android:id="@+id/fragmentPlaceholder"
            android:layout_width="match_parent"
            android:layout_height="570dp"
            android:elevation="8dp"> some content here </FrameLayout>


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

Here 570dp is equal to half screen (for example)

And the content of scene_description.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">

    <Transition
        android:id="@+id/transition1"
        app:constraintSetStart="@id/bottomSheetHidden"
        app:constraintSetEnd="@id/bottomSheetHalfOpen"
        app:duration="300">

        <OnSwipe
            app:dragDirection="dragDown"
            app:onTouchUp="autoCompleteToStart"
            app:touchAnchorId="@+id/fragmentPlaceholder"
            app:touchAnchorSide="bottom"/>

    </Transition>


    <Transition
        android:id="@+id/transition2"
        app:constraintSetStart="@id/bottomSheetHalfOpen"
        app:constraintSetEnd="@id/bottomSheetOpenFullScreen"
        app:duration="300">

    </Transition>


    <Transition
        android:id="@+id/transition3"
        app:constraintSetStart="@id/bottomSheetHidden"
        app:constraintSetEnd="@id/bottomSheetOpenFullScreen"
        app:duration="300">

        <OnSwipe
            app:dragDirection="dragDown"
            app:touchAnchorId="@+id/fragmentPlaceholder"
            app:touchAnchorSide="bottom" />

    </Transition>


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

        <Constraint android:id="@id/fragmentPlaceholder">
            <Layout
                android:layout_width="match_parent"
                android:layout_height="570dp"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintTop_toBottomOf="parent"/> <!-- below screen, not visible-->
        </Constraint>

    </ConstraintSet>


    <ConstraintSet android:id="@+id/bottomSheetHalfOpen"
        app:deriveConstraintsFrom="@id/bottomSheetHidden">

        <Constraint android:id="@id/fragmentPlaceholder">
            <Layout
                android:layout_width="match_parent"
                android:layout_height="570dp"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintBottom_toBottomOf="parent" />
        </Constraint>
    </ConstraintSet>


    <ConstraintSet android:id="@+id/bottomSheetOpenFullScreen"
        app:deriveConstraintsFrom="@id/bottomSheetHidden">

        <Constraint android:id="@id/fragmentPlaceholder">
            <Layout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_marginTop="30dp"
                app:layout_constraintTop_toTopOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintBottom_toBottomOf="parent" />
        </Constraint>

    </ConstraintSet>

</MotionScene>


The problems is OnSwipe doesn't work when bottom sheet is in Full screen state, but works when bottom sheet is in half screen state. I want to have an opportunity to hide bottom sheet using swipe movement.

How this problem could be solved? Should transitions be added or modified?

Your transitions just needed a little tweaking, constraints were fine:

  • You don't need a third transition. If you're swiping between different states in the same direction - or actually even if you change directions, MotionLayout takes care of cleanly moving through multiple onSwipe transitions.
  • Your second and third ConstraintSets do not actually change the position of the bottom edge of fragment you're moving, but you specified that the scene should calculate progress based on that edge relative to the swipe gesture. I recommend going through theMotionLayout codelab and specifically Lesson 9 which illustrates this concept really well. As a consequence I changed the touchAnchorSide to top .
  • duration means nothing to OnSwipe transitions, can just delete it
  • It really doesn't matter whether you use dragUp or dragDown , it ends up with the same vertical gesture-based animation. I think dragUp is a little more understandable in this case.

Modified transitions:

    <Transition
        android:id="@+id/transition1"
        app:constraintSetStart="@id/bottomSheetHidden"
        app:constraintSetEnd="@id/bottomSheetHalfOpen">

        <OnSwipe
            app:dragDirection="dragUp"
            app:onTouchUp="autoCompleteToStart"
            app:touchAnchorId="@+id/fragmentPlaceholder"
            app:touchAnchorSide="top"/>

    </Transition>

    <Transition
        android:id="@+id/transition2"
        app:constraintSetStart="@id/bottomSheetHalfOpen"
        app:constraintSetEnd="@id/bottomSheetOpenFullScreen">

        <OnSwipe
            app:dragDirection="dragUp"
            app:touchAnchorId="@+id/fragmentPlaceholder"
            app:touchAnchorSide="top" />

    </Transition>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM