学习安卓系统中的自定义动画和片段间的过渡效果

245 阅读7分钟

安卓中的自定义动画和片段间的过渡效果

导航组件是Android Jetpack库的一部分,允许你实现导航,从简单的按钮点击到更复杂的模式。这使得用户可以更容易地从一个目的地导航到另一个目的地。

在Fragments之间来回导航有时会让人困惑。通过自定义过渡动画,如果用户要去一个新的目的地,我们可以添加相应的和描述性的过渡动画。另外,当导航回到前一个片段时,我们可以为这个动作制作动画。

我们可以添加自定义的过渡动画,使对话片段的出现和取消成为动画。此外,我们还可以在我们的应用程序中加入共享的过渡元素,以便在新的目的地打开一个图像。

转场动画一般会改善应用程序的用户体验(UX),有助于留住用户。

前提条件

要完成本教程,你应该具备以下条件。

  • 在你的机器上安装了[Android Studio]。
  • 具有创建和运行Android应用程序的良好知识。
  • [Kotlin]编程语言的基本信息。
  • 设置和使用导航组件的基础知识,你可以在[本教程]中学习如何使用导航组件。

过渡动画

过渡动画可以有4种类型。

  • 输入-为NavHostFragment带来一个新的片段。
  • 退出-从NavHostFragment中删除当前显示的Fragment。
  • Pop Enter-当导航返回时,这将带来以前的片段。
  • Pop Exit-这将退出Fragment,为前一个Fragment提供可见空间。

我们还可以定义共享的元素过渡,它可以将一个被点击的图像移动到一个新的目的地。当你有图像而你想导航到某个特定图像的细节时,这很有用。图像会扩展到一个新的目的地。

对于对话框,我们可以在它们被显示和解散时对其运动进行动画处理。我们可以定义slide-upslide-down 过渡动画。

在翻译不同的元素时,即从左、右、上、下,我们可以在我们的动画资源文件中使用以下属性。

  • fromXDelta - 表示我们从哪个X轴值开始转换。
  • toXDelta - 表示在X轴上的什么位置。
  • fromYDelta - 表示从Y轴的什么值开始。
  • toYDelta - 表示我们要过渡到Y轴的什么值。
  • duration 单位:毫秒 - 这是动画发生的时间。

过渡动画图

Navigation Graph

从上面的图表来看。

水平过渡 (X-轴)

0% ,我们可以向右移动,即100% ,也可以向左移动,即-100%

  • -100% 移动到0% ,意味着我们的片段从左边进入。我们将利用这一点来进入我们的片段。
  • 0% 移动到100% 意味着我们的片段正在向右边移动。你可以用它来退出我们的片段。
  • 0% 移动到-100% 意味着我们的片段正在向左边移动。我们将用它来从NavHostFragment中删除当前的Fragment。
  • 100% 移动到0% 意味着我们的片段将从右边来。这将被用来带回最初的Fragment。

垂直过渡(Y轴)

0% ,我们可以移动到顶部,也就是100% ,或者我们可以向下移动到-100%

  • 100% 移动到0% ,意味着我们的DialogFragment将从底部进入。我们可以用它来创建一个幻灯片动画。
  • 0% 移动到100% 意味着我们的DialogFragment将从中心移动到底部。我们可以用它来创建一个下滑动画。
  • -100% 移动到0% ,意味着我们的DialogFragment将从顶部出现。

第1步 - 创建一个动画目录

首先,创建一个新的资源目录并将其命名为anim ,这将存放我们的过渡动画。

第2步 - 创建过渡动画

进入一个片段

这涉及到将一个新的片段带入视图。这个新的片段将从左边进入。因此我们需要创建一个名为from_left 的动画。为此,右键单击动画目录并选择new >> animation layout file

<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate android:fromXDelta="-100%" android:toXDelta="0%" android:duration="700"/>
</set>

我们从NavHostFragment中移除当前的Fragment,以便新的Fragment可以被看到。Fragment将向右侧退出,我们将创建一个名为to_right 的动画。

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate android:fromXDelta="0%" android:toXDelta="100%" android:duration="700"/>
</set>

导航回前一个Fragment

首先,我们需要移除当前正在显示的Fragment。我们将创建一个名为to_left 的动画,它将向左侧移除片段。

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate android:fromXDelta="0%" android:toXDelta="-100%" android:duration="700"/>
</set>

把最初的Fragment带回NavHostFragment上。这个Fragment将来自右边,我们将创建一个名为from_right 的动画。

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate android:fromXDelta="100%" android:toXDelta="0%" android:duration="700"/>
</set>

