Cyclically alters bitmap images
I
have a Canvas and I want the bitmap image to change every 50 milliseconds.
Basically what I want to do is like an animated GIF.
As you can see, there are 4 images and I want it to change the image every 50 milliseconds.
The code below doesn’t work, I don’t know why.
protected void onDraw(final Canvas canvas) {
res = getResources();
image = BitmapFactory.decodeResource(res, R.drawable.image_1);
canvas.drawBitmap(image, 0, 0, paint);
new Thread(new Runnable() {
@Override
public void run() {
while (! Thread.interrupted())
try {
Thread.sleep(50);
System.out.println("OK2");
time++;
((Activity) context).runOnUiThread(new Runnable() {
@Override
public void run() {
if (time == 1) {
image = BitmapFactory.decodeResource(res,
R.drawable.image_1);
canvas.drawBitmap(image, 0, 0, paint);
invalidate();
}
if (time == 2) {
image = BitmapFactory.decodeResource(res,
R.drawable.image_2);
canvas.drawBitmap(image, 0, 0, paint);
invalidate();
}
if (time == 3) {
image = BitmapFactory.decodeResource(res,
R.drawable.image_3);
canvas.drawBitmap(image, 0, 0, paint);
invalidate();
}
if (time >= 4) {
time = 0;
image = BitmapFactory.decodeResource(res,
R.drawable.image_4);
canvas.drawBitmap(image, 0, 0, paint);
invalidate();
}
}
});
} catch (InterruptedException e) {
}
}
}).start();
super.onDraw(canvas);
}
Thanks in advance.
Solution
There are a couple of questions:
You are decoding the resource every time. decodeResource
may not be fast enough to load an image within 50 milliseconds. It is faster to decode the frames once and store them in an array. For example:
Bitmap images[4];
void loadFrames()
{
res = getResources();
images[0] = BitmapFactory.decodeResource(res, R.drawable.image_1);
images[1] = BitmapFactory.decodeResource(res, R.drawable.image_2);
images[2] = BitmapFactory.decodeResource(res, R.drawable.image_3);
images[3] = BitmapFactory.decodeResource(res, R.drawable.image_4);
}
Each call to onDraw()
starts a new thread, which means that hundreds of threads will be created. Instead, you should create the thread only once. Inside the thread, increment the counter and set image
to the correct frame, then call invalidate:
Thread.sleep(50);
time = (time + 1) % 4;
image = images[time];
((Activity) context).runOnUiThread(new Runnable() {
@Override
public void run() {
invalidate();
}
};
Then in onDraw(), draw on
the Canvas with the current image:
canvas.drawBitmap(image, 0, 0, paint);