Android 为 Activity 添加转场动画

792 阅读3分钟

一 Android 动画的分类

Android 动画.png

1.1 属性动画概览

通过控制对象的属性,来实现动画效果。
可以控制对象什么属性呢?什么属性都可以,理论是通过set和get某个属性来达到动画效果。例如常用下面一些属性来实现View对象的一些动画效果。

  • 位移:translationXtranslationYtranslationZ
  • 透明度:alpha,透明度全透明到不透明:0f->1f
  • 旋转:rotation,旋转一圈:0f->360f
  • 缩放:水平缩放scaleX,垂直缩放scaleY 相信大家对属性动画已经很熟悉了,本文不对属性动画做过多详细的阐述。我们来看看转场动画。

二 什么是转场动画

首先我们要先搞清楚什么是转场。
对于一个动画而言,它是由多个Cut,也就是多个分镜头组成的。
而转场就是分镜之间衔接的方式。

image.png
图片来自《动态设计的转场心法》

三 早期的转场

Activity 有默认的转场效果,主要用到 overridePendingTransition(int enterAnim, int exitAnim) 这个方法。

  • enterAnim —— 即将进入的 Activity,所需的动画资源id;
  • exitAnim —— 即将退出的 Activity,所需的动画资源id;
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
overridePendingTransition(R.anim.translate_in,R.anim.translate_out);

需要注意:这个方法必须在 startActivity(Intent) 或者 finish() 之后被调用才能生效。
存在的问题:只支持平移、旋转、缩放和透明度这四种动画类型,遇到稍微复杂的动画无法实现。

四 Material Design 转场动画

在 Android 5.0 之后,我们可以使用 Material Design 为我们带来的转场动画。
转场动画包含「进入」和「退出」、「共享元素」三种类型。

4.1 进入和退出动画

进入和退出动画不包括共享元素的动画,支持一下三种过渡动画类型:

  • Explode(爆炸式) - 将视图移入场景中心或从中移出。
  • Slide(滑动式) - 将视图从场景的其中一个边缘移入或移出。
  • Fade(淡入淡出式) - 通过更改视图的不透明度,在场景中添加视图或从中移除视图。 系统支持将任何扩展 Visibility 类的过渡作为进入或退出的过渡动画。
    利用Android现有的 Transition 框架,实现起来是很简单的,步骤如下:

步骤一 检查系统版本

// Check if we're running on Android 5.0 or higher
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    // Apply activity transition
} else {
    // Swap without transition
}

步骤二 指定动画

// inside your activity (if you did not enable transitions in your theme)
getWindow().requestFeature(Window.FEATURE_CONTENT_TRANSITIONS);

// set an enter transition
getWindow().setEnterTransition(new Slide());
// or set an exit transition
getWindow().setExitTransition(new Explode());

步骤三 start 设置过动画的 Activity

startActivity(intent,
              ActivityOptions.makeSceneTransitionAnimation(this).toBundle());   

4.2 共享元素动画

步骤一 在主题背景中启用窗口内容过渡

<style name="AppTheme" parent="Theme.AppCompat.Light">
<item name="android:windowContentTransitions">true</item>
</style>

步骤二 为共享元素设置上transtionName

设置name的时候两个界面都要添加上,这样才可以检测到是哪两个元素共享。

<ImageView
android:id="@+id/image"
android:layout_width="150dp"
android:layout_height="100dp"
android:transitionName="image"
android:src="@drawable/default_image" />

也可以在代码中设置:

imageView.setTransitionName("image");

步骤三 使用 ActivityOptions.makeSceneTransitionAnimation() 方法

Intent intent = new Intent(mContext, Main2Activity.class);
ActivityOptions options =
ActivityOptions.makeSceneTransitionAnimation(mContext, holder.image, "image");
startActivity(intent, options.toBundle());

设置多个元素共享的时候需要这样:

Intent intent = new Intent(mContext, Main2Activity.class);
ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(this,
        Pair.create(holder.image, "image"),
        Pair.create(holder.text, "text"));
startActivity(intent, options.toBundle());

如果你是通过 Glide 或者其他图片库加载的网络图片,大概率会遇到加载过程中黑屏的问题。
可以在 onCreate 中调用 postponeEnterTransition() 方法表明我们的动画需要延迟执行,等我们需要的时机,再调用 Activity 中的 startPostponedEnterTransition() 方法来开始执行动画。