При запуске palm-inspector в Ubuntu 9.10 получил сообщение
palm-inspector: error while loading shared libraries: libicui18n.so.38: cannot open shared object file: No such file or directory
Причина - в репах karmic лежит libicu40 и видимо версия 3.8 стала не нужна. Решение - найти эту библиотеку где-нибудь (например в репе для 9.04)
пятница, 8 января 2010 г.
четверг, 15 октября 2009 г.
BlackBerry Layer UI Manager
Выбор layout manager (на русский это лучше не переводить) в библиотеке BlackBerry явно не блещет разнообразием. Абстрактный Manager и его наследники FlowFieldManager, HorizontalFieldManager, VerticalFieldManager - все, на что решились ребята из RIM (есть конечно еще DialogFieldManager, но это комбинация предыдущих...).
Может этого и хватит для страшненького простенького интерфейса, но для чего-то более приятного глазу явно мало. В официальной документации советуют создавать собственные имплементации, чем и приходится заниматься.
Наиболее востребованными оказались 2 метода расположения элементов:
- слоистый (каждый следующий добавленный элемент располагается сверху предыдущего, левый верхний угол - точка (0,0))
- абсолютный (элементы помещаются на родителя с указанием абсолютных координат (x,y) )
вот что из этого получилось. Метод №1:
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.Manager;
public class AXHSimpleLayeredFieldManager extends Manager {
public AXHSimpleLayeredFieldManager(long l) {
super(l);
}
protected void sublayout(int width, int height) {
//Display.getWidth() || Graphics.getScreenWidth()
int maxWidth = Config.SCREEN_WIDTH;
//Display.getHeight() || Graphics.getScreenHeight()
int maxHeight = Config.SCREEN_HEIGHT;//
for (int i = 0, n = getFieldCount(); i < n; i++) {
Field field = getField(i);
layoutChild(field, Display.getWidth(), Display.getHeight());
long fieldStyle = field.getStyle();
long fieldHalign = fieldStyle & Field.FIELD_HALIGN_MASK;
int fieldXOffset = 0;
if (fieldHalign == Field.FIELD_RIGHT) {
fieldXOffset = maxWidth - field.getWidth();
} else if (fieldHalign == Field.FIELD_HCENTER) {
fieldXOffset = (maxWidth - field.getWidth()) / 2;
}
int fieldYOffset = 0;
long fieldValign = fieldStyle & Field.FIELD_VALIGN_MASK;
if (fieldValign == Field.FIELD_BOTTOM) {
fieldYOffset = maxHeight - field.getHeight();
} else if (fieldValign == Field.FIELD_VCENTER) {
fieldYOffset = (maxHeight - field.getHeight()) / 2;
}
setPositionChild(field, fieldXOffset, fieldYOffset);
}
setExtent(maxWidth, maxHeight);
}
}
Blackberry GIF Rendering
Как известно, рендеринг анимированной гифки в BlackBerry отсутствует. Решение - костыль, рисующий кадр за кадром в отдельном потоке, представленный RIM в базе знаний .
Единственная проблема - алгоритм не поддерживает оптимизированные gif.
Небольшая модификация кода от RIM позволяет эту проблему решить
Рисуем кадр-за кадром на отдельном битмапе, который впоследствии отображается на экране.
Весь код:
Единственная проблема - алгоритм не поддерживает оптимизированные 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;
}
}
}
}
}
}
Подписаться на:
Комментарии (Atom)