AnimationDrawable的使用
Drawable animation可以加载Drawable资源实现帧动画。AnimationDrawable是实现Drawable animations的基本类。
一、什么是AnimationDrawable
AnimationDrawable代表一个动画,首先来说说补间动画,补间动画就是设置图片的首末状态,在指定的时间里面完成动画的变化。
定义补间动画的XML资源以<set>元素作为根元素,该元素内可以指定如下4个属性:
alpha:设置透明度的改变
scale:设置图片进行缩放的改变
translate:设置图片进行位移的变化。
route:设置图片进行旋转。
二、如何使用AnimationDrawable
推荐用XML文件的方法实现Drawable动画,不推荐在代码中实现。定义图片的XML文件应该放在/res/anim路径下,设置补间动画的思路很简单:设置一张图片的开始状态,再设置图片的结束状态,最后设置动画的持续时间和变化。
三、AnimationDrawable的xml定义
首先定义一个用于播放的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/on_001"
android:duration="100"/>
<item
android:drawable="@drawable/on_002"
android:duration="100"/>
<item
android:drawable="@drawable/on_003"
android:duration="100"/>
<item
android:drawable="@drawable/on_004"
android:duration="100"/>
<item
android:drawable="@drawable/on_005"
android:duration="100"/>
<item
android:drawable="@drawable/on_006"
android:duration="100"/>
</animation-list>
定义完后使用代码调用它
AnimationDrawable ad = (AnimationDrawable) getResources().getDrawable(
R.drawable.bootanimation);
mView.setBackgroundDrawable(ad);
ad.start();
四、AnimationDrawable的代码实现
在具体实现中,需要预先准备了15张单帧动画图像,分别命名为image1到image15,并存放在工程的res/drawable目录下。然后可以通过如下方法将每一帧的图像加载到AnimationDrawable对象中。
mAnimationDrawable = new AnimationDrawable();
for (int i = 1; i <= 15; i++) {
int resourcesId = getResources().getIdentifier("image"+i, "drawable", mContext.getPackageName());
mDrawable = getResources().getDrawable(resourcesId);
mAnimationDrawable.addFrame(mDrawable, 500);
}
五、AnimationDrawable使用的封装
在项目中,个别项目需要多次使用到AnimationDrawable,这时候可以对AnimationDrawable的使用进行封装
1、对AnimationDrawable属性的封装
package com.lyh.common.anim;
/**
*
* 类名:AnimationAttribute
*
* @author lyh
*/
public class AnimationAttribute {
private String drawable; // 图片资源名称
private String oneShot; // 是否重复播放的参数
private String duration; // 播放间隔时间的参数
public String getDrawable() {
return drawable;
}
public void setDrawable(String drawable) {
this.drawable = drawable;
}
public String getOneShot() {
return oneShot;
}
public void setOneShot(String oneShot) {
this.oneShot = oneShot;
}
public String getDuration() {
return duration;
}
public void setDuration(String duration) {
this.duration = duration;
}
}
2、xml解析类XMLContentHandler
package com.lyh.common.anim;
import java.util.ArrayList;
import java.util.List;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class XMLContentHandler extends DefaultHandler {
private List<AnimationAttribute> persons = null;
private AnimationAttribute currentPerson;
private String tagName = null;// 当前解析的元素标签
public List<AnimationAttribute> getPersons() {
return persons;
}
/**
* 接收文档的开始的通知。
*/
@Override
public void startDocument() throws SAXException {
persons = new ArrayList<AnimationAttribute>();
}
/**
* 接收字符数据的通知。
**/
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
if (tagName != null) {
// String data = new String(ch, start, length);
if (tagName.equals("name")) {
// this.currentPerson.setName(data);
} else if (tagName.equals("age")) {
// this.currentPerson.setAge(Short.parseShort(data));
}
}
}
/**
* 接收元素开始的通知。 参数意义如下:
*
* @param namespaceURI
* :元素的命名空间
* @param localName
* :元素的本地名称(不带前缀)
* @param qName
* :元素的限定名(带前缀)
* @param atts
* :元素的属性集合
*/
@Override
public void startElement(String namespaceURI, String localName,
String qName, Attributes atts) throws SAXException {
currentPerson = new AnimationAttribute();
if (localName.equals("item")) {
currentPerson.setDrawable(atts.getValue("android:drawable"));
currentPerson.setDuration(atts.getValue("android:duration"));
} else if (localName.equals("animation-list")) {
currentPerson.setOneShot(atts.getValue("android:oneshot"));
}
this.tagName = localName;
}
/**
* 接收文档的结尾的通知。 参数意义如下:
*
* @param uri
* :元素的命名空间
* @param localName
* :元素的本地名称(不带前缀)
* @param name
* :元素的限定名(带前缀)
*/
@Override
public void endElement(String uri, String localName, String name)
throws SAXException {
if (localName.equals("item")) {
persons.add(currentPerson);
currentPerson = null;
}
this.tagName = null;
}
}
3、动画播放类
package com.lyh.common.anim;
import java.io.FileInputStream;
import java.io.InputStream;
import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import android.content.Context;
import android.graphics.drawable.AnimationDrawable;
import android.graphics.drawable.Drawable;
import android.widget.ImageView;
/**
*
* 类名:PlayAnimation
*
* @author lyh
*
*/
public class PlayAnimation extends AnimationDrawable {
private Context context;
private final String FOLDERNAME = "drawable";
private Map<String, Drawable> resMap;
public PlayAnimation(Context context) {
WeakReference<Context> mCt = new WeakReference<Context>(context);
this.context = mCt.get();
if (resMap == null) {
resMap = new HashMap<String, Drawable>();
}
}
/**
*
* 函数名称 : startAnimationResourceFileName 功能描述 : 播放动画,用文件名加载动画资源的启动方式
* 参数及返回值说明:
*
* @param imgAnimation
* 承载动画播放的控件
* @param fileNameList
* 文件名的集合
* @param duration
* 动画播放间隔时间
* @param oneShot
* 重复播放动画,ture不重复,false重复
*
*/
public void startAnimationResourceFileName(ImageView imgAnimation,
List<String> fileNameList, int duration, boolean oneShot) {
addResourceFileName(fileNameList, duration, oneShot);
imgAnimation.setBackgroundDrawable(this);
this.start();
}
/**
*
* 函数名称 : startAnimationResourceId 功能描述 : 播放动画,用资源id加载动画资源的启动方式
*
* 参数及返回值说明:
*
* @param imgAnimation
* 承载动画播放的控件
* @param resourceList
* 播放资源id集合
* @param duration
* 动画播放间隔时间
* @param oneShot
* 重复播放动画,ture不重复,false重复
*
*/
public void startAnimationResourceId(ImageView imgAnimation,
List<Integer> resourceList, int duration, boolean oneShot) {
addResourceId(resourceList, duration, oneShot);
imgAnimation.setBackgroundDrawable(this);
this.start();
}
/**
*
* 函数名称 : startAssetsResouurce 功能描述 : 播放动画,用asstes文件夹下解析xml文件,加载动画资源的启动方式
* 参数及返回值说明:
*
* @param imgAnimation
* 承载动画播放的控件
* @param fileName
* assets的相对路径
*
* 修改记录: 日期 :2013-8-16 下午2:13:59 修改人: 描述 :
*
*/
public void startAssetsResource(ImageView imgAnimation, String fileName) {
addAssetsResource(fileName);
imgAnimation.setBackgroundDrawable(this);
this.start();
}
/**
* 从sd卡读取资源,播放动画
* @param imgAnimation
* @param fileName
*/
public void startSdcardResource(ImageView imgAnimation, String fileName) {
addSdcardResource(fileName);
imgAnimation.setBackgroundDrawable(this);
this.start();
}
/**
*
* 函数名称 : addResourceFileName 功能描述 : 用文件名批量添加动画资源 参数及返回值说明:
*
* @param fileNameList
* 文件名的集合
* @param duration
* 动画播放间隔时间
* @param oneShot
* 重复播放动画,ture不重复,false重复
*
*/
public void addResourceFileName(List<String> fileNameList, int duration,
boolean oneShot) {
for (int i = 0; i < fileNameList.size(); i++) {
int id = context.getResources().getIdentifier(
context.getPackageName() + ":" + FOLDERNAME + "/"
+ fileNameList.get(i), null, null);
this.addFrame(context.getResources().getDrawable(id), duration);
}
this.setOneShot(false);
}
/**
*
* 函数名称 : addResourceId 功能描述 : 用文件名单个添加动画资源 参数及返回值说明:
*
* @param fileName
* 文件名
* @param duration
* 动画播放间隔时间
* @param oneShot
* 重复播放动画,ture不重复,false重复
*
*/
public void addResourceFileName(String fileName, int duration,
boolean oneShot) {
int id = context.getResources().getIdentifier(
context.getPackageName() + ":" + FOLDERNAME + "/" + fileName,
null, null);
this.addFrame(context.getResources().getDrawable(id), duration);
this.setOneShot(false);
}
/**
*
* 函数名称 : addResourceId 功能描述 : 用资源id添加动画资源 参数及返回值说明:
*
* @param resourceList
* 资源集合
* @param duration
* 动画播放间隔时间
* @param oneShot
* 重复播放动画,ture不重复,false重复
*/
public void addResourceId(List<Integer> resourceList, int duration,
boolean oneShot) {
for (int i = 0; i < resourceList.size(); i++) {
this.addFrame(
context.getResources().getDrawable(resourceList.get(i)),
duration);
}
this.setOneShot(oneShot);
}
/**
*
* 函数名称 : addAssetsResource 功能描述 : 用asstes文件下xml文件添加动画资源 参数及返回值说明:
*
* @param folderName
* 文件在asstes的相对路径
*/
public void addAssetsResource(String fileName) {
try {
List<AnimationAttribute> list = anaysisXml(true, fileName);
if (resMap.get(fileName + 0) == null) {
String path = fileName.substring(0, fileName.lastIndexOf("/"))
+ "/";
for (int i = 0; i < list.size(); i++) {
InputStream inputStream2 = context.getResources()
.getAssets().open(path + list.get(i).getDrawable());
Drawable drawable = Drawable.createFromStream(inputStream2,
null);
this.addFrame(drawable,
Integer.valueOf(list.get(i).getDuration()));
this.setOneShot(Boolean.valueOf(list.get(i).getOneShot()));
resMap.put(fileName + i, drawable);
}
} else {
for (int i = 0; i < list.size(); i++) {
this.addFrame(resMap.get(fileName + i),
Integer.valueOf(list.get(i).getDuration()));
this.setOneShot(Boolean.valueOf(list.get(i).getOneShot()));
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 读取sd卡图片资源
*
* @param fileName
*/
public void addSdcardResource(String fileName) {
List<AnimationAttribute> list = anaysisXml(false, fileName);
String path = fileName.substring(0, fileName.lastIndexOf("/")) + "/";
for (int i = 0; i < list.size(); i++) {
Drawable drawable = Drawable.createFromPath(path
+ list.get(i).getDrawable());
this.addFrame(drawable, Integer.valueOf(list.get(i).getDuration()));
this.setOneShot(Boolean.valueOf(list.get(i).getOneShot()));
}
}
/**
* 解析assets目录下的xml动画文件
*
* @param fileName
* @return
*/
public List<AnimationAttribute> anaysisXml(boolean assets, String fileName) {
try {
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser saxParser;
saxParser = spf.newSAXParser();
XMLContentHandler handler = new XMLContentHandler();
InputStream inputStream = null;
if (assets) {
inputStream = this.context.getResources().getAssets()
.open(fileName);
} else {
inputStream = new FileInputStream(fileName);
}
saxParser.parse(inputStream, handler);
inputStream.close();
List<AnimationAttribute> list = handler.getPersons();
return list;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}