说起动画大家想必都比较熟悉,因为开发中要经常面对各种各样的动画效果。如果遇到一个比较“挑剔”的设计师,在自定义控件和动画方面没有两把像样的刷子估计就要受尽折磨了。自定义控件除了一些View相关知识比较重要外,动画也占相当重要的部分。Android自发布到现在经历了多次重大版本迭代,UI效果已经变的相当强大,当年从诺基亚N73过渡到Android手机,感觉换了一片天地,其强大的功能和酷炫的界面令人折服,但这种酷炫跟今天的手机来比,估计要“差之千里”了。言归正传,今天主要讲Android的动画,在Android3.0之前,动画主要分为两类:补间动画和帧动画。Android3.0发布之后,属性动画正式登场,可以说是开启了动画的新纪元。除了这3种动画外,还出现了一些在特定领域使用的动画,如转场动画,触摸反馈动画等。本文的重点是Android的三大主要动画,因为篇幅较长分为了两篇,第一篇主要内容为补间动画和帧动画,第二篇——Android动画详解(下)则集中精力介绍属性动画。

Android动画详解(上)

补间动画

补间动画在Android早期版本上可以说是“一手遮天”,但随着属性动画的发布地位就明显下降了。补间动画在现在的开发中应用的已经较少,因为其只对View起作用,而且View的位置并未更改,很容易导致其点击事件响应错位。虽然补间动画确定明显,但是一些简单的场景还是可以一试的,毕竟用起来方便。
补间动画主要可以实现平移、缩放、旋转、透明度变化4种基本动画以及其组合实现的组合动画。如下图所示:
Android动画详解(上)
图中所说的位置既可能是坐标,也可能是百分比。比如说pivotX为50时代表作为为50,pivotX为0.5或者50%时则该图形的X方向的中心,如果是50P%则代表父布局的X方向的中心。
Android动画详解(上)
上图为补间动画的一个简单实现,其XML代码如下:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="5000"
    android:fillAfter="true"
    android:interpolator="@android:anim/accelerate_decelerate_interpolator"
    android:shareInterpolator="true">
    <translate
        android:fromXDelta="0%"
        android:fromYDelta="0%"
        android:toXDelta="100%"
        android:toYDelta="100%" />

    <scale
        android:fromXScale="1.0"
        android:fromYScale="1.0"
        android:pivotX="50%"
        android:pivotY="50%"
        android:toXScale="0"
        android:toYScale="0" />

    <rotate
        android:fromDegrees="0"
        android:pivotX="50%"
        android:pivotY="50%"
        android:toDegrees="360" />

    <alpha
        android:fromAlpha="1.0"
        android:toAlpha="0" />
</set>

其中:

  • android:duration——动画持续时间
  • android:fillAfter——是否保留动画结束时的效果
  • android:interpolator——插值器设置
  • android:shareInterpolator——是否共享插值器

插值器主要用于控制动画的变化速率,Android提供了多种插值器供我们选择。如:

  • LinearInterpolator——线性插值器
  • AccelerateInterpolator——加速插值器
  • DecelerateInterpolator——减速插值器
  • AccelerateDecelerateInterpolator——加减速插值器
  • CycleInterpolator——正弦加速器

帧动画

帧动画的使用比较简单,只要有合理的素材就可以达到自己想要的效果。帧动画的核心是AnimationDrawable类,它的方法也比较简单。

  • start()——开始播放动画
  • stop()——在当前帧结束动画
  • isRunning()——是否正在播放
  • getNumberOfFrames()——获得所有的帧数
  • getFrame(int index)——获得对应索引的帧
  • getDuration(int i)——获得对应索引帧的持续时间
  • isOneShot()——是否仅播放一次
  • setOneShot(boolean oneShot)——设置是否仅播放一次
  • addFrame(@NonNull Drawable frame, int duration)——动态添加一帧,并设置该帧的持续时间

下面为一个帧动画的效果图,其中左侧的动画使用的是XML方式,右侧的动画使用的是Java的方式。
Android动画详解(上)
XML的配置代码如下:

<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="false">
    <item android:drawable="@mipmap/zuan1" android:duration="200"/>
    <item android:drawable="@mipmap/zuan2" android:duration="200"/>
    <item android:drawable="@mipmap/zuan3" android:duration="200"/>
    <item android:drawable="@mipmap/zuan4" android:duration="200"/>
    <item android:drawable="@mipmap/zuan5" android:duration="200"/>
    <item android:drawable="@mipmap/zuan6" android:duration="200"/>
    <item android:drawable="@mipmap/zuan7" android:duration="200"/>
    <item android:drawable="@mipmap/zuan8" android:duration="200"/>
    <item android:drawable="@mipmap/zuan9" android:duration="200"/>
</animation-list>

Java方式(包括了xml方式的调用)的代码如下:

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_frame_animation);
        mXmlImg = this.findViewById(R.id.frame_xml_img);
        mJavaImg = this.findViewById(R.id.frame_java_img);
        final AnimationDrawable xmlDrawable = (AnimationDrawable) getResources().getDrawable(R.drawable.frameanimation);
        mXmlImg.setImageDrawable(xmlDrawable);
        final AnimationDrawable javaDrawable = new AnimationDrawable();
        javaDrawable.setOneShot(false);//是否执行1次
        int resId;
        for (int i = 1; i < 12; i++) {
            resId = getResources().getIdentifier("hj" + i, "mipmap", getPackageName());
            javaDrawable.addFrame(getResources().getDrawable(resId), 200);
        }
        mJavaImg.setImageDrawable(javaDrawable);
        findViewById(android.R.id.content).post(new Runnable() {
            @Override
            public void run() {
                xmlDrawable.start();
                javaDrawable.start();
            }
        });
    }

注意,之所以start方法要在post里面调用是因为onCreate()中,对应的AnimationDrawable可能还未附着到Window上。另外我们可以在onWindowFocusChange()或者onResume()方法中调用。

项目代码见:Android动画详解(下)

相关文章:

  • 2021-11-16
  • 2022-01-06
  • 2022-12-23
  • 2022-01-01
  • 2021-07-10
  • 2021-04-04
  • 2021-04-12
  • 2021-12-29
猜你喜欢
  • 2021-07-07
  • 2021-07-28
  • 2021-12-27
  • 2021-10-19
  • 2022-12-23
相关资源
相似解决方案