Единственная проблема - алгоритм не поддерживает оптимизированные gif.
Небольшая модификация кода от RIM позволяет эту проблему решить
Рисуем кадр-за кадром на отдельном битмапе, который впоследствии отображается на экране.
...
private Bitmap background;
...
protected void paint(Graphics graphics) {
//Optimized gif support: draw frame-by-frame on the background layer
Graphics g = new Graphics(background);
g.drawImage(_image.getFrameLeft(_currentFrame), _image
.getFrameTop(_currentFrame), _image
.getFrameWidth(_currentFrame), _image
.getFrameHeight(_currentFrame), _image, _currentFrame, 0, 0);
graphics.drawBitmap(0, 0, background.getWidth(),
background.getHeight(), background, 0, 0);
}
Весь код:
import net.rim.device.api.system.Bitmap;
import net.rim.device.api.system.GIFEncodedImage;
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.component.BitmapField;
//A field that displays an animated GIF.
public class AnimatedGIFField extends BitmapField {
private GIFEncodedImage _image; // The image to draw.
private int _currentFrame; // The current frame in
// the animation sequence.
private int _width; // The width of the image
// (background frame).
private int _height; // The height of the image
// (background frame).
private AnimatorThread _animatorThread;
private Bitmap background;
public AnimatedGIFField(GIFEncodedImage image) {
this(image, 0);
}
public AnimatedGIFField(GIFEncodedImage image, long style) {
// Call super to setup the field with the specified style.
// The image is passed in as well for the field to
// configure its required size.
super(image.getBitmap(), style);
// Store the image and it's dimensions.
_image = image;
_width = image.getWidth();
_height = image.getHeight();
background = image.getBitmap();
// Start the animation thread.
_animatorThread = new AnimatorThread(this);
_animatorThread.start();
}
protected void paint(Graphics graphics) {
//Optimized gif support: draw frame-by-frame on the background layer
Graphics g = new Graphics(background);
g.drawImage(_image.getFrameLeft(_currentFrame), _image
.getFrameTop(_currentFrame), _image
.getFrameWidth(_currentFrame), _image
.getFrameHeight(_currentFrame), _image, _currentFrame, 0, 0);
graphics.drawBitmap(0, 0, background.getWidth(),
background.getHeight(), background, 0, 0);
}
// Stop the animation thread when the screen the field is on is
// popped off of the display stack.
protected void onUndisplay() {
_animatorThread.stop();
super.onUndisplay();
}
// A thread to handle the animation.
private class AnimatorThread extends Thread {
private AnimatedGIFField _theField;
private boolean _keepGoing = true;
private int _totalFrames; // The total number of
// frames in the image.
private int _loopCount; // The number of times the
// animation has looped (completed).
private int _totalLoops; // The number of times the animation should
// loop (set in the image).
public AnimatorThread(AnimatedGIFField theField) {
_theField = theField;
_totalFrames = _image.getFrameCount();
_totalLoops = _image.getIterations();
}
public synchronized void stop() {
_keepGoing = false;
}
public void run() {
while (_keepGoing) {
// Invalidate the field so that it is redrawn.
UiApplication.getUiApplication().invokeAndWait(new Runnable() {
public void run() {
_theField.invalidate();
}
});
try {
// Sleep for the current frame delay before
// the next frame is drawn.
sleep(_image.getFrameDelay(_currentFrame) * 10);
} catch (InterruptedException iex) {
} // Couldn't sleep.
// Increment the frame.
++_currentFrame;
if (_currentFrame == _totalFrames) {
// Reset back to frame 0 if we have reached the end.
_currentFrame = 0;
++_loopCount;
// Check if the animation should continue.
if (_loopCount == _totalLoops) {
_keepGoing = false;
}
}
}
}
}
}
Комментариев нет:
Отправить комментарий