导航回到前一个Fragment是有帮助的,因为顶部的返回按钮也是动画的。

给片段添加动画

为了添加过渡动画,在你的NavGraph ,点击一个你想为其过渡制作动画的Action 。在你的右边,你会看到一个窗格,它有一个添加动画的部分。

Animation Pane

对于home Fragment,我们需要指定popEnterAnimpopExitAnim ,以便相应地对ActionBar/Toolbar 进行动画。

  • enterAnim 属性中,传递from_left anim。
  • exitAnim 中,通过to_right anim。
  • popEnterAnim 中传入from_right anim。
  • popExitAnim 中传入to_left anim。

对于其他动作不是导航到新目的地的Fragments,会明确地调用一个返回按钮。

在动画面板中,你将包括。

  • popEnterAnim 中传递from_right anim。
  • popExitAnim ,通过to_left anim。

第3步 - 创建对话动画

在这一步,我们将看看如何给DialogFragments制作动画。

显示对话框

我们将创建一个名为slide_up 的动画,使我们的对话框从底部到屏幕中央产生动画。

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate android:fromYDelta="100%" android:toYDelta="0%" android:duration="300"/>
</set>

关闭对话框

我们将创建一个名为slide_down 的动画,在我们的对话框从屏幕中心移动到底部的过程中为它提供动画。

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate android:fromYDelta="0%" android:toYDelta="100%" android:duration="300"/>
</set>

将动画添加到对话框中

为DialogFragment添加动画与普通的Fragments有一点不同。

首先导航到你的res "values 。在你的theme ,定义以下样式。

<style name="DialogFragmentAnimation">
    <item name="android:windowEnterAnimation">@anim/slide_up</item>
    <item name="android:windowExitAnimation">@anim/slide_down</item>
</style>

然后在你的DialogFragment ,覆盖onActivityCreated 方法并添加我们定义的样式到Dialog。

override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        dialog!!.window!!.attributes.windowAnimations = R.style.DialogFragmentAnimation
    }

第4步 - 创建共享元素过渡

在这里,一旦图片被点击,我们将导航到另一个Fragment。该图像将在另一个Fragment中扩展到一个更大的图像。

在我们的第一个Fragment布局中,添加一个ImageView

我们必须给ImageView一个transitionName - 当使用共享过渡元素时,每个视图都需要有一个独特的transitionName ,这样Android就可以确定它应该在哪些视图上执行过渡。

<ImageView
    android:id="@+id/image"
    android:layout_width="120dp"
    android:layout_height="120dp"
    android:transitionName="small_image"
    android:src="@drawable/mountain"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintHorizontal_bias="0.5"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/buttonDialog" />

在我们的第二个Fragment布局中,我们还将包括一个ImageView--前一个Fragment中的图像的扩展。

我们还将给它一个不同的过渡名称,即large image ,并给它不同的尺寸,以便它能覆盖3/4的屏幕。

<ImageView
    android:id="@+id/image"
    android:layout_width="0dp"
    android:layout_height="550dp"
    android:transitionName="large_image"
    android:scaleType="centerCrop"
    android:src="@drawable/mountain"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintHorizontal_bias="0.5"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

第一个片段的逻辑

在第一个片段中,我们将为ImageView设置一个onClickListener ,并添加以下代码来启动过渡。

binding.image.setOnClickListener {
        val extras = FragmentNavigatorExtras(binding.image to "large_image")

        findNavController().navigate(R.id action_FragmentOne_to_FragmentThree, null, null, extras)
    }

我们创建类型为FragmentNavigatorExtras 的extra,在这里我们传递被点击的ImageView的id ,然后传递我们需要过渡到的过渡名称。最后,我们执行导航并传递额外的内容。

确保你已经在你的NavGraph中创建了一个动作,将第一个片段链接到我们要导航的片段。

第二个片段的逻辑

在另一个Fragment中,我们需要指示我们的动画何时进入或离开。在onCreateView ,包括以下几行代码。

val animation = TransitionInflater.from(requireContext()).inflateTransition(android.R.transition.move)

sharedElementEnterTransition = animation
sharedElementReturnTransition = animation

演示

Demo

总结

在本教程中,我们已经了解了什么是过渡动画,以及如何在浏览目的地时添加动画。我们还研究了如何为DialogFragment的过渡制作动画,最后是如何创建一个共享元素的过渡。

来吧,用这些过渡来增强你的安卓项目,以增加你的应用程序的互动性。