一、AnimationDrawable介绍

用于创建逐帧动画的对象,由一系列 Drawable 对象定义,可用作 View 对象的背景。

创建逐帧动画的最简单方法是在 XML 文件中定义动画,放置在 res/drawable/ 文件夹中,并将其设置为 View 对象的背景。然后,调用start()运行动画。

  1. 通过XML 文件中定义动画,放置在 res/drawable/ 文件夹中

以 XML 定义的 AnimationDrawable 由单个 <animation-list>元素和一系列嵌套 <item>标签组成。每个项目定义一个动画帧。请参见下面的示例。

res/drawable/ 文件夹中的 spin_animation.xml 文件:

<!-- Animation frames are wheel0.png through wheel5.png
     files inside the res/drawable/ folder -->
 <animation-list android:id="@+id/selected" android:oneshot="false">
    <item android:drawable="@drawable/wheel0" android:duration="50" />
    <item android:drawable="@drawable/wheel1" android:duration="50" />
    <item android:drawable="@drawable/wheel2" android:duration="50" />
    <item android:drawable="@drawable/wheel3" android:duration="50" />
    <item android:drawable="@drawable/wheel4" android:duration="50" />
    <item android:drawable="@drawable/wheel5" android:duration="50" />
 </animation-list>
  1. 通过代码加载和播放此动画

创建背景逐帧动画

// Load the ImageView that will host the animation and
 // set its background to our AnimationDrawable XML resource.
 ImageView img = (ImageView)findViewById(R.id.spinning_wheel_image);
 img.setBackgroundResource(R.drawable.spin_animation);

 // Get the background, which has been compiled to an AnimationDrawable object.
 AnimationDrawable frameAnimation = (AnimationDrawable) img.getBackground();

 // Start the animation (looped playback by default).
 frameAnimation.start();
 // Load the ImageView that will host the animation and
 // set its background to our AnimationDrawable XML resource.
 ImageView img = (ImageView)findViewById(R.id.spinning_wheel_image);
 img.setBackgroundResource(R.drawable.spin_animation);

 // Get the background, which has been compiled to an AnimationDrawable object.
 AnimationDrawable frameAnimation = (AnimationDrawable) img.getBackground();

 // Start the animation (looped playback by default).
 frameAnimation.start();

创建前景逐帧动画

// Load the ImageView that will host the animation and
 // set its ImageResource to our AnimationDrawable XML resource.
 ImageView img = (ImageView)findViewById(R.id.spinning_wheel_image);
 img.setImageResource(R.drawable.spin_animation);

 // Get the Drawable, which has been compiled to an AnimationDrawable object.
 AnimationDrawable frameAnimation = (AnimationDrawable) img.getDrawable();

 // Start the animation (looped playback by default).
 frameAnimation.start();
 // Load the ImageView that will host the animation and
 // set its ImageResource to our AnimationDrawable XML resource.
 ImageView img = (ImageView)findViewById(R.id.spinning_wheel_image);
 img.setImageResource(R.drawable.spin_animation);

 // Get the Drawable, which has been compiled to an AnimationDrawable object.
 AnimationDrawable frameAnimation = (AnimationDrawable) img.getDrawable();

 // Start the animation (looped playback by default).
 frameAnimation.start();

AnimationDrawable XML 属性



AnimationDrawable XML 属性

android:drawable

对用于框架的可绘制资源的引用。

android:duration

显示此帧的时间量(以毫秒为单位)。

android:oneshot

如果为真,动画将只运行一次然后停止。

android:variablePadding

如果为 true,则允许 drawable 的填充根据所选的当前状态进行更改。

android:visible

提供可绘制对象的初始可见性状态;默认值为 false。



二、AnimationDrawable Public 方法



Public methods

void

addFrame(Drawable frame, int duration)

向动画添加帧

int

getDuration(int i)

Drawable

getFrame(int index)

int

getNumberOfFrames()

void

inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Resources.Theme theme)

从 XML 资源中扩充此 Drawable,该资源可选择按主题设置样式。

boolean

isOneShot()

boolean

isRunning()

指示动画当前是否正在运行。

Drawable

mutate()

使这个 drawable 可变。

void

run()

此方法仅用于实现目的,不应直接调用。

void

setOneShot(boolean oneShot)

设置动画是播放一次还是重复播放。

boolean

setVisible(boolean visible, boolean restart)

设置此 AnimationDrawable 是否可见。

void

start()

从第一帧开始播放动画,必要时循环播放。

void

stop()

在当前帧停止动画。

void

unscheduleSelf(Runnable what)

使用当前Callback实现来取消调度此 Drawable。



Java code 添加帧图片,并播放动画

// 从layout布局文件中获取名叫imageView的ImageView控件
 ImageView imageView = (ImageView)findViewById(R.id.imageView);
 // 创建一个帧动画对象
 AnimationDrawable frameAnimation = new AnimationDrawable();
 // 添加图片到帧动画的列表中
 frameAnimation.addFrame(getDrawable(R.drawable.frame1), 50);
 frameAnimation.addFrame(getDrawable(R.drawable.frame2), 50);
 frameAnimation.addFrame(getDrawable(R.drawable.frame3), 50);
 
 // 设置帧动画是否只播放一次。为true表示只播放一次,为false表示循环播放
 frameAnimation.setOneShot(false);

 // 设置图像视图的图形为帧动画
 imageView.setImageDrawable(frameAnimation);

 // 开始播放帧动画
 frameAnimation.start();
 // 从layout布局文件中获取名叫imageView的ImageView控件
 ImageView imageView = (ImageView)findViewById(R.id.imageView);
 // 创建一个帧动画对象
 AnimationDrawable frameAnimation = new AnimationDrawable();
 // 添加图片到帧动画的列表中
 frameAnimation.addFrame(getDrawable(R.drawable.frame1), 50);
 frameAnimation.addFrame(getDrawable(R.drawable.frame2), 50);
 frameAnimation.addFrame(getDrawable(R.drawable.frame3), 50);
 
 // 设置帧动画是否只播放一次。为true表示只播放一次,为false表示循环播放
 frameAnimation.setOneShot(false);

 // 设置图像视图的图形为帧动画
 imageView.setImageDrawable(frameAnimation);

 // 开始播放帧动画
 frameAnimation.start();

三、AnimationDrawable测试程序

java:

MainActivity.java

package com.example.animationdrawabletest;

import androidx.appcompat.app.AppCompatActivity;

import android.graphics.drawable.AnimationDrawable;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;

public class MainActivity extends AppCompatActivity  implements
        View.OnClickListener{
    private static final String TAG = "lzl-test-AnimationDrawable-Test";
    private ImageView mImageViewByCode, mImageViewByXml;
    private Button mButtonByCode, mButtonByXml;
    private AnimationDrawable mAnimationDrawableByCode, mAnimationDrawableByXml;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mImageViewByCode = (ImageView) findViewById(R.id.imageView_code);
        mImageViewByCode.setOnClickListener(this);
        mButtonByCode = (Button) findViewById(R.id.button_code);
        mButtonByCode.setOnClickListener(this);
        mButtonByCode.setText("开始");

        mImageViewByXml = (ImageView) findViewById(R.id.imageView_xml);
        mImageViewByXml.setOnClickListener(this);
        mButtonByXml = (Button) findViewById(R.id.button_xml);
        mButtonByXml.setOnClickListener(this);
        mButtonByXml.setText("开始");

        setAnimationDrawableByCode();
        setAnimationDrawableByXml();
    }

    private void setAnimationDrawableByCode() {
        mAnimationDrawableByCode = new AnimationDrawable();

        // 下面图片加入到AnimationDrawable的列表中
        mAnimationDrawableByCode.addFrame(getDrawable(R.drawable.fingerprint_unlock_1), 50);
        mAnimationDrawableByCode.addFrame(getDrawable(R.drawable.fingerprint_unlock_2), 50);
        mAnimationDrawableByCode.addFrame(getDrawable(R.drawable.fingerprint_unlock_3), 50);
        mAnimationDrawableByCode.addFrame(getDrawable(R.drawable.fingerprint_unlock_4), 50);
        mAnimationDrawableByCode.addFrame(getDrawable(R.drawable.fingerprint_unlock_5), 50);

        // false表示循环播放
        mAnimationDrawableByCode.setOneShot(false);
        mImageViewByCode.setImageDrawable(mAnimationDrawableByCode);
        mAnimationDrawableByCode.start(); // 开始播放帧动画
    }

    private void setAnimationDrawableByXml() {
        // 设置从animation_list.xml获取
        mImageViewByXml.setImageResource(R.drawable.animation_list);
        mAnimationDrawableByXml = (AnimationDrawable) mImageViewByXml.getDrawable();
        /*mImageViewByXml.setBackgroundResource(R.drawable.animation_list);
        mAnimationDrawableByXml = (AnimationDrawable) mImageViewByXml.getBackground();*/
        mAnimationDrawableByXml.start(); // 开始播放帧动画
    }
    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.button_code || v.getId() == R.id.imageView_code) {
            // 判断帧动画是否正在播放
            if (mAnimationDrawableByCode.isRunning()) {
                mAnimationDrawableByCode.stop(); // 停止播放帧动画
                mButtonByCode.setText("开始");
            } else {
                mAnimationDrawableByCode.start(); // 开始播放帧动画
                mButtonByCode.setText("暂停");
            }
        }

        if (v.getId() == R.id.button_xml || v.getId() == R.id.imageView_xml) {
            // 判断帧动画是否正在播放
            if (mAnimationDrawableByXml.isRunning()) {
                mAnimationDrawableByXml.stop(); // 停止播放帧动画
                mButtonByXml.setText("开始");
            } else {
                mAnimationDrawableByXml.start(); // 开始播放帧动画
                mButtonByXml.setText("暂停");
            }
        }
    }
}
package com.example.animationdrawabletest;

import androidx.appcompat.app.AppCompatActivity;

import android.graphics.drawable.AnimationDrawable;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;

public class MainActivity extends AppCompatActivity  implements
        View.OnClickListener{
    private static final String TAG = "lzl-test-AnimationDrawable-Test";
    private ImageView mImageViewByCode, mImageViewByXml;
    private Button mButtonByCode, mButtonByXml;
    private AnimationDrawable mAnimationDrawableByCode, mAnimationDrawableByXml;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mImageViewByCode = (ImageView) findViewById(R.id.imageView_code);
        mImageViewByCode.setOnClickListener(this);
        mButtonByCode = (Button) findViewById(R.id.button_code);
        mButtonByCode.setOnClickListener(this);
        mButtonByCode.setText("开始");

        mImageViewByXml = (ImageView) findViewById(R.id.imageView_xml);
        mImageViewByXml.setOnClickListener(this);
        mButtonByXml = (Button) findViewById(R.id.button_xml);
        mButtonByXml.setOnClickListener(this);
        mButtonByXml.setText("开始");

        setAnimationDrawableByCode();
        setAnimationDrawableByXml();
    }

    private void setAnimationDrawableByCode() {
        mAnimationDrawableByCode = new AnimationDrawable();

        // 下面图片加入到AnimationDrawable的列表中
        mAnimationDrawableByCode.addFrame(getDrawable(R.drawable.fingerprint_unlock_1), 50);
        mAnimationDrawableByCode.addFrame(getDrawable(R.drawable.fingerprint_unlock_2), 50);
        mAnimationDrawableByCode.addFrame(getDrawable(R.drawable.fingerprint_unlock_3), 50);
        mAnimationDrawableByCode.addFrame(getDrawable(R.drawable.fingerprint_unlock_4), 50);
        mAnimationDrawableByCode.addFrame(getDrawable(R.drawable.fingerprint_unlock_5), 50);

        // false表示循环播放
        mAnimationDrawableByCode.setOneShot(false);
        mImageViewByCode.setImageDrawable(mAnimationDrawableByCode);
        mAnimationDrawableByCode.start(); // 开始播放帧动画
    }

    private void setAnimationDrawableByXml() {
        // 设置从animation_list.xml获取
        mImageViewByXml.setImageResource(R.drawable.animation_list);
        mAnimationDrawableByXml = (AnimationDrawable) mImageViewByXml.getDrawable();
        /*mImageViewByXml.setBackgroundResource(R.drawable.animation_list);
        mAnimationDrawableByXml = (AnimationDrawable) mImageViewByXml.getBackground();*/
        mAnimationDrawableByXml.start(); // 开始播放帧动画
    }
    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.button_code || v.getId() == R.id.imageView_code) {
            // 判断帧动画是否正在播放
            if (mAnimationDrawableByCode.isRunning()) {
                mAnimationDrawableByCode.stop(); // 停止播放帧动画
                mButtonByCode.setText("开始");
            } else {
                mAnimationDrawableByCode.start(); // 开始播放帧动画
                mButtonByCode.setText("暂停");
            }
        }

        if (v.getId() == R.id.button_xml || v.getId() == R.id.imageView_xml) {
            // 判断帧动画是否正在播放
            if (mAnimationDrawableByXml.isRunning()) {
                mAnimationDrawableByXml.stop(); // 停止播放帧动画
                mButtonByXml.setText("开始");
            } else {
                mAnimationDrawableByXml.start(); // 开始播放帧动画
                mButtonByXml.setText("暂停");
            }
        }
    }
}

xml:

activity_main.xml layout

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="300dp"
        android:orientation="horizontal">

        <ImageView
            android:id="@+id/imageView_code"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            app:srcCompat="@drawable/fingerprint_unlock_1" />

        <ImageView
            android:id="@+id/imageView_xml"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            app:srcCompat="@drawable/fingerprint_unlock_1" />
    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <Button
            android:id="@+id/button_code"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="30dp"
            android:layout_weight="1"
            android:text="开始" />
        <Button
            android:id="@+id/button_xml"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="30dp"
            android:layout_weight="1"
            android:text="开始" />
    </LinearLayout>
</LinearLayout>

/res/drawable/animation_list.xml

<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="false">
    <item android:drawable="@drawable/fingerprint_unlock_1" android:duration="50" />
    <item android:drawable="@drawable/fingerprint_unlock_2" android:duration="50" />
    <item android:drawable="@drawable/fingerprint_unlock_3" android:duration="50" />
    <item android:drawable="@drawable/fingerprint_unlock_4" android:duration="50" />
    <item android:drawable="@drawable/fingerprint_unlock_5" android:duration="50" />
</animation-list>

模拟器运行




android 动效切换卡顿 android 帧动画_xml