【Android 开发】帧动画(Frame animation)详解

引言

Android开发里一共有三大动画,分别是帧动画(Frame animation)、补间动画(Tween animation)和属性动画(Property animation),先来介绍一下最简单的动画——帧动画。


内容简概

一、概念及常用方法
二、案例——火焰动画
三、运行效果

具体内容

一、概念及常用方法

(一)概念

我们平时看的电影、动画片其实都是一帧一帧构成的,通俗地讲就是一张图片是一帧,当播放速度足够快,因为人眼"视觉残留"的原因,会让我们造成动画的"错觉"。这里的帧动画也是如此,Android中实现帧动画,一般我们也会使用Drawable。通过xml方式实现常会用到animation-list。

(二)常用方法
animationDrawable 作用
.stop() 停止动画
.start() 开始动画
.isRunning() 判断动画是否正在进行
animation-list 作用
oneshot =false反复循环执行,=true执行一次
duration 图片显示时间长度

二、案例——火焰动画

(一)前期准备
(二)xml方式实现
  1. 创建一个图片文件


  1. 放入所有图片,配置基本属性(播放方式、时间)
<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="false">
    <!--oneshot设置反复执行-->
    <!--一个item对应一帧:一张图片-->
    <item android:drawable="@drawable/campfire01"
        android:duration="100"/>
    <item android:drawable="@drawable/campfire02"
        android:duration="100"/>
    <item android:drawable="@drawable/campfire03"
        android:duration="100"/>
    <!--后面图片操作同上,一共17张图片-->
</animation-list>
  1. 图片文件有了,接着到我们的布局文件:activity_main.xml:
<?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"
    tools:context=".MainActivity"
    android:orientation="vertical">

    <Button
        android:id="@+id/btn_start"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="开始" />

    <Button
        android:id="@+id/btn_stop"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="停止" />

    <ImageView
        android:id="@+id/iv_anim"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@drawable/fire_anim"
        android:layout_gravity="center"/>
</LinearLayout>
  1. 最后是我们的MainActivity.java,这里在这里控制动画的开始以及暂停。
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
    private Button btn_start;
    private Button btn_stop;
    private ImageView iv_anim;
    private AnimationDrawable anim;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        bindViews();
        anim = (AnimationDrawable) iv_anim.getBackground();
    }

    private void bindViews() {
        btn_start = findViewById(R.id.btn_start);
        btn_stop = findViewById(R.id.btn_stop);
        iv_anim = findViewById(R.id.iv_anim);
        btn_start.setOnClickListener(this);
        btn_stop.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_start:
                anim.start();
                break;
            case R.id.btn_stop:
                anim.stop();
                break;
        }
    }
}
(三)代码方式创建

通过xml方式实现最大的弊端就是当图片数量多时,代码量巨大,而且不易修改,而通过代码实现则能优化这一点。

  1. 首先配置布局文件activity_main
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:orientation="vertical"
    android:id="@+id/main">

    <Button
        android:id="@+id/btn_start"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="开始" />

    <Button
        android:id="@+id/btn_stop"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="停止" />

    <ImageView
        android:id="@+id/iv_anim"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@drawable/fire_anim"
        android:layout_gravity="center"/>
</LinearLayout>
  1. 然后在MainActivity中完成添加图片、设置播放时间等相关操作。
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
    private Button btn_start;
    private Button btn_stop;
    private ImageView iv_anim;
    private AnimationDrawable anim;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 1.找到控件
        bindViews();

        // 2. 添加每一帧的动画
        anim = new AnimationDrawable();
        int[] resID = {R.drawable.campfire01,R.drawable.campfire02,R.drawable.campfire03,
                R.drawable.campfire04,R.drawable.campfire05,R.drawable.campfire06,
                R.drawable.campfire07,R.drawable.campfire08,R.drawable.campfire09,
                R.![1574069883075.gif](https://upload-images.jianshu.io/upload_images/18962003-dc22d969220726c8.gif?imageMogr2/auto-orient/strip)
drawable.campfire10,R.drawable.campfire11,R.drawable.campfire12,
                R.drawable.campfire13,R.drawable.campfire14,R.drawable.campfire15,
                R.drawable.campfire16,R.drawable.campfire17};
        for (int id:resID){
            anim.addFrame(getResources().getDrawable(id,null),100);
        }
        // 3. 设置循环播放
        anim.setOneShot(false);
        // 4. 设置ImageView的背景为AnimationDrawable
        iv_anim.setBackground(anim);
    }
    private void bindViews() {
        btn_start = findViewById(R.id.btn_start);
        btn_stop = findViewById(R.id.btn_stop);
        iv_anim = findViewById(R.id.iv_anim);
        btn_start.setOnClickListener(this);
        btn_stop.setOnClickListener(this);
    }
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_start:
                anim.start();
                break;
            case R.id.btn_stop:
                anim.stop();
                break;
        }
    }
}

三、运行效果

通过上面两种方式实现的效果是一样的,动图如下:



后记

用不同方法实现同一种效果可以学到更多,也有助于加深理解。AnimationDrawable还有其他几种运行方式,就不一一展开了,甩个链接→AnimationDrawable运行的几种方式

优点:有非常大的灵活性,表现任何想表现的内容,合于表演很细腻的动画。
弊端:容易引起OOM,就是“内存耗尽”或者卡顿。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 162,408评论 4 371
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,690评论 2 307
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 112,036评论 0 255
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,726评论 0 221
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,123评论 3 296
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 41,037评论 1 225
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,178评论 2 318
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,964评论 0 213
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,703评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,863评论 2 254
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,333评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,658评论 3 263
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,374评论 3 244
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,195评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,988评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,167评论 2 285
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,970评论 2 279