如何在带约束的 MotionLayout 中创建幻灯片动画?
How to create slide animation in MotionLayout with constraints?
运动布局:
<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"
tools:context=".MainActivity"
app:layoutDescription="@xml/activity_main_scene">
<FrameLayout
android:id="@+id/left_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#0c0"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:text="right text"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left"
android:text="left text"
android:textColor="#33691E" />
</FrameLayout>
<FrameLayout
android:id="@+id/bar"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="#c00"
tools:ignore="SpeakableTextPresentCheck"
tools:layout_editor_absoluteX="918dp">
<View
android:layout_width="50dp"
android:layout_height="match_parent"
android:clickable="false" />
</FrameLayout>
<FrameLayout
android:id="@+id/right_content"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="#00c"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#fff"
android:layout_gravity="right"
android:text="right text"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#fff"
android:layout_gravity="left"
android:text="left text"
/>
</FrameLayout>
</androidx.constraintlayout.motion.widget.MotionLayout>
场景:
<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:motion="http://schemas.android.com/apk/res-auto"
>
<ConstraintSet android:id="@+id/start">
<Constraint android:id="@id/left_content"
android:layout_width="0dp"
android:layout_height="match_parent"
android:visibility="visible"
android:alpha="1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@id/bar"
/>
<Constraint android:id="@id/bar"
android:layout_width="wrap_content"
android:layout_height="match_parent"
app:layout_constraintRight_toRightOf="parent"
/>
<Constraint android:id="@id/right_content"
android:layout_width="0dp"
android:layout_height="match_parent"
app:layout_constraintLeft_toRightOf="@id/bar"
app:layout_constraintRight_toRightOf="parent"/>
</ConstraintSet>
<ConstraintSet android:id="@+id/end">
<Constraint android:id="@id/left_content"
android:layout_width="0dp"
android:layout_height="match_parent"
android:alpha="1"
/>
<Constraint android:id="@id/bar"
android:layout_width="wrap_content"
android:layout_height="match_parent"
app:layout_constraintLeft_toLeftOf="parent"
/>
<Constraint android:id="@id/right_content"
android:visibility="visible"
android:layout_width="0dp"
android:layout_height="match_parent"
app:layout_constraintLeft_toRightOf="@id/bar"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
</ConstraintSet>
<Transition
app:constraintSetStart="@+id/start"
app:constraintSetEnd="@id/end">
<!-- <OnClick app:targetId="@id/bar" app:clickAction="toggle" />-->
<OnSwipe app:touchAnchorId="@id/bar" app:dragDirection="dragLeft" />
</Transition>
</MotionScene>
我需要像这样使用旧动画应用翻译动画:
<translate android:fromXDelta="0%"
android:toXDelta="-100%"
android:duration="150"
/>
当前的动画是一个dissapearing view的resize但是我需要平移动画,怎么实现?
终于解决了,至少说起来不容易:
要在不调整内容大小的情况下实现幻灯片动画,您需要
2 个屏幕外布局,重新创建可想象的地方,可见内容将被推入或拉出。
第一个屏幕外缓冲区(位于可见布局的左侧)将镜像可见布局(不是完整副本,而是顶级容器的蓝图)。
第二个屏幕外缓冲区(位于可见布局的右侧)将是可见布局的副本。
重要提示:必须限制布局的不可见部分,因为它对用户可见,以避免将动画从 0 调整为目标大小
很难描述,但更容易显示结果:
<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"
tools:context=".MainActivity"
app:layoutDescription="@xml/activity_main_scene">
<View
android:id="@+id/off_screen_left"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
<View
android:id="@+id/off_screen_left_content"
android:layout_width="0dp"
android:layout_height="0dp"
/>
<FrameLayout
android:id="@+id/off_screen_left_bar"
android:layout_width="wrap_content"
android:layout_height="match_parent">
<View
android:layout_width="50dp"
android:layout_height="match_parent"
/>
</FrameLayout>
<View
android:id="@+id/off_screen_right"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
<FrameLayout
android:id="@+id/off_screen_right_bar"
android:layout_width="wrap_content"
android:layout_height="match_parent"
>
<View android:layout_width="50dp"
android:layout_height="match_parent"
/>
</FrameLayout>
<View android:id="@+id/off_screen_right_content"
android:layout_width="0dp"
android:layout_height="0dp"
/>
<FrameLayout
android:id="@+id/left_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#0c0"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:text="right text"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left"
android:text="left text"
android:textColor="#33691E" />
</FrameLayout>
<FrameLayout
android:id="@+id/bar"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="#c00"
tools:ignore="SpeakableTextPresentCheck">
<View
android:layout_width="50dp"
android:layout_height="match_parent"
/>
</FrameLayout>
<FrameLayout
android:id="@+id/right_content"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="#00c"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#fff"
android:layout_gravity="right"
android:text="right text"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#fff"
android:layout_gravity="left"
android:text="left text"
/>
</FrameLayout>
</androidx.constraintlayout.motion.widget.MotionLayout>
和场景:
<?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"
xmlns:motion="http://schemas.android.com/apk/res-auto"
>
<ConstraintSet android:id="@+id/off_screens">
<Constraint android:id="@id/off_screen_left"
android:layout_width="0dp"
android:layout_height="match_parent"
app:layout_constraintRight_toLeftOf="parent"
app:layout_constraintWidth_default="percent"
app:layout_constraintWidth_percent="1"
/>
<Constraint android:id="@id/off_screen_left_bar"
android:layout_width="wrap_content"
android:layout_height="match_parent"
app:layout_constraintLeft_toLeftOf="@id/off_screen_left"
/>
<Constraint android:id="@id/off_screen_left_content"
android:layout_width="0dp"
android:layout_height="match_parent"
app:layout_constraintLeft_toRightOf="@id/off_screen_left_bar"
app:layout_constraintRight_toRightOf="@id/off_screen_left"
/>
<Constraint android:id="@id/off_screen_right"
android:layout_width="0dp"
android:layout_height="match_parent"
app:layout_constraintLeft_toRightOf="parent"
app:layout_constraintWidth_default="percent"
app:layout_constraintWidth_percent="1"
/>
<Constraint android:id="@id/off_screen_right_bar"
android:layout_width="wrap_content"
android:layout_height="match_parent"
app:layout_constraintRight_toRightOf="@id/off_screen_right"
/>
<Constraint android:id="@id/off_screen_right_content"
android:layout_width="0dp"
android:layout_height="match_parent"
app:layout_constraintLeft_toLeftOf="@id/off_screen_right"
app:layout_constraintRight_toLeftOf="@id/off_screen_right_bar"
/>
</ConstraintSet>
<ConstraintSet android:id="@+id/start"
app:deriveConstraintsFrom="@id/off_screens">
<Constraint android:id="@id/left_content"
android:layout_width="0dp"
android:layout_height="match_parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@id/bar"
/>
<Constraint android:id="@id/bar"
android:layout_width="wrap_content"
android:layout_height="match_parent"
app:layout_constraintRight_toRightOf="parent"
/>
<Constraint android:id="@id/right_content"
android:layout_width="0dp"
android:layout_height="match_parent"
app:layout_constraintLeft_toLeftOf="@id/off_screen_right_content"
app:layout_constraintRight_toRightOf="@id/off_screen_right_content"/>
</ConstraintSet>
<ConstraintSet android:id="@+id/end" app:deriveConstraintsFrom="@id/off_screens">
<Constraint android:id="@id/left_content"
android:layout_width="0dp"
android:layout_height="match_parent"
app:layout_constraintLeft_toLeftOf="@id/off_screen_left_content"
app:layout_constraintRight_toRightOf="@id/off_screen_left_content"
/>
<Constraint android:id="@id/bar"
android:layout_width="wrap_content"
android:layout_height="match_parent"
app:layout_constraintLeft_toLeftOf="parent"
/>
<Constraint android:id="@id/right_content"
android:layout_width="0dp"
android:layout_height="match_parent"
app:layout_constraintLeft_toRightOf="@id/bar"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
</ConstraintSet>
<Transition
app:constraintSetStart="@+id/start"
app:constraintSetEnd="@id/end">
<OnSwipe app:touchAnchorId="@id/bar"
app:dragDirection="dragLeft" />
</Transition>
</MotionScene>
结果动画:
运动布局:
<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"
tools:context=".MainActivity"
app:layoutDescription="@xml/activity_main_scene">
<FrameLayout
android:id="@+id/left_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#0c0"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:text="right text"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left"
android:text="left text"
android:textColor="#33691E" />
</FrameLayout>
<FrameLayout
android:id="@+id/bar"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="#c00"
tools:ignore="SpeakableTextPresentCheck"
tools:layout_editor_absoluteX="918dp">
<View
android:layout_width="50dp"
android:layout_height="match_parent"
android:clickable="false" />
</FrameLayout>
<FrameLayout
android:id="@+id/right_content"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="#00c"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#fff"
android:layout_gravity="right"
android:text="right text"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#fff"
android:layout_gravity="left"
android:text="left text"
/>
</FrameLayout>
</androidx.constraintlayout.motion.widget.MotionLayout>
场景:
<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:motion="http://schemas.android.com/apk/res-auto"
>
<ConstraintSet android:id="@+id/start">
<Constraint android:id="@id/left_content"
android:layout_width="0dp"
android:layout_height="match_parent"
android:visibility="visible"
android:alpha="1"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@id/bar"
/>
<Constraint android:id="@id/bar"
android:layout_width="wrap_content"
android:layout_height="match_parent"
app:layout_constraintRight_toRightOf="parent"
/>
<Constraint android:id="@id/right_content"
android:layout_width="0dp"
android:layout_height="match_parent"
app:layout_constraintLeft_toRightOf="@id/bar"
app:layout_constraintRight_toRightOf="parent"/>
</ConstraintSet>
<ConstraintSet android:id="@+id/end">
<Constraint android:id="@id/left_content"
android:layout_width="0dp"
android:layout_height="match_parent"
android:alpha="1"
/>
<Constraint android:id="@id/bar"
android:layout_width="wrap_content"
android:layout_height="match_parent"
app:layout_constraintLeft_toLeftOf="parent"
/>
<Constraint android:id="@id/right_content"
android:visibility="visible"
android:layout_width="0dp"
android:layout_height="match_parent"
app:layout_constraintLeft_toRightOf="@id/bar"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
</ConstraintSet>
<Transition
app:constraintSetStart="@+id/start"
app:constraintSetEnd="@id/end">
<!-- <OnClick app:targetId="@id/bar" app:clickAction="toggle" />-->
<OnSwipe app:touchAnchorId="@id/bar" app:dragDirection="dragLeft" />
</Transition>
</MotionScene>
我需要像这样使用旧动画应用翻译动画:
<translate android:fromXDelta="0%"
android:toXDelta="-100%"
android:duration="150"
/>
当前的动画是一个dissapearing view的resize但是我需要平移动画,怎么实现?
终于解决了,至少说起来不容易: 要在不调整内容大小的情况下实现幻灯片动画,您需要 2 个屏幕外布局,重新创建可想象的地方,可见内容将被推入或拉出。
第一个屏幕外缓冲区(位于可见布局的左侧)将镜像可见布局(不是完整副本,而是顶级容器的蓝图)。
第二个屏幕外缓冲区(位于可见布局的右侧)将是可见布局的副本。
重要提示:必须限制布局的不可见部分,因为它对用户可见,以避免将动画从 0 调整为目标大小
很难描述,但更容易显示结果:
<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"
tools:context=".MainActivity"
app:layoutDescription="@xml/activity_main_scene">
<View
android:id="@+id/off_screen_left"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
<View
android:id="@+id/off_screen_left_content"
android:layout_width="0dp"
android:layout_height="0dp"
/>
<FrameLayout
android:id="@+id/off_screen_left_bar"
android:layout_width="wrap_content"
android:layout_height="match_parent">
<View
android:layout_width="50dp"
android:layout_height="match_parent"
/>
</FrameLayout>
<View
android:id="@+id/off_screen_right"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
<FrameLayout
android:id="@+id/off_screen_right_bar"
android:layout_width="wrap_content"
android:layout_height="match_parent"
>
<View android:layout_width="50dp"
android:layout_height="match_parent"
/>
</FrameLayout>
<View android:id="@+id/off_screen_right_content"
android:layout_width="0dp"
android:layout_height="0dp"
/>
<FrameLayout
android:id="@+id/left_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#0c0"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:text="right text"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left"
android:text="left text"
android:textColor="#33691E" />
</FrameLayout>
<FrameLayout
android:id="@+id/bar"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="#c00"
tools:ignore="SpeakableTextPresentCheck">
<View
android:layout_width="50dp"
android:layout_height="match_parent"
/>
</FrameLayout>
<FrameLayout
android:id="@+id/right_content"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="#00c"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#fff"
android:layout_gravity="right"
android:text="right text"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#fff"
android:layout_gravity="left"
android:text="left text"
/>
</FrameLayout>
</androidx.constraintlayout.motion.widget.MotionLayout>
和场景:
<?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"
xmlns:motion="http://schemas.android.com/apk/res-auto"
>
<ConstraintSet android:id="@+id/off_screens">
<Constraint android:id="@id/off_screen_left"
android:layout_width="0dp"
android:layout_height="match_parent"
app:layout_constraintRight_toLeftOf="parent"
app:layout_constraintWidth_default="percent"
app:layout_constraintWidth_percent="1"
/>
<Constraint android:id="@id/off_screen_left_bar"
android:layout_width="wrap_content"
android:layout_height="match_parent"
app:layout_constraintLeft_toLeftOf="@id/off_screen_left"
/>
<Constraint android:id="@id/off_screen_left_content"
android:layout_width="0dp"
android:layout_height="match_parent"
app:layout_constraintLeft_toRightOf="@id/off_screen_left_bar"
app:layout_constraintRight_toRightOf="@id/off_screen_left"
/>
<Constraint android:id="@id/off_screen_right"
android:layout_width="0dp"
android:layout_height="match_parent"
app:layout_constraintLeft_toRightOf="parent"
app:layout_constraintWidth_default="percent"
app:layout_constraintWidth_percent="1"
/>
<Constraint android:id="@id/off_screen_right_bar"
android:layout_width="wrap_content"
android:layout_height="match_parent"
app:layout_constraintRight_toRightOf="@id/off_screen_right"
/>
<Constraint android:id="@id/off_screen_right_content"
android:layout_width="0dp"
android:layout_height="match_parent"
app:layout_constraintLeft_toLeftOf="@id/off_screen_right"
app:layout_constraintRight_toLeftOf="@id/off_screen_right_bar"
/>
</ConstraintSet>
<ConstraintSet android:id="@+id/start"
app:deriveConstraintsFrom="@id/off_screens">
<Constraint android:id="@id/left_content"
android:layout_width="0dp"
android:layout_height="match_parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@id/bar"
/>
<Constraint android:id="@id/bar"
android:layout_width="wrap_content"
android:layout_height="match_parent"
app:layout_constraintRight_toRightOf="parent"
/>
<Constraint android:id="@id/right_content"
android:layout_width="0dp"
android:layout_height="match_parent"
app:layout_constraintLeft_toLeftOf="@id/off_screen_right_content"
app:layout_constraintRight_toRightOf="@id/off_screen_right_content"/>
</ConstraintSet>
<ConstraintSet android:id="@+id/end" app:deriveConstraintsFrom="@id/off_screens">
<Constraint android:id="@id/left_content"
android:layout_width="0dp"
android:layout_height="match_parent"
app:layout_constraintLeft_toLeftOf="@id/off_screen_left_content"
app:layout_constraintRight_toRightOf="@id/off_screen_left_content"
/>
<Constraint android:id="@id/bar"
android:layout_width="wrap_content"
android:layout_height="match_parent"
app:layout_constraintLeft_toLeftOf="parent"
/>
<Constraint android:id="@id/right_content"
android:layout_width="0dp"
android:layout_height="match_parent"
app:layout_constraintLeft_toRightOf="@id/bar"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
</ConstraintSet>
<Transition
app:constraintSetStart="@+id/start"
app:constraintSetEnd="@id/end">
<OnSwipe app:touchAnchorId="@id/bar"
app:dragDirection="dragLeft" />
</Transition>
</MotionScene>
结果动画: