Related
I am trying to achieve a flat look for blackberry controls, namely objectchoicefield and buttonfield.
The following code does not seem to do the trick. (The width setting does work, but not the border setting.)
public static ObjectChoiceField GetDropdownList(String label, String[] data)
{
ObjectChoiceField ocf = new ObjectChoiceField(null, data, 0, Field.FIELD_LEFT);
ocf.setBorder(BorderFactory.createSimpleBorder(new XYEdges(0,0,0,0)));
ocf.setMinimalWidth(Display.getWidth()-61);
return ocf;
}
I get the same appearance with or without the setBorder statement. Basically I do not want any 3D look or shadow or shine or rounded corners.
Thanks
This might not do everything you want, but you can try looking at this custom ObjectChoiceField that I built for OS 4.6 and lower devices. I wanted to add a glossy, 3D look, but you could change the custom paint() code I used to make a simpler, flatter look.
Taking my example, changing the rounded corner radius to 1, and removing the call to super.paint(g) gives something like this:
public class CustomChoiceField extends ObjectChoiceField {
private int _bgWidth = 0;
private int _bgHeight = 0;
private int _numChoices = 0;
private boolean _hasFocus = false;
private static final int HIGHLIGHT_COLOR = 0xFF185AB5; // blue-ish
private static final int RADIUS = 1; // rounded corner radius in pixels
private static final int DFLT_PADDING = 20;
public CustomChoiceField(Object[] choices, int initialIndex) {
super("", choices, initialIndex);
_numChoices = choices.length;
}
public int getPreferredHeight() {
return _bgHeight;
}
public int getPreferredWidth() {
return _bgWidth;
}
protected void layout(int width, int height) {
if (_bgWidth == 0 || _bgHeight == 0) {
if (height <= Display.getHeight()) {
// probably using custom Manager to specify size
_bgWidth = width;
_bgHeight = height;
} else {
// use default sizing
_bgHeight = DFLT_PADDING + getHeightOfChoices();
for (int i = 0; i < _numChoices; i++) {
_bgWidth = Math.max(_bgWidth, DFLT_PADDING + getWidthOfChoice(i));
}
}
}
super.layout(_bgWidth, _bgHeight);
super.setExtent(_bgWidth, _bgHeight);
}
protected void applyTheme(Graphics arg0, boolean arg1) {
// do nothing
}
protected void drawFocus(Graphics g, boolean on) {
// do nothing .. handled manually in paint(g)
}
protected void onFocus(int direction) {
_hasFocus = true;
super.onFocus(direction);
invalidate();
}
protected void onUnfocus() {
_hasFocus = false;
super.onUnfocus();
invalidate(); // required to clear focus
}
protected void paint(Graphics g) {
int oldColor = g.getColor();
// field color depends on whether we have focus or not
int bgColor = (_hasFocus) ? HIGHLIGHT_COLOR : Color.BLACK;
// when the field has focus, we make it a little less transparent
int alpha = (_hasFocus) ? 0xDD : 0xBB;
g.setColor(bgColor);
g.setGlobalAlpha(alpha);
g.fillRoundRect(0, 0, _bgWidth, _bgHeight, RADIUS, RADIUS);
// draw a plain white line as a border
g.setColor(Color.WHITE);
g.setGlobalAlpha(0xFF);
g.drawRoundRect(0, 0, _bgWidth, _bgHeight, RADIUS, RADIUS);
// draw the currently selected choice's text (also in white)
String text = (String)getChoice(getSelectedIndex());
int y = (_bgHeight - getFont().getHeight()) / 2;
g.drawText(text, 0, y, DrawStyle.HCENTER | DrawStyle.TOP, _bgWidth);
g.setColor(oldColor);
}
}
And you use the CustomChoiceField like this:
private ObjectChoiceField[] ocf = new ObjectChoiceField[3];
public ObjectChoiceScreen() {
super(MainScreen.VERTICAL_SCROLL | MainScreen.VERTICAL_SCROLLBAR);
Object[] choices1 = new Object[] { "one", "two", "three" };
ocf[0] = new CustomChoiceField(choices1, 0);
Object[] choices2 = new Object[] { "ichi", "ni", "san" };
ocf[1] = new CustomChoiceField(choices2, 0);
Object[] choices3 = new Object[] { "uno", "dos", "tres" };
ocf[2] = new CustomChoiceField(choices3, 0);
for (int i = 0; i < ocf.length; i++) {
ocf[i].setMargin(new XYEdges(10, 10, 10, 10));
}
getMainManager().addAll(ocf);
This isn't production code, so you'll need to test it yourself. For example, it doesn't handle changing the choices with setChoices(). But, it's a start, and will get you something like this:
You'll notice the difference in color between the first two object choice fields, and the bottom one, which is focused.
My code has the same popup for selecting choices as the normal ObjectChoiceField. So, you still may get rounded corners that way. In my case, I didn't need to change that look and feel, so I'm not sure how you might change that, too.
I want to implement something like this in my application:
That is, each image contains one heart icon. I want to handle the click event on heart click and for that I have the following code
list.setEmptyString("No Image Available", DrawStyle.HCENTER);
list.setRowHeight(Display.getHeight() - 100);
list.setSize(data.size());
if (listVManager != null && listVManager.getFieldCount() > 0) {
listVManager.deleteAll();
}
list.setCallback(new ListFieldCallback() {
public void drawListRow(ListField list, Graphics graphics,
int index, int y, int w) {
int yPos = y + list.getRowHeight() - 1;
graphics.setColor(0x434343);
graphics.fillRect(0, y, w, list.getRowHeight());
if (logoThumbnailImage != null
&& logoThumbnailImage.length > index
&& logoThumbnailImage[index] != null) {
EncodedImage img = logoThumbnailImage[index];
graphics.drawImage(0, y + 10, Display.getWidth(),
Display.getHeight() - 100, img, 0, 0, 0);
graphics.drawText("Hello", 10,
Display.getHeight() - 150);
graphics.drawImage(Display.getWidth() - 70,
Display.getHeight() - 150 + 300,
heart.getWidth(), heart.getHeight(), heart,
0, 0, 0);
} else {
graphics.drawImage(
15,
y + 10,
Display.getWidth(),
Display.getHeight() - 100,
sizeImage(iconImage, Display.getWidth(),
Display.getHeight() - 100), 0, 0, 0);
}
graphics.drawText("Hello", 10,
Display.getHeight() - 150);
graphics.drawLine(0, yPos, w, yPos);
}
public Object get(ListField listField, int index) {
return null;
}
public int getPreferredWidth(ListField listField) {
return Display.getWidth();
}
public int indexOfList(ListField listField, String prefix,
int start) {
return 0;
}
});
listVManager.add(list);
loadImages = new LoadImages(80, 80);
loadImages.start();
}
});
here load image is thread that load images in background and store them in logoThumbnailImage array and invalidate list from there when the it loads the image.
The Load image thread class:
private class LoadImages extends Thread {
int widthL;
int heightL;
LoadImages(int width, int height) {
this.widthL = width;
this.heightL = height;
}
public void run() {
logoThumbnailImage=new EncodedImage[numberOfItem];
if (object != null) {
for (int i = 0; i < numberOfItem; i++) {
try {
String text=object[i].getJSONArray("UrlArray").getString(0).toString();
EncodedImage encodedImg = JPEGEncodedImage.encode(connectServerForImage(text), quality); //connectserverForImage load Images from server
logoThumbnailImage[i] = sizeImage(encodedImg, Display.getWidth(), Display.getHeight()-100);
list.invalidate();
} catch (Exception e)
{
e.printStackTrace();
}
}
} else {
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
Dialog.alert("No Data Found");
}
});
}
}
}
The application runs smoothly but I got the following output:
I have the following problem
1. The heart and description is displayed on only one list row. Can any one tell me what I am missing?
2. How to perform the click event on heart
Having looked at this only briefly, the problem appears to be that you are, in places, ignoring the 'y' position that is passed in to your drawListRow() method:
public void drawListRow(ListField list, Graphics graphics,
int index, int y, int w) {
Effectively the 'canvas' that you should be using to paint the current row (the row identified using int index) is bounded by the rectangle
(0, y, w, list.getRowHeight()).
In fact, you can actually paint anywhere in the extent that belongs to the ListField, i.e. the area you can paint onto is actually the rectangle
(0, 0, list.getWidth(), list.getHeight()).
You can do this, but you shouldn't. If you go outside your row's rectangle you will be painting over another row.
In your case, painting outside the selected row is exactly what your code does. You do this:
graphics.drawText("Hello", 10,
Display.getHeight() - 150);
This will actually be positioned on the ListField, 10 pixels in from the left and Display.getHeight() - 150 down from the top. It will be positioned at this point in the ListField, regardless of which row you are painting. So every row will put the Hello text in the same place.
So when coding your drawListRow(), make sure you offset all the positions to stay within the bounds of the row you are supposed to be painting. The origin of the area you are painting is (0, y), so offset all vertical positions using y. Do not use Display.getHeight(), use list.getRowHeight() to get the height you can paint (starting at y), and do not use Display.getWidth(), use the w variable that is passed in to get the width that you can paint. All your graphics actions should occur within these bounds.
I am developing an application which requires me to create a progress bar moving from right to left.
I tried using GaugeField by filling startVal as 100 and then on decrementing it but I couldn't achieve it.
Is there any way in BlackBerry say paint() method or drawRect() using timer where we can fill it from right to left?
Check following code for an implementation of Custom GaugeField.
Output
Implementation of CustomGaugeField
class CustomGaugeField extends GaugeField {
// Default constructor, need improvement
public CustomGaugeField() {
super("", 0, 100, 0, GaugeField.PERCENT);
}
// Colors
private static final int BG_COLOR = 0xd6d7d6;
private static final int BAR_COLOR = 0x63cb52;
private static final int FONT_COLOR = 0x5a55c6;
protected void paint(Graphics graphics) {
int xProgress = (int) ((getWidth() / 100.0) * getValue());
int xProgressInv = getWidth() - xProgress;
// draw background
graphics.setBackgroundColor(BG_COLOR);
graphics.clear();
// draw progress bar
graphics.setColor(BAR_COLOR);
graphics.fillRect(xProgressInv, 0, xProgress, getHeight());
// draw progress indicator text
String text = getValue() + "%";
Font font = graphics.getFont();
int xText = (getWidth() - font.getAdvance(text)) / 2;
int yText = (getHeight() - font.getHeight()) / 2;
graphics.setColor(FONT_COLOR);
graphics.drawText(text, xText, yText);
}
}
How to use
class MyScreen extends MainScreen {
public MyScreen() {
setTitle("Custom GaugeField Demo");
GaugeField gField;
for (int i = 0; i < 6; i++) {
gField = new CustomGaugeField();
gField.setMargin(10, 10, 10, 10);
add(gField);
}
startProgressTimer();
}
private void startProgressTimer() {
TimerTask ttask = new TimerTask() {
public void run() {
Field f;
for (int i = 0; i < getFieldCount(); i++) {
f = getField(i);
if (f instanceof CustomGaugeField) {
final CustomGaugeField gField = (CustomGaugeField) f;
final int increment = (i + 1) * 2;
UiApplication.getUiApplication().invokeLater(
new Runnable() {
public void run() {
gField.setValue((gField.getValue() + increment) % 101);
}
}
);
}
}
}
};
Timer ttimer = new Timer();
ttimer.schedule(ttask, 1000, 300);
}
}
Here is what I recommend you do. Download the BlackBerry Advanced UI Samples ... select the Download as Zip button.
Take a look at some screenshots of what the samples have here. The one you need to use is the Bitmap Gauge Field:
What you can do is modify the BitmapGaugeField class that they have in the sample folder, under Advanced UI -> src/com/samples/toolkit/ui/component
In BitmapGaugeField.java, you will only need to change the drawHorizontalPill() method:
private void drawHorizontalPill( Graphics g, Bitmap baseImage, Bitmap centerTile, int clipLeft, int clipRight, int width )
{
int yPosition = ( _height - baseImage.getHeight() ) >> 1;
width = Math.max( width, clipLeft + clipRight );
// ORIGINAL IMPLEMENTATION COMMENTED OUT HERE:
// Left
//g.drawBitmap( 0, yPosition, clipLeft, baseImage.getHeight(), baseImage, 0, 0);
// Middle
//g.tileRop( _rop, clipLeft, yPosition, Math.max( 0, width - clipLeft - clipRight ), centerTile.getHeight(), centerTile, 0, 0);
// Right
//g.drawBitmap( width - clipRight, yPosition, clipRight, baseImage.getHeight(), baseImage, baseImage.getWidth() - clipRight, 0);
int offset = _width - width;
// Left
g.drawBitmap( 0 + offset, yPosition, clipLeft, baseImage.getHeight(), baseImage, 0, 0);
// Middle
g.tileRop( _rop, clipLeft + offset, yPosition, Math.max( 0, width - clipLeft - clipRight ), centerTile.getHeight(), centerTile, 0, 0);
// Right
g.drawBitmap( width - clipRight + offset, yPosition, clipRight, baseImage.getHeight(), baseImage, baseImage.getWidth() - clipRight, 0);
}
The way you use this class is to pass in values for the background, and foreground (fill) stretchable bitmaps, the range of values, initial value, and some clipping margins.
public BitmapGaugeField(
Bitmap background, /** bitmap to draw for gauge background */
Bitmap progress, /** bitmap to draw for gauge foreground */
int numValues, /** this is the discrete range, not including 0 */
int initialValue,
int leadingBackgroundClip,
int trailingBackgroundClip,
int leadingProgressClip,
int trailingProgressClip,
boolean horizontal ) /** it looks like you could even do vertical! */
An example, if you want this gauge to go from 0 to 100, and have an initial value of 30 (this code goes in a Manager class):
Bitmap gaugeBack3 = Bitmap.getBitmapResource( "gauge_back_3.png" );
Bitmap gaugeProgress3 = Bitmap.getBitmapResource( "gauge_progress_3.png" );
BitmapGaugeField bitGauge3 = new BitmapGaugeField( gaugeBack3, gaugeProgress3,
100, 30,
14, 14, 14, 14,
true );
bitGauge3.setPadding(15,5,15,5);
add(bitGauge3);
bitGauge3.setValue(80); // change the initial value from 30 to 80
You'll find in the project some PNG images, like gauge_back_3.png and gauge_progress_3.png. If you don't like the colors or shapes, you can swap those images out for ones you draw yourself (in Photoshop, or another drawing program).
Good luck!
This is before focus state. It work fine.
This is on focusing state. It work fine.
This is after focus state. It occurred problem where the image gone.
It works fine for the top right but top left image got problem.
Here is my custom VerticalFieldManager:
public class Custom_TopField extends HorizontalFieldManager implements
FieldChangeListener {
private Bitmap bg = Bitmap.getBitmapResource("header_bar.png");
private Bitmap download = Bitmap.getBitmapResource("btn_download.png");
private Bitmap downloadactive = Bitmap
.getBitmapResource("btn_download_active.png");
private Bitmap refresh = Bitmap.getBitmapResource("icon_refresh.png");
private Bitmap refreshactive = Bitmap
.getBitmapResource("icon_refresh_active.png");
private Bitmap back = Bitmap.getBitmapResource("btn_back.png");
private Bitmap backctive = Bitmap.getBitmapResource("btn_back_active.png");
private Bitmap news = Bitmap.getBitmapResource("icon_news.png");
private Bitmap newsactive = Bitmap
.getBitmapResource("icon_news_active.png");
private Custom_ButtonField downloadbtn, refreshbtn, backbtn, newsbtn;
private Custom_LabelField title;
Custom_TopField(final MainScreen mainscreen) {
Background background = BackgroundFactory.createBitmapBackground(bg);
setBackground(background);
title = new Custom_LabelField("东方日报", DrawStyle.ELLIPSIS
| LabelField.USE_ALL_WIDTH | DrawStyle.HCENTER
| Field.FOCUSABLE, Color.WHITE) {
protected boolean navigationClick(int status, int time) {
Main.getUiApplication().pushScreen(new Main_AllLatestNews());
Main.getUiApplication().popScreen(mainscreen);
return true;
}
};
title.setFont(Font.getDefault().derive(Font.BOLD, 33));
add(title);
downloadbtn = new Custom_ButtonField(download, downloadactive,
downloadactive);
downloadbtn.setChangeListener(this);
add(downloadbtn);
refreshbtn = new Custom_ButtonField(refresh, refreshactive,
refreshactive);
refreshbtn.setChangeListener(this);
add(refreshbtn);
backbtn = new Custom_ButtonField(back, backctive, backctive);
backbtn.setChangeListener(this);
add(backbtn);
/*newsbtn = new Custom_ButtonField(news, newsactive, newsactive);
newsbtn.setChangeListener(this);
add(newsbtn);*/
}
protected void sublayout(int width, int height) {
Field field = getField(0);
layoutChild(field, 120, Font.getDefault().getHeight());
setPositionChild(field, (getPreferredWidth() - title.getWidth()) / 2,
15);
field = getField(1);
layoutChild(field, download.getWidth(), download.getHeight());
setPositionChild(field, getPreferredWidth()
- (download.getWidth() + 10),
getPreferredHeight() - (download.getHeight() + 5));
field = getField(2);
layoutChild(field, refresh.getWidth(), refresh.getHeight());
setPositionChild(field,
getPreferredWidth() - (refresh.getWidth() + 10),
getPreferredHeight() - (refresh.getHeight() + 5));
field = getField(3);
layoutChild(field, back.getWidth(), back.getHeight());
setPositionChild(field, 10, 5);
/*field = getField(4);
layoutChild(field, news.getWidth(), news.getHeight());
setPositionChild(field, 10, 5);*/
width = Math.min(width, getPreferredWidth());
height = Math.min(height, getPreferredHeight());
setExtent(width, height);
}
public int getPreferredHeight() {
return 70;
}
public int getPreferredWidth() {
return Display.getWidth();
}
public void paint(Graphics graphics) {
int rectHeight = getPreferredHeight();
int rectWidth = getPreferredWidth();
graphics.drawRect(0, 0, rectWidth, rectHeight);
super.paint(graphics);
}
public void fieldChanged(Field field, int context) {
if (field == downloadbtn) {
} else if (field == refreshbtn) {
} else if (field == backbtn) {
} else if (field == newsbtn) {
}
}
}
Here is custom button field
public class Custom_ButtonField extends ButtonField {
Bitmap mNormal;
Bitmap mFocused;
Bitmap mActive;
int mWidth;
int mHeight;
private int color = -1;
String text;
public Custom_ButtonField(Bitmap normal, Bitmap focused, Bitmap active) {
super(CONSUME_CLICK | Field.FOCUSABLE);
mNormal = normal;
mFocused = focused;
mActive = active;
mWidth = mNormal.getWidth();
mHeight = mNormal.getHeight();
setMargin(0, 0, 0, 0);
setPadding(0, 0, 0, 0);
setBorder(BorderFactory.createSimpleBorder(new XYEdges(0, 0, 0, 0)));
setBorder(VISUAL_STATE_ACTIVE,
BorderFactory.createSimpleBorder(new XYEdges(0, 0, 0, 0)));
}
public Custom_ButtonField(String text, Bitmap normal, Bitmap focused,
Bitmap active, int color) {
super(CONSUME_CLICK | Field.FOCUSABLE);
this.color = color;
mNormal = normal;
mFocused = focused;
mActive = active;
mWidth = mNormal.getWidth();
mHeight = mNormal.getHeight();
setMargin(0, 0, 0, 0);
setPadding(0, 0, 0, 0);
setBorder(BorderFactory.createSimpleBorder(new XYEdges(0, 0, 0, 0)));
setBorder(VISUAL_STATE_ACTIVE,
BorderFactory.createSimpleBorder(new XYEdges(0, 0, 0, 0)));
this.text = text;
}
protected void onFocus(int direction) {
super.onFocus(direction);
}
protected void onUnfocus() {
super.onUnfocus();
}
protected void paint(Graphics graphics) {
Bitmap bitmap = null;
switch (getVisualState()) {
case VISUAL_STATE_NORMAL:
bitmap = mNormal;
break;
case VISUAL_STATE_FOCUS:
bitmap = mFocused;
break;
case VISUAL_STATE_ACTIVE:
bitmap = mActive;
break;
default:
bitmap = mNormal;
}
graphics.drawBitmap(0, 0, bitmap.getWidth(), bitmap.getHeight(),
bitmap, 0, 0);
graphics.setFont(Font.getDefault().derive(Font.BOLD, 25));
graphics.setColor(color);
graphics.drawText(text, (mNormal.getWidth() - Font.getDefault()
.getAdvance(text)) / 2, ((mNormal.getHeight() - Font
.getDefault().getHeight()) / 2) + 10, DrawStyle.HCENTER
| DrawStyle.VCENTER);
}
public int getPreferredWidth() {
return mWidth;
}
public int getPreferredHeight() {
return mHeight;
}
protected void layout(int width, int height) {
setExtent(mWidth, mHeight);
}
}
This is the second problem just like this I've seen in the last couple weeks.
Background
To understand the solution, first you should understand the basic UI classes in BlackBerry.
First, we have the Field class. A Field is the base class of the normal UI components. If you write a UI component yourself, from scratch, then you would subclass Field:
public class MyWidget extends Field {
However, if there already exists a BlackBerry class that does almost what you need, and you just need to change its behaviour a bit, then you would subclass something else. For example:
public class MyButtonWidget extends ButtonField {
The same pattern exists for the Manager class. If you are writing a Manager from scratch, then extend Manager:
public class MyManager extends Manager {
which involves doing this, according to the BlackBerry docs:
Implementing your own layout manager
If you have particular needs, you
can implement your own manager. Extend the Manager class, and
implement sublayout, getPreferredWidth, and getPreferredHeight. For
efficiency, you may optionally override subpaint.
However, if an existing Manager subclass already does most of what you need, and you just want to customize it, then you might consider extending that subclass:
public class MyHorizontalManager extends HorizontalFieldManager {
In your case, your Custom_TopField is doing all of the required work for a fully custom Manager (see the highlighted quote above from the javadocs). So, there's not really any reason for you to extend HorizontalFieldManager. A HorizontalFieldManager is used when you just want to add() your fields, and have them all laid out horizontally. But, you do that explicitly in your sublayout() code. As it turns out, it looks like your logic is competing with the base class.
Solution
So, what you should do, is have your class just extend Manager:
public class Custom_TopField extends Manager implements FieldChangeListener {
If you do that, you will need to call a different super constructor. Something like this (you might want to pick different style constants depending on your needs):
Custom_TopField(final MainScreen mainscreen) {
super(Manager.USE_ALL_WIDTH | Manager.NO_VERTICAL_SCROLL | Manager.NO_HORIZONTAL_SCROLL);
Another alternative would be to simply not implement sublayout(), extend HorizontalFieldManager like you originally had, and then control layout with the child fields' margins and long style flags. But, since the solution I gave above requires only changing 2 lines of code, that's probably the easiest for you this time.
Other Problem(s)
I also noticed in your code, and screenshots, that the Download button doesn't show up. I don't know the exact size of all your png images, but if the refresh and download images are the same size, then your current logic is just laying out the refresh button right over the download button. So, the download button is hidden. That's probably not what you want?
I am a Blackberry java developer. I am trying to develop a simple slot machine logic. I am new to animated graphics etc in blackberry. So, can anyone tell me how to design a simple slot machine where on pressing a button the images in 3 blocks must start rotating and after it stops the prizes will be displayed according to the pics. So can u plz help me with some samples or tutorials of how to do it...
Edit: I am developing it just as fun application that doesnt involve any money transactions. So, any Blackberry developers plz guide me how to achieve the task and to spin the three images on click of a button...
This is a simple example but you will have to deal with decoration, smooth rolling etc yourself.
Let's say you have 6 images 70x70.
Simple BitmapField extension to paint current slot image, half of image above and half of image below:
class SlotField extends BitmapField {
Bitmap bmp1 = Bitmap.getBitmapResource("img1.png");
Bitmap bmp2 = Bitmap.getBitmapResource("img2.png");
Bitmap bmp3 = Bitmap.getBitmapResource("img3.png");
Bitmap bmp4 = Bitmap.getBitmapResource("img4.png");
Bitmap bmp5 = Bitmap.getBitmapResource("img5.png");
Bitmap bmp6 = Bitmap.getBitmapResource("img6.png");
Bitmap[] bmps = new Bitmap[] { bmp1, bmp2, bmp3, bmp4, bmp5, bmp6 };
int mPos = 0;
public SlotField(int position) {
mPos = position;
}
public int getBitmapHeight() {
return bmp1.getHeight() * 2;
}
public int getBitmapWidth() {
return bmp1.getWidth();
}
protected void layout(int width, int height) {
setExtent(getBitmapWidth(), getBitmapHeight());
}
int getNextPos() {
if (mPos == bmps.length - 1) {
return 0;
} else
return mPos + 1;
}
int getPrevPos() {
if (mPos == 0) {
return bmps.length - 1;
} else
return mPos - 1;
}
protected void paint(Graphics g) {
Bitmap hImg = bmps[getPrevPos()];
Bitmap mImg = bmps[mPos];
Bitmap lImg = bmps[getNextPos()];
g.drawBitmap(0, 0, 70, 35, hImg, 0, 35);
g.drawBitmap(0, 35, 70, 70, mImg, 0, 0);
g.drawBitmap(0, 105, 70, 35, lImg, 0, 0);
}
}
Now put these fields on screen and animate with timer:
class MainScr extends MainScreen {
SlotField slot1 = new SlotField(0);
SlotField slot2 = new SlotField(3);
SlotField slot3 = new SlotField(5);
boolean running = false;
public MainScr() {
HorizontalFieldManager hField = new HorizontalFieldManager();
add(hField);
hField.add(slot1);
hField.add(slot2);
hField.add(slot3);
ButtonField btnRoll = new ButtonField("Roll");
btnRoll.setChangeListener(new FieldChangeListener() {
public void fieldChanged(Field field, int context) {
if (!running)
rollSlots();
}
});
add(btnRoll);
}
void rollSlots() {
Timer timer = new Timer();
final Random rnd = new Random();
TimerTask ttask1 = new TimerTask() {
int cycle = 0;
public void run() {
slot1.mPos = slot1.getNextPos();
invalidate();
cycle++;
if (cycle >= 100+rnd.nextInt(6))
cancel();
}
};
TimerTask ttask2 = new TimerTask() {
int cycle = 0;
public void run() {
slot2.mPos = slot2.getNextPos();
invalidate();
cycle++;
if (cycle >= 100+rnd.nextInt(6))
cancel();
}
};
TimerTask ttask3 = new TimerTask() {
int cycle = 0;
public void run() {
slot3.mPos = slot3.getNextPos();
invalidate();
cycle++;
if (cycle >= 100+rnd.nextInt(6))
cancel();
}
};
timer.schedule(ttask1, 0, 50);
timer.schedule(ttask2, 200, 50);
timer.schedule(ttask3, 400, 50);
}
}
alt text http://img534.imageshack.us/img534/2172/slots.jpg
For UI functionality read
Blackberry User Interface Design - Customizable UI?
and
Blackberry - fields layout animation
The simulation of mechanical reels on a gaming machine is protected by United States Patent 7452276. The patent web page has links to 40 other US and international patents that you would have to investigate before you could start developing your software.
After you received permission from all of the different US and international patent holders to develop your software, you would develop a long .gif strip with the different images that you quickly move down in three or more positions. Your software would have to distort the top and bottom edges of the visible portions of the .gif strip to give the appearance of a mechanical slot wheel.