// 自定义一个animationDrawable,监听动画结束 public abstract class GowildAnimationDrawable extends AnimationDrawable { Handler finishHandler; // 判断结束的Handler public GowildAnimationDrawable(AnimationDrawable animationDrawable) { // 这里得自己把每一帧加进去 for (int i = 0; i < animationDrawable.getNumberOfFrames(); i++) { this.addFrame(animationDrawable.getFrame(i), animationDrawable.getDuration(i)); } } @Override public void start() { super.start(); /** * 首先用父类的start() * 然后启动线程,来调用onAnimationEnd() * 单词调用 */ finishHandler = new Handler(); finishHandler.postDelayed( new Runnable() { public void run() { onAnimationEnd(); } }, getTotalDuration()); } /** * @Title: getTotalDuration * @Description: TODO(这个方法获得动画的持续时间(之后调用onAnimationEnd())) * @param @return 设定文件 * @return int 返回类型 * @throws */ public int getTotalDuration() { int durationTime = 0; for (int i = 0; i < this.getNumberOfFrames(); i++) { durationTime += this.getDuration(i); } return durationTime; } /** * @Title: onAnimationEnd * @Description: TODO(结束时调用的方法,一定要实现) * @param 设定文件 * @return void 返回类型 * @throws */ public abstract void onAnimationEnd(); }
// 初始化加载图片帧 public class PetGuideFrameAnimation { /** * @Fields frameTime : TODO(每一帧的播放时间) */ private static final int frameTime = 1; private Context mContext = null; private Matrix mmMatrix = null; private ImageView mImageView = null; /** * @Fields resource : TODO(素材,播放时间) */ private List<Map<Integer, Integer>> resource = new ArrayList<Map<Integer, Integer>>(); private int resourceIndex = 0; private int randomSeed = 2; private int currentTime = 0; private onFrameAnimationListener mFrameAnimationListener = null; private long startTime = 0L; /** * @Fields perListCount : TODO(每次加载帧动画数) */ private int perListCount = 1; /** * @Fields listIndex : TODO(帧动画组每组索引) */ private int listIndex = 0; /** * @Fields frameAniming : TODO(动画播放标志) */ private boolean frameAniming = true; /** * @Fields animationTime : TODO(帧动画持续时间) */ private int animationTime = 0; public PetGuideFrameAnimation(Context context, Matrix matrix, ImageView imageView) { mContext = context; mmMatrix = matrix; mImageView = imageView; initPetGuide1(); } public void setFrameAnimationListener(onFrameAnimationListener frameAnimationListener) { this.mFrameAnimationListener = frameAnimationListener; } @SuppressWarnings("deprecation") public AnimationDrawable getDrawableGuide() { AnimationDrawable frameAnim = new AnimationDrawable(); animationTime = 0; listIndex = 0; while (frameAniming && listIndex < perListCount) { if (resourceIndex < resource.size()) { int id = resource.get(resourceIndex).keySet().iterator().next(); Bitmap temp = BitmapFactory.decodeResource(mContext.getResources(), id); BitmapDrawable guide = new BitmapDrawable(Bitmap.createBitmap(temp, 0, 0, temp.getWidth(), temp.getHeight(), mmMatrix, true)); currentTime = resource.get(resourceIndex).values().iterator().next() * frameTime; animationTime += currentTime; frameAnim.addFrame(guide, currentTime); resourceIndex++; listIndex++; } else { frameAniming = false; } } frameAnim.setOneShot(true); return frameAnim; } /** * @Title: getFrameAniming * @Description: TODO(帧动画加载状态) * @param @return 设定文件 * @return boolean 返回类型 * @throws */ public boolean getFrameAniming() { return frameAniming; } @SuppressLint("UseSparseArrays") private void initPetGuide1() { Map<Integer, Integer> map = new HashMap<Integer, Integer>(); map.put(R.drawable.pet_guide_1_01, 12); resource.add(map); map = new HashMap<Integer, Integer>(); map.put(R.drawable.pet_guide_1_02, 2); resource.add(map); map = new HashMap<Integer, Integer>(); map.put(R.drawable.pet_guide_1_01, 2); resource.add(map); map = new HashMap<Integer, Integer>(); map.put(R.drawable.pet_guide_1_02, 2); resource.add(map); map = new HashMap<Integer, Integer>(); map.put(R.drawable.pet_guide_1_03, 16); resource.add(map); map = new HashMap<Integer, Integer>(); map.put(R.drawable.pet_guide_1_01, 2); resource.add(map); } }
// 调用开始动态加载 @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View root = inflater.inflate(R.layout.gowild_pet_guide_window, container, false); guideImage = (ImageView) root .findViewById(R.id.pet_guide_image); mPetGuideFrameAnimation = new PetGuideFrameAnimation(mPetMainActivity, null, guideImage); finishHandler.post(runable); return root; } Handler finishHandler = new Handler(); /** * @Fields runable : TODO(帧动画动态加载) */ Runnable runable = new Runnable() { @Override public void run() { if (mPetGuideFrameAnimation.getFrameAniming()) { mAnimationDrawable = mPetGuideFrameAnimation.getDrawableGuide(); gowildAnimationDrawable = new GowildAnimationDrawable(mAnimationDrawable) { @Override public void onAnimationEnd() { if (!mPetGuideFrameAnimation.getFrameAniming()) { mPetMainActivity.getFrameAnimationListener().frameAnimationFinish(); } } }; guideImage.setBackgroundDrawable(gowildAnimationDrawable); gowildAnimationDrawable.start(); finishHandler.postDelayed(runable, gowildAnimationDrawable==null?0:gowildAnimationDrawable.getTotalDuration()); } else { mPetMainActivity.getFrameAnimationListener().frameAnimationFinish(); } } };
主要思路:
通过循环递归将帧动画不断加载出来,避免一次性全部初始化。
存在问题:
大部分时间都耗费在了图片加载上,所以尽管上面有设置每一帧显示时间,但在从第一组到第二组过度的过程中,会出现严重的停机卡顿。如果改一次压缩一次,图片的压缩即使控制在40KB左右,每一次的延迟都会浪费在图片加载上,播放效果也不会非常流畅。