1. import java.io.IOException;
  2. import android.content.Context;
  3. import android.graphics.Bitmap;
  4. import android.graphics.Bitmap.Config;
  5. import android.graphics.BitmapFactory;
  6. import android.graphics.Canvas;
  7. import android.graphics.ColorFilter;
  8. import android.graphics.Paint;
  9. import android.graphics.PixelFormat;
  10. import android.graphics.Rect;
  11. import android.graphics.drawable.Drawable;
  12. import android.os.SystemClock;
  13. /**
  14. * AssetAnimationDrawable
  15. *
  16. * @author Alexei Garbuzenko
  17. *
  18. */
  19. public class AssetAnimationDrawable extends Drawable implements Runnable {
  20. private final Bitmap m_bitmap;
  21. private final Paint m_bitmapPaint;
  22. private final int m_width;
  23. private final int m_height;
  24. private final int m_duration;
  25. private final int m_frames;
  26. private long m_lastUpdate;
  27. private int m_frame;
  28. private Rect m_frameRect;
  29. public AssetAnimationDrawable(Context context, String asset, int frames,
  30. int fps) throws IOException {
  31. BitmapFactory.Options options = new BitmapFactory.Options();
  32. options.inPreferredConfig = Config.RGB_565; // A.G.: use 16-bit mode
  33. // without alpha for
  34. // animations
  35. m_bitmap = BitmapFactory.decodeStream(context.getResources()
  36. .getAssets().open(asset), null, options);
  37. m_width = m_bitmap.getWidth() / frames;
  38. m_height = m_bitmap.getHeight();
  39. m_duration = 1000 / fps;
  40. m_frames = frames; // A.G.: note the little gap cause of integer
  41. // division.
  42. // i.e. duration would be 33 for 30fps, meaning
  43. // 990ms for 30 frames.
  44. m_bitmapPaint = new Paint();
  45. m_bitmapPaint.setFilterBitmap(true);
  46. m_frame = 0;
  47. m_frameRect = new Rect(0, 0, m_width, m_height); // first frame
  48. m_lastUpdate = SystemClock.uptimeMillis();
  49. }
  50. @Override
  51. protected void finalize() throws Throwable {
  52. super.finalize();
  53. recycle();
  54. }
  55. @Override
  56. public void draw(Canvas canvas) {
  57. canvas.drawBitmap(m_bitmap, m_frameRect, copyBounds(), m_bitmapPaint);
  58. }
  59. @Override
  60. public int getOpacity() {
  61. return PixelFormat.OPAQUE;
  62. }
  63. @Override
  64. public void setAlpha(int a) {
  65. m_bitmapPaint.setAlpha(a);
  66. }
  67. @Override
  68. public void setColorFilter(ColorFilter filter) {
  69. m_bitmapPaint.setColorFilter(filter);
  70. }
  71. @Override
  72. public int getIntrinsicWidth() {
  73. return m_width;
  74. }
  75. @Override
  76. public int getIntrinsicHeight() {
  77. return m_height;
  78. }
  79. @Override
  80. public void run() {
  81. long tick = SystemClock.uptimeMillis();
  82. if (tick - m_lastUpdate >= m_duration) {
  83. m_frame = (int) (m_frame + (tick - m_lastUpdate) / m_duration)
  84. % m_frames;
  85. m_lastUpdate = tick; // TODO: time shift for incomplete frames
  86. m_frameRect = new Rect(m_frame * m_width, 0, (m_frame + 1)
  87. * m_width, m_height);
  88. invalidateSelf();
  89. }
  90. scheduleSelf(this, tick + m_duration);
  91. }
  92. public void start() {
  93. run();
  94. }
  95. public void stop() {
  96. unscheduleSelf(this);
  97. }
  98. public void recycle() {
  99. stop();
  100. if (m_bitmap != null && !m_bitmap.isRecycled())
  101. m_bitmap.recycle();
  102. }
  103. }

AnimationDrawable class that takes sprite sheet and displays it with given fps