Drawable animation可以加载Drawable资源实现帧动画。AnimationDrawable是实现Drawable animations的基本类。
AnimationDrawable代表一个动画,首先来说说补间动画,补间动画就是设置图片的首末状态,在指定的时间里面完成动画的变化。
定义补间动画的XML资源以<set>元素作为根元素,该元素内可以指定如下4个属性:
alpha:设置透明度的改变
scale:设置图片进行缩放的改变
translate:设置图片进行位移的变化。
route:设置图片进行旋转。
推荐用XML文件的方法实现Drawable动画,不推荐在代码中实现。定义图片的XML文件应该放在/res/anim路径下,设置补间动画的思路很简单:设置一张图片的开始状态,再设置图片的结束状态,最后设置动画的持续时间和变化。
首先定义一个用于播放的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();
在具体实现中,需要预先准备了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的使用进行封装
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; } }
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; } }
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; } }