动画与过渡:让APP“活”起来
说实话,动画是APP的灵魂。没有动画的APP,就像一杯白开水——能喝,但没滋味。我刚开始做Android开发时,总觉得动画是锦上添花的东西,直到有一次给客户演示原型,对方说:“你这按钮点下去没反应啊?”其实有反应,只是没动画反馈。嗯,从那以后,我把动画提到了和功能同等重要的位置。
今天咱们聊聊Android里的动画体系。说白了,就是怎么让界面元素动起来,怎么让页面切换更丝滑。我会把实际项目中的经验揉进去,你跟着走一遍,基本就能应付大部分动画需求了。
View动画(Tween Animation)
View动画是Android最早期的动画方案。它只对View的视觉效果做变换,不改变View的实际属性。什么意思呢?比如你把一个按钮平移了100像素,它看起来是移动了,但点击区域还在原地。我在项目中就踩过这个坑——用户点不到按钮,因为实际位置没变。
View动画支持四种基本变换:
| 动画类型 | XML标签 | 作用 |
|---|---|---|
| 缩放 | scale | 放大或缩小 |
| 旋转 | rotate | 绕中心或指定点旋转 |
| 平移 | translate | 沿X或Y轴移动 |
| 透明度 | alpha | 从透明到不透明 |
来个实际例子。假设你想让一个图片从左侧滑入:
<!-- res/anim/slide_in_left.xml -->
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:fromXDelta="-100%"
android:toXDelta="0%"
android:duration="500" />
<alpha
android:fromAlpha="0.0"
android:toAlpha="1.0"
android:duration="500" />
</set>
在代码里这样用:
Animation anim = AnimationUtils.loadAnimation(this, R.anim.slide_in_left);
imageView.startAnimation(anim);
android:fillAfter="true"。我曾经因为这个被测试妹子追着改bug,说按钮“跳来跳去”。
属性动画(Property Animation)
属性动画是View动画的升级版。它真正改变对象的属性值,而不是只改视觉效果。说白了,你用属性动画移动一个按钮,它的点击区域也会跟着走。这才是“真·动画”。
核心类是 ValueAnimator 和 ObjectAnimator。我个人习惯用 ObjectAnimator,因为它更直接:
ObjectAnimator animator = ObjectAnimator.ofFloat(
myView,
"translationX",
0f, 300f
);
animator.setDuration(1000);
animator.start();
你想想看,这比View动画灵活多了。你可以对任何对象的任何属性做动画,只要它有setter方法。比如自定义View里的 progress 属性,或者背景颜色:
ObjectAnimator colorAnim = ObjectAnimator.ofObject(
myView,
"backgroundColor",
new ArgbEvaluator(),
0xFF0000, 0x00FF00
);
colorAnim.setDuration(2000);
colorAnim.start();
AnimatorSet 可以把多个动画组合起来,实现“同时播放”、“顺序播放”等效果。我在做登录页面的Logo动画时,就用它实现了“先放大再旋转”的效果,用户体验直接拉满。
帧动画(Frame Animation)
帧动画,说白了就是“翻书动画”。你把一张张图片按顺序播放,看起来就像在动。适合做加载中的小菊花、或者一些简单的逐帧效果。
在 res/drawable 下定义:
<!-- loading_animation.xml -->
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false">
<item android:drawable="@drawable/frame_01" android:duration="100" />
<item android:drawable="@drawable/frame_02" android:duration="100" />
<item android:drawable="@drawable/frame_03" android:duration="100" />
<item android:drawable="@drawable/frame_04" android:duration="100" />
</animation-list>
代码里启动:
ImageView loadingView = findViewById(R.id.loading);
loadingView.setImageResource(R.drawable.loading_animation);
AnimationDrawable anim = (AnimationDrawable) loadingView.getDrawable();
anim.start();
Activity过渡动画
Activity之间的切换动画,说白了就是“翻页效果”。Android提供了两种方式:
1. 主题中定义:
<style name="AppTheme" parent="Theme.AppCompat.Light">
<item name="android:windowEnterTransition">@transition/slide_right</item>
<item name="android:windowExitTransition">@transition/slide_left</item>
</style>
2. 代码中调用:
startActivity(intent);
overridePendingTransition(R.anim.slide_in_right, R.anim.slide_out_left);
我个人更推荐用 Material Design 的共享元素过渡。比如两个Activity里都有同一张图片,你可以让它在切换时“飞”过去,效果非常酷:
// Activity A
Intent intent = new Intent(this, DetailActivity.class);
ActivityOptionsCompat options = ActivityOptionsCompat
.makeSceneTransitionAnimation(this, imageView, "shared_image");
startActivity(intent, options.toBundle());
// Activity B 的布局中
<ImageView
android:transitionName="shared_image"
... />
Lottie动画库
Lottie是Airbnb开源的一个动画库。它把设计师用After Effects做的动画导出成JSON文件,然后直接在APP里渲染。说白了,设计师做什么,APP就显示什么,几乎零损耗。
为什么我强烈推荐它?因为它解决了动画开发的终极难题——设计师和开发者的沟通成本。以前设计师给一个动效,我得用代码一点一点调,调完还不一定像。现在好了,设计师导出JSON,我直接扔进去:
// 添加依赖:implementation 'com.airbnb.android:lottie:6.0.0'
// 布局中
<com.airbnb.lottie.LottieAnimationView
android:id="@+id/lottie_view"
android:layout_width="200dp"
android:layout_height="200dp"
app:lottie_rawRes="@raw/loading_animation"
app:lottie_loop="true"
app:lottie_autoPlay="true" />
代码控制也很简单:
LottieAnimationView lottieView = findViewById(R.id.lottie_view);
lottieView.setAnimation(R.raw.confetti);
lottieView.playAnimation();
// 监听动画进度
lottieView.addAnimatorUpdateListener(animation -> {
float progress = animation.getAnimatedValueAbsolute();
// 根据进度做其他事情
});
如何选择?一张表说清楚
| 场景 | 推荐方案 | 原因 |
|---|---|---|
| 简单缩放/旋转/平移 | View动画 | 轻量,代码少 |
| 需要改变实际属性 | 属性动画 | 真正改变对象状态 |
| 简单逐帧效果 | 帧动画 | 实现简单,但注意OOM |
| 页面切换 | 过渡动画 | 系统原生支持,体验好 |
| 复杂动效/设计师主导 | Lottie | 还原度高,文件小 |
最后说一句:动画不是越多越好。我见过有些APP,每个按钮都弹一下,每个页面都转一圈,看得人眼花。记住一个原则——动画是为了引导用户,不是为了炫技。该动的时候动,不该动的时候别动,这才是高手。