zoukankan      html  css  js  c++  java
  • 详解Android动画之Frame Animation(转)

    在开始实例讲解之前,先引用官方文档中的一段话:

    Frame动画是一系列图片按照一定的顺序展示的过程,和放电影的机制很相似,我们称为逐帧动画。Frame动画可以被定义在XML文件中,也可以完全编码实现。

    如果被定义在XML文件中,我们可以放置在/res下的anim或drawable目录中(/res/[anim | drawable]/filename.xml),文件名可以作为资源ID在代码中引用;如果由完全由编码实现,我们需要使用到AnimationDrawable对象。

    如果是将动画定义在XML文件中的话,语法如下:

    <?xml version="1.0" encoding="utf-8"?>
    <animation-list xmlns:android="http://schemas.android.com/apk/res/android"
        android:oneshot=["true" | "false"] >
        <item
            android:drawable="@[package:]drawable/drawable_resource_name"
            android:duration="integer" />
    </animation-list>

    需要注意的是:

    <animation-list>元素是必须的,并且必须要作为根元素,可以包含一或多个<item>元素;android:onshot如果定义为true的话,此动画只会执行一次,如果为false则一直循环。

    <item>元素代表一帧动画,android:drawable指定此帧动画所对应的图片资源,android:druation代表此帧持续的时间,整数,单位为毫秒。

    文档接下来的示例我就不在解说了,因为接下来我们也要结合自己的实例演示一下这个过程。

    我们新建一个名为anim的工程,将四张连续的图片分别命名为f1.png,f2.png,f3.png,f4.png,放于drawable目录,然后新建一个frame.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="@drawable/f1" android:duration="300" />
        <item android:drawable="@drawable/f2" android:duration="300" />
        <item android:drawable="@drawable/f3" android:duration="300" />
        <item android:drawable="@drawable/f4" android:duration="300" />
    </animation-list>

    我们可以将frame.xml文件放置于drawable或anim目录,官方文档上是放到了drawable中了,大家可以根据喜好来放置,放在这两个目录都是可以运行的。

    然后介绍一下布局文件res/layout/frame.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
      xmlns:android="http://schemas.android.com/apk/res/android"
      android:orientation="vertical"
      android:layout_width="fill_parent"
      android:layout_height="fill_parent">
      <ImageView
          android:id="@+id/frame_image"
          android:layout_width="fill_parent"
          android:layout_height="fill_parent"
          android:layout_weight="1"/>
      <Button
          android:layout_width="fill_parent"
          android:layout_height="wrap_content"
          android:text="stopFrame"
          android:onClick="stopFrame"/>
      <Button
          android:layout_width="fill_parent"
          android:layout_height="wrap_content"
          android:text="runFrame"
          android:onClick="runFrame"/>
    </LinearLayout>

    我们定义了一个ImageView作为动画的载体,然后定义了两个按钮,分别是停止和启动动画。

    接下来介绍一下如何通过加载动画定义文件来实现动画的效果。我们首先会这样写:

    package com.scott.anim;
    
    import android.app.Activity;
    import android.graphics.drawable.AnimationDrawable;
    import android.graphics.drawable.Drawable;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.ImageView;
    
    public class FrameActivity extends Activity {
        
        private ImageView image;
        
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.frame);
            image = (ImageView) findViewById(R.id.frame_image);
            
            image.setBackgroundResource(R.anim.frame);
            AnimationDrawable anim = (AnimationDrawable) image.getBackground();
            anim.start();
        }
    }

    看似十分完美,跟官方文档上写的一样,然而当我们运行这个程序时会发现,它只停留在第一帧,并没有出现我们期望的动画,也许你会失望的说一句:“Why?”,然后你把相应的代码放在一个按钮的点击事件中,动画就顺利执行了,再移回到onCreate中,还是没效果,这个时候估计你会气急败坏的吼一句:“What the fuck!”。但是,什么原因呢?如何解决呢?

    出现这种现象是因为当我们在onCreate中调用AnimationDrawable的start方法时,窗口Window对象还没有完全初始化,AnimationDrawable不能完全追加到窗口Window对象中,那么该怎么办呢?我们需要把这段代码放在onWindowFocusChanged方法中,当Activity展示给用户时,onWindowFocusChanged方法就会被调用,我们正是在这个时候实现我们的动画效果。当然,onWindowFocusChanged是在onCreate之后被调用的,如图:

    然后我们需要重写一下代码:

    package com.scott.anim;
    
    import android.app.Activity;
    import android.graphics.drawable.AnimationDrawable;
    import android.graphics.drawable.Drawable;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.ImageView;
    
    public class FrameActivity extends Activity {
        
        private ImageView image;
        
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.frame);
            image = (ImageView) findViewById(R.id.frame_image);
        }
        
        @Override
        public void onWindowFocusChanged(boolean hasFocus) {
            super.onWindowFocusChanged(hasFocus);
            image.setBackgroundResource(R.anim.frame);
            AnimationDrawable anim = (AnimationDrawable) image.getBackground();
            anim.start();
        }
    }

    运行一下,动画就可以正常显示了。

    如果在有些场合,我们需要用纯代码方式实现一个动画,我们可以这样写:

    AnimationDrawable anim = new AnimationDrawable();
    for (int i = 1; i <= 4; i++) {
        int id = getResources().getIdentifier("f" + i, "drawable", getPackageName());
        Drawable drawable = getResources().getDrawable(id);
        anim.addFrame(drawable, 300);
    }
    anim.setOneShot(false);
    image.setBackgroundDrawable(anim);
    anim.start();

    完整的FrameActivity.java代码如下:

    package com.scott.anim;
    
    import android.app.Activity;
    import android.graphics.drawable.AnimationDrawable;
    import android.graphics.drawable.Drawable;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.ImageView;
    
    public class FrameActivity extends Activity {
        
        private ImageView image;
        
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.frame);
            image = (ImageView) findViewById(R.id.frame_image);
        }
        
        @Override
        public void onWindowFocusChanged(boolean hasFocus) {
            super.onWindowFocusChanged(hasFocus);
            image.setBackgroundResource(R.anim.frame);    //将动画资源文件设置为ImageView的背景
            AnimationDrawable anim = (AnimationDrawable) image.getBackground();    //获取ImageView背景,此时已被编译成AnimationDrawable
            anim.start();    //开始动画
        }
        
        public void stopFrame(View view) {
            AnimationDrawable anim = (AnimationDrawable) image.getBackground();
            if (anim.isRunning()) {    //如果正在运行,就停止
                anim.stop();
            }
        }
        
        public void runFrame(View view) {
            //完全编码实现的动画效果
            AnimationDrawable anim = new AnimationDrawable();
            for (int i = 1; i <= 4; i++) {
                //根据资源名称和目录获取R.java中对应的资源ID
                int id = getResources().getIdentifier("f" + i, "drawable", getPackageName());
                //根据资源ID获取到Drawable对象
                Drawable drawable = getResources().getDrawable(id);
                //将此帧添加到AnimationDrawable中
                anim.addFrame(drawable, 300);
            }
            anim.setOneShot(false);    //设置为loop
            image.setBackgroundDrawable(anim);    //将动画设置为ImageView背景
            anim.start();    //开始动画
        }
    }

    转载地址:http://blog.csdn.net/liuhe688/article/details/6657776

  • 相关阅读:
    LeetCode 623. Add One Row to Tree
    LeetCode 894. All Possible Full Binary Trees
    LeetCode 988. Smallest String Starting From Leaf
    LeetCode 979. Distribute Coins in Binary Tree
    LeetCode 814. Binary Tree Pruning
    LeetCode 951. Flip Equivalent Binary Trees
    LeetCode 426. Convert Binary Search Tree to Sorted Doubly Linked List
    LeetCode 889. Construct Binary Tree from Preorder and Postorder Traversal
    LeetCode 687. Longest Univalue Path
    LeetCode 428. Serialize and Deserialize N-ary Tree
  • 原文地址:https://www.cnblogs.com/hubing/p/4653777.html
Copyright © 2011-2022 走看看