底单+Android MotionLayout 实现

Ild*_*pov 6 java android kotlin android-jetpack android-motionlayout

我正在尝试使用 MotionLayout 实现底部工作表。它在一个微不足道的情况下工作 - 当底部工作表应该仅在屏幕的一半中可见时(例如)。但是当底部工作表扩展并填满整个屏幕时,我无法让它工作。

在此处输入图片说明

所以这里可以是 3 个状态:

  1. 底部工作表隐藏
  2. 底部工作表填满了半个屏幕
  3. 底页填满整个屏幕

这是布局:

<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>
Run Code Online (Sandbox Code Playgroud)

这里570dp等于半屏(例如)

以及内容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>
Run Code Online (Sandbox Code Playgroud)


问题是当底部工作表处于全屏状态时 OnSwipe 不起作用,但当底部工作表处于半屏状态时工作。我想有机会使用滑动运动隐藏底部工作表。

如何解决这个问题?是否应该添加或修改过渡?

Jas*_*son 2

你的转换只需要一点调整,约束就很好:

  • 您不需要第三次转换。如果您以同一方向在不同状态之间滑动 - 或者实际上即使您改变方向,MotionLayout 也会在多个onSwipe转换之间干净地移动。
  • 您的第二个和第三个 ConstraintSets 实际上不会更改您正在移动的片段底部边缘的位置,但您指定场景应根据相对于滑动手势的边缘计算进度。我建议您阅读MotionLayout Codelab,特别是第 9 课,它很好地说明了这个概念。结果我把touchAnchorSide改为top.
  • duration对转换没有任何意义OnSwipe,删除即可
  • dragUp无论您使用或,这并不重要dragDown,最终都会得到相同的基于垂直手势的动画。我认为dragUp在这种情况下更容易理解一些。

修改后的过渡:

    <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>
Run Code Online (Sandbox Code Playgroud)