Custom buttons aren't displaying on my UI - user-interface

I'm creating a simple blackberry application for testing purposes and my custom buttons do not show on the UI of the simulator.
I've created a custom button called CustomButtonField and here is the code:
package test.expense;
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.Graphics;
public class CustomButtonField extends Field {
String label;
int backgroundColor;
int foregroundColor;
public CustomButtonField(String label, int backgroundColor, int foregroundColor, long style){
super(style);
this.label = label;
this.backgroundColor = backgroundColor;
this.foregroundColor = foregroundColor;
}
public int getPreferedHeight(){
return getFont().getHeight() + 8;
}
public int getPreferedWidth(){
return getFont().getAdvance(label) + 8;
}
protected void layout(int width, int height) {
setExtent(Math.min(width, getPreferredWidth()), Math.min(height, getPreferredHeight()));
}
protected void paint(Graphics graphics) {
graphics.setColor(backgroundColor);
graphics.fillRoundRect(1, 1, getWidth()-2, getHeight()-2, 12, 12);
graphics.setColor(foregroundColor);
graphics.drawText(label, 4, 4);
}
}
And here is where I invoke it and display it:
HorizontalFieldManager buttonManager = new HorizontalFieldManager(FIELD_RIGHT);
CustomButtonField btnCancel;
CustomButtonField btnSubmit;
public ExpenseSheetScreen() {
super();
btnCancel = new CustomButtonField("Cancel", Color.WHITE, 0x716eb3, 0);
btnCancel.setChangeListener(this);
btnSubmit = new CustomButtonField("Submit", Color.WHITE, 0x716eb3, 0);
btnSubmit.setChangeListener(this);
buttonManager.add(btnCancel);
buttonManager.add(btnSubmit);
add(buttonManager);
}// End Expense Sheet Screen.
What am I doing wrong?

protected void layout(int width, int height) {
setExtent(Math.min(width, getPreferredWidth()),
Math.min(height, getPreferredHeight()));
}
setExtend is set to 0, 0 all the time.

Related

No suitable method found in my overriden methods mono for android

I'm trying to draw a line based on touch event. Basically it draws line as the finger moves. I'm getting an error when overriding ontouchevent and onsizechanged. It was originally written in JAVA. I just translated it to C#. Here's the code:
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
currentLevel = Intent.GetIntExtra("gameLevel", 0);
playerScore = Intent.GetIntExtra("score", 0);
SetContentView(new SampleView(this));
// Create your application here
}
private class SampleView : View
{
private Paint mPaint;
private static Bitmap m_bitmap;
private DisplayMetrics m_metrics;
private Canvas m_canvas;
private Path m_path;
private Paint m_bitmapPaint;
private float m_X, m_Y;
static bool m_pathDrawn = false;
private static float TOUCH_TOLERANCE = 4;
public SampleView(Context context)
: base(context)
{
Focusable = true;
mPaint = new Paint();
mPaint.AntiAlias = true;
mPaint.Dither = true;
mPaint.SetStyle(Paint.Style.Stroke);
mPaint.StrokeWidth = 12;
mPaint.StrokeJoin = Paint.Join.Round;
mPaint.StrokeCap = Paint.Cap.Round;
m_metrics = context.Resources.DisplayMetrics;
m_bitmap = Bitmap.CreateBitmap(m_metrics.WidthPixels, m_metrics.HeightPixels, Bitmap.Config.Argb8888);
m_canvas = new Canvas(m_bitmap);
m_bitmapPaint = new Paint();
}
public void onerase()
{
m_canvas = null;
}
protected override void onSizeChanged(int p_w, int p_h, int p_oldw, int p_oldh)
{
this.onSizeChanged(p_w, p_h, p_oldw, p_oldh);
}
protected override void OnDraw(Canvas canvas)
{
canvas.DrawColor(Color.Black);
canvas.DrawBitmap(m_bitmap, 0, 0, m_bitmapPaint);
canvas.DrawPath(m_path, mPaint);
}
private void touch_start(float p_x, float p_y)
{
m_path.Reset();
m_path.MoveTo(p_x, p_y);
m_X = p_x;
m_Y = p_y;
}
private void touch_move(float p_x, float p_y)
{
float m_dx = Math.Abs(p_x - m_X);
float m_dy = Math.Abs(p_y - m_Y);
if (m_dx >= TOUCH_TOLERANCE || m_dy >= TOUCH_TOLERANCE)
{
m_path.QuadTo(m_X, m_Y, (p_x + m_X) / 2, (p_y + m_Y) / 2);
m_X = p_x;
m_Y = p_y;
m_pathDrawn = true;
}
}
private void touch_up()
{
m_path.LineTo(m_X, m_Y);
// commit the path to our offscreen
m_canvas.DrawPath(m_path, mPaint);
// kill this so we don't double draw
m_path.Reset();
}
public override bool onTouchEvent(MotionEvent p_event)
{
float m_x = p_event.GetX();
float m_y = p_event.GetY();
switch (p_event.Action)
{
case MotionEventActions.Down:
touch_start(m_x, m_y);
Invalidate();
break;
case MotionEventActions.Move:
touch_move(m_x, m_y);
Invalidate();
break;
case MotionEventActions.Up:
touch_up();
Invalidate();
break;
}
return true;
}
}
Another thing. I want to make my image view from a layout as my canvas and draw the line there ontouchevent. How should I do this? Thanks!
Method name should use pascal casing.
Android.Views.View.OnTouchEvent Method
Android.Views.View.OnSizeChanged Method
public override bool OnTouchEvent(MotionEvent e)
{
}
protected override void OnSizeChanged(int w, int h, int oldw, int oldh)
{
}
Mono coding guidelines.

how to crop image with particular shape in Blackberry?

Hi all thanks to read my answer hope you can help me
I am working on Image cropping in blackberry. In my application contain 3 main things.
1)Load the image on the screen
2)select the shape of the cropping area
3)display that cropping image on next screen with out losing its shape
Step1: i can done the image loading part
step2: using Menu i just add the 4 types of shapes
1)Circle
2)Rectangle with rounded shape
3)Star
4)Cloud
using menu when he click on any menu item ,then that particular shape image will display on the screen.
we can give the movement to that image because we have to provide him to select any portion of the image.
step3: After fix the position then we will allow the user to crop using menu.
when he click on menu item " CROP". then we have to crop the image according the shape and that image should display on the next screen
Note: Following code working only for Rectangular shape but i want to
use all shapes
This is my sample code ::
import net.rim.device.api.system.Bitmap;
import net.rim.device.api.system.Display;
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.Manager;
import net.rim.device.api.ui.MenuItem;
import net.rim.device.api.ui.Screen;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.XYEdges;
import net.rim.device.api.ui.XYRect;
import net.rim.device.api.ui.component.BitmapField;
import net.rim.device.api.ui.component.Dialog;
import net.rim.device.api.ui.component.Menu;
import net.rim.device.api.ui.container.MainScreen;
import net.rim.device.api.ui.container.VerticalFieldManager;
import net.rim.device.api.ui.decor.BackgroundFactory;
public class ClipMove extends MainScreen{
Bitmap circle_frame,rectangle_frame,star_frame,cloud_frame,image,selected_frame;
BitmapField frmae_field;
private int padding_x=0,padding_y=0;
private VerticalFieldManager vrt_mgr;
public ClipMove() {
//Here my shape images are transparent
circle_frame=Bitmap.getBitmapResource("circle.gif");
rectangle_frame=Bitmap.getBitmapResource("rect1.png");
star_frame=Bitmap.getBitmapResource("star.gif");
cloud_frame=Bitmap.getBitmapResource("cloud.gif");
//this is my actual image to crop
image=Bitmap.getBitmapResource("sample.jpg");
vrt_mgr=new VerticalFieldManager(){
protected void sublayout(int maxWidth, int maxHeight) {
super.sublayout(Display.getWidth(),Display.getHeight());
setExtent(Display.getWidth(),Display.getHeight());
}
};
vrt_mgr.setBackground(BackgroundFactory.createBitmapBackground(image));
add(vrt_mgr);
}
protected void makeMenu(Menu menu, int instance) {
super.makeMenu(menu, instance);
menu.add(new MenuItem("Rect",0,0) {
public void run() {
// TODO Auto-generated method stub
vrt_mgr.deleteAll();
selected_frame=rectangle_frame;
frmae_field=new BitmapField(rectangle_frame);
vrt_mgr.add(frmae_field);
vrt_mgr.invalidate();
}
});
menu.add(new MenuItem("Circle",0,0) {
public void run() {
// TODO Auto-generated method stub
vrt_mgr.deleteAll();
selected_frame=circle_frame;
frmae_field=new BitmapField(circle_frame);
vrt_mgr.add(frmae_field);
vrt_mgr.invalidate();
}
});
menu.add(new MenuItem("Star",0,0) {
public void run() {
// TODO Auto-generated method stub
vrt_mgr.deleteAll();
selected_frame=star_frame;
frmae_field=new BitmapField(star_frame);
vrt_mgr.add(frmae_field);
vrt_mgr.invalidate();
}
});
menu.add(new MenuItem("Cloud",0,0) {
public void run() {
// TODO Auto-generated method stub
vrt_mgr.deleteAll();
selected_frame=cloud_frame;
frmae_field=new BitmapField(cloud_frame);
vrt_mgr.add(frmae_field);
vrt_mgr.invalidate();
}
});
menu.add(new MenuItem("Crop",0,0) {
public void run() {
// TODO Auto-generated method stub
Field f=vrt_mgr.getField(0);
// XYRect rect=getFieldExtent(f);
XYRect rect=new XYRect(padding_x, padding_y,frmae_field.getBitmapWidth(),frmae_field.getBitmapHeight());
Bitmap crop = cropImage(image, rect.x, rect.y,
rect.width, rect.height);
synchronized (UiApplication.getEventLock()) {
UiApplication.getUiApplication().pushScreen(new sampleScreen(crop,selected_frame));
}
}
});
}
protected boolean navigationMovement(int dx, int dy, int status, int time) {
if(frmae_field!=null){
padding_x=padding_x+dx;
padding_y=padding_y+dy;
XYEdges edge=new XYEdges(padding_y, 0, 0, padding_x);
frmae_field.setPadding(edge);
vrt_mgr.invalidate();
return true;
}else {
return false;
}
}
public void DisplayMessage(final String str)
{
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
Dialog.inform(str);
}
});
}
public XYRect getFieldExtent(Field fld) {
int cy = fld.getContentTop();
int cx = fld.getContentLeft();
Manager m = fld.getManager();
while (m != null) {
cy += m.getContentTop() - m.getVerticalScroll();
cx += m.getContentLeft() - m.getHorizontalScroll();
if (m instanceof Screen)
break;
m = m.getManager();
}
return new XYRect(cx, cy, fld.getContentWidth(), fld.getContentHeight());
}
// this logic only useful for rectangler shape
public Bitmap cropImage(Bitmap image, int x, int y, int width,int height) {
Bitmap result = new Bitmap(width, height);
Graphics g = Graphics.create(result);
g.drawBitmap(0, 0, width, height, image, x, y);
return result;
}
}
//this is my next screen to show the croped image
class sampleScreen extends MainScreen
{
VerticalFieldManager manager;
public sampleScreen(final Bitmap img,final Bitmap back) {
manager=new VerticalFieldManager(){
protected void paint(Graphics graphics) {
graphics.drawBitmap(0, 0, img.getWidth(), img.getHeight(), img, 0, 0);
super.paint(graphics);
}
protected void sublayout(int maxWidth, int maxHeight) {
super.sublayout( img.getWidth(), img.getHeight());
setExtent( img.getWidth(), img.getHeight());
}
};
BitmapField field=new BitmapField(back);
field.setPadding(0, 0, 0, 0);
manager.add(field);
add(manager);
}
}
My screen shots:
By using another dummy image, it is possible to determine which pixels of the original image needs to be deleted (we can make them transparent). Though It may not be the optimal solution, but it can be applied for any geometric figure we can draw on BlackBerry.
Check following steps:
Create a new Bitmap image (dummyImage) of same dimension as the
source image (myImage).
Draw (fill) the target geometric shape on it using a defined color
(fillColor).
Now for each pixel of myImage, if the same pixel of dummyImage
contains fillColor then keep it unchanged, else make this pixel
fully transparent by assigning zero (0) to it.
Now myImage is almost ready, need to trim this image for
transparent pixel removal.
Following code will apply a circular crop on a image. (but won't trim the transparent pixels).
package mypackage;
import net.rim.device.api.system.Bitmap;
import net.rim.device.api.system.Display;
import net.rim.device.api.ui.Color;
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.MenuItem;
import net.rim.device.api.ui.component.BitmapField;
import net.rim.device.api.ui.component.Menu;
import net.rim.device.api.ui.container.MainScreen;
class MyScreen extends MainScreen {
private Bitmap myImage = Bitmap.getBitmapResource("img/myImage.jpeg");
private BitmapField _bf;
public MyScreen() {
_bf = new BitmapField(myImage);
adjustBitmapMargin();
add(_bf);
}
private void adjustBitmapMargin() {
int x = (Display.getWidth() - myImage.getWidth()) / 2;
int y = (Display.getHeight() - myImage.getHeight()) / 2;
_bf.setMargin(y, 0, 0, x);
}
protected void makeMenu(Menu menu, int instance) {
menu.add(miCropCircle);
super.makeMenu(menu, instance);
}
private MenuItem miCropCircle = new MenuItem("Crop - Circle", 0, 0) {
public void run() {
cropImage();
}
};
private void cropImage() {
int width = myImage.getWidth();
int height = myImage.getHeight();
// get original data from the image
int myImageData[] = new int[width * height];
myImage.getARGB(myImageData, 0, width, 0, 0, width, height);
// get default color of a newly created bitmap
int defaultColors[] = new int[1 * 1];
(new Bitmap(1, 1)).getARGB(defaultColors, 0, 1, 0, 0, 1, 1);
int defaultColor = defaultColors[0];
int fillColor = Color.RED;
int diameter = 200;
// dummy data preparation
Bitmap dummyImage = new Bitmap(width, height);
Graphics dummyImageGraphics = Graphics.create(dummyImage);
dummyImageGraphics.setColor(fillColor);
int startX = width / 2 - diameter / 2;
int startY = height / 2 - diameter / 2;
dummyImageGraphics.fillArc(startX, startY, diameter, diameter, 0, 360);
int dummyData[] = new int[width * height];
dummyImage.getARGB(dummyData, 0, width, 0, 0, width, height);
// filling original data with transparent value.
int totalPixels = width * height;
for (int i = 0; i < totalPixels; i++) {
if (dummyData[i] == defaultColor) {
myImageData[i] = 0;
}
}
// set new data
myImage.setARGB(myImageData, 0, width, 0, 0, width, height);
// redraw screen
_bf.setBitmap(myImage);
adjustBitmapMargin();
invalidate();
// free up some memory here
defaultColors = null;
dummyImage = null;
dummyData = null;
dummyImageGraphics = null;
}
}
Output of the above code:

BlackBerry text wraping

I can't align text on the BlackBerry screen. I've tried using a LabelField or a RichTextField but the text is not getting aligned the way I want. It is aligned horizontally and hidden in the screen. I want the text to wrap on the next line, when it hits the end of the screen horizontally, rather than getting hidden.
Here is my code -
import net.rim.device.api.ui.Color;
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.FieldChangeListener;
import net.rim.device.api.ui.Font;
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.Ui;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.component.LabelField;
import net.rim.device.api.ui.component.RichTextField;
import net.rim.device.api.ui.component.SeparatorField;
import net.rim.device.api.ui.container.HorizontalFieldManager;
import net.rim.device.api.ui.container.MainScreen;
import net.rim.device.api.ui.container.VerticalFieldManager;
public class DetailBloodBank extends MainScreen
{
String resultData = "", location = "", phoneNumber = "";
LabelField bloodBankName, locationLabel, phoneNumLabel;
String bloodBank = "";
LabelField locationDetail, phoneNumDetail;
public DetailBloodBank(String data) {
super(NO_VERTICAL_SCROLL);
int height = Display.getHeight();
int widhth = Display.getWidth();
//SizedVFM horizontalFieldManager = new SizedVFM(widhth,height);
HorizontalFieldManager horizontalFieldManager = new HorizontalFieldManager(HorizontalFieldManager.NO_VERTICAL_SCROLL)
{
protected void paint(Graphics g) {
g.setBackgroundColor(Color.BLACK);
g.clear();
super.paint(g);
}
};
//setBanner(horizontalFieldManager);
resultData = data;
System.out.println(resultData);
bloodBankName = new LabelField(resultData)
{
public void paint(Graphics g) {
g.setColor(Color.WHITE);
super.paint(g);
}
};
Font font = Font.getDefault().derive(Font.BOLD, 8, Ui.UNITS_pt);
bloodBankName.setFont(font);
locationLabel = new LabelField("Location")
{
public void paint(Graphics g) {
g.setColor(Color.WHITE);
super.paint(g);
}
};
Font font2 = Font.getDefault().derive(Font.BOLD, 8, Ui.UNITS_pt);
locationLabel.setFont(font2);
phoneNumLabel = new LabelField("Phone Number")
{
public void paint(Graphics g) {
g.setColor(Color.WHITE);
super.paint(g);
}
};
Font font3 = Font.getDefault().derive(Font.BOLD, 8, Ui.UNITS_pt);
phoneNumLabel.setFont(font3);
DBHelpers dbh = new DBHelpers();
dbh.retrieveDetails(resultData);
location = dbh.getLocation();
phoneNumber = dbh.getPhoneNumber();
dbh.getConnectionClose();
phoneNumDetail = new LabelField(phoneNumber)
{
public void paint(Graphics g) {
g.setColor(Color.WHITE);
super.paint(g);
}
};
Font font4 = Font.getDefault().derive(Font.PLAIN, 6, Ui.UNITS_pt);
phoneNumDetail.setFont(font4);
locationDetail = new LabelField(location)
{
public void paint(Graphics g) {
g.setColor(Color.WHITE);
super.paint(g);
}
};
Font font5 = Font.getDefault().derive(Font.PLAIN, 6, Ui.UNITS_pt);
locationDetail.setFont(font5);
final SeparatorField sepfield2 = new SeparatorField(SeparatorField.LINE_HORIZONTAL | Field.USE_ALL_WIDTH)
{
protected void paint(Graphics g) {
g.setBackgroundColor(Color.WHITE);
g.clear();
super.paint(g);
}
protected void layout(int maxWidth, int maxHeight) {
int width = Display.getWidth();
int height = 25; //height of the manager
super.layout(1250, 15);
}
};
final VerticalFieldManager verticalFieldManager = new VerticalFieldManager(NO_HORIZONTAL_SCROLL);
verticalFieldManager.add(locationLabel);
verticalFieldManager.add(locationDetail);
final VerticalFieldManager verticalFieldManager2 = new VerticalFieldManager(NO_HORIZONTAL_SCROLL);
verticalFieldManager2.add(phoneNumLabel);
verticalFieldManager2.add(phoneNumDetail);
VerticalFieldManager routeManager2 = new VerticalFieldManager()
{
protected void sublayout(int width, int height) {
layoutChild(bloodBankName, getPreferredWidth(), getPreferredHeight());
layoutChild(sepfield2, getPreferredWidth(), getPreferredHeight());
layoutChild(verticalFieldManager, getPreferredWidth(), getPreferredHeight());
layoutChild(verticalFieldManager2, getPreferredWidth(), getPreferredHeight());
setPositionChild(bloodBankName, 5, 15);
setPositionChild(sepfield2, 0, 35);
setPositionChild(verticalFieldManager, 0, 72);
int y = verticalFieldManager.getHeight();
System.out.println(y);
setPositionChild(verticalFieldManager2, 0, y + 90);
super.setExtent(width, height);
}
};
routeManager2.add(bloodBankName);
routeManager2.add(sepfield2);
routeManager2.add(verticalFieldManager);
routeManager2.add(verticalFieldManager2);
horizontalFieldManager.add(routeManager2);
add(horizontalFieldManager);
}
}
The problem is with your layout logic in routeManager2.
layoutChild(bloodBankName, getPreferredWidth(), getPreferredHeight());
The preferred width of the LabelField or RichTextField is going to be the width of the String associated with it in the current font size. It would prefer to show everything on one line if possible. So, instead of passing its preference, pass the width provided to sublayout(int, int).
layoutChild(bloodBankName, width, getPreferredHeight());
Hope this helps.

How can I display custom icon and two hyperlinks in model pop up on Blackberry map?

I need to display a custom icon and two hyperlinks in model pop up on Blackberry map. How can I do this?
alt text http://img689.imageshack.us/img689/2886/maplinkicon.jpg
First implement extention of ButtonField which will:
look like icon
on click will open Browser with predefined link
will use context menu
Code for such control:
class MapLinkIcon extends ButtonField implements FieldChangeListener {
Bitmap mNormal;
Bitmap mFocused;
String mLink;
String mDescription;
int mWidth;
int mHeight;
public MapLinkIcon(Bitmap normal, Bitmap focused, String link,
String description) {
super(CONSUME_CLICK);
mNormal = normal;
mFocused = focused;
mLink = link;
mDescription = description;
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.setChangeListener(this);
}
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 = mFocused;
break;
default:
bitmap = mNormal;
}
graphics.drawBitmap(0, 0, bitmap.getWidth(), bitmap.getHeight(),
bitmap, 0, 0);
}
public int getPreferredWidth() {
return mWidth;
}
public int getPreferredHeight() {
return mHeight;
}
protected void layout(int width, int height) {
setExtent(mWidth, mHeight);
}
protected void applyTheme(Graphics arg0, boolean arg1) {
}
public void fieldChanged(Field field, int context) {
openLink(mLink);
}
MenuItem mMenuItem = new MenuItem("Go To Link", 0, 0) {
public void run() {
openLink(mLink);
}
};
protected void makeContextMenu(ContextMenu contextMenu) {
super.makeContextMenu(contextMenu);
contextMenu.addItem(mMenuItem);
}
private static void openLink(String link) {
Browser.getDefaultSession().displayPage(link);
}
}
Now we can use this button control in combination with MapField, override sublayout to place button over the map:
class CustomMapField extends VerticalFieldManager {
MapField mMapField;
MapLinkIcon mButton;
public CustomMapField() {
add(mMapField = new MapField());
}
public int getPreferredHeight() {
return getScreen().getHeight();
}
public int getPreferredWidth() {
return getScreen().getWidth();
}
public void moveTo(Coordinates coordinates, Bitmap icoNorm, Bitmap icoAct,
String link, String description) {
mMapField.moveTo(coordinates);
add(mButton = new MapLinkIcon(icoNorm, icoAct, link, description));
}
protected void sublayout(int maxWidth, int maxHeight) {
int width = getPreferredWidth();
int height = getPreferredHeight();
layoutChild(mMapField, width, height);
setPositionChild(mMapField, 0, 0);
layoutChild(mButton, mButton.mWidth, mButton.mHeight);
XYPoint fieldOut = new XYPoint();
mMapField.convertWorldToField(mMapField.getCoordinates(), fieldOut);
int xPos = fieldOut.x - mButton.mWidth / 2;
int yPos = fieldOut.y - mButton.mHeight;
setPositionChild(mButton, xPos, yPos);
setExtent(width, height);
}
}
Example of use:
class Scr extends MainScreen {
CustomMapField mMapField;
Coordinates mCoordinates;
public Scr() {
double latitude = 51.507778;
double longitude = -0.128056;
mCoordinates = new Coordinates(latitude, longitude, 0);
mMapField = new CustomMapField();
Bitmap icoNormal = Bitmap.getBitmapResource("so_icon_normal.png");
Bitmap icoActive = Bitmap.getBitmapResource("so_icon_active.png");
String link = "http://stackoverflow.com";
String description = "StackOverflow";
mMapField.moveTo(mCoordinates, icoNormal, icoActive, link, description);
add(mMapField);
}
}
See also:
How to show our own icon in BlackBerry Map?
How to show more than one location in Blackberry MapField?

How do I color LabelField text within a ListField when the parent manager has the focus?

I have an overridden LabelField that allows me to change the font color based on whether an item in my ListField should be subdued or now. Making the LabelField color subdued works great. But, when the row (that contains my LabelField) is highlighted in the ListField, I would like the label field color to be different or inverted.
Here is my code:
public class MyLabelField extends LabelField{
public MyLabelField (String s, long l){
super(s, l);
m_bSubdue = true; // this value does change in implementation but not in this sample
}
protected void paint(Graphics g)
{
if(m_bSubdue && !this.isFocus()){ // this isFocus() trick is not working
int color = 0x00696969; // RGB val
g.setColor(color);
}
super.paint(g);
}
boolean m_bSubdue;
}
In this sample, I would like MyLabelField to be drawn with a gray color but when the ListField row its contained in has the focus, I would like the color to default to LabelField paint which should make it white.
Based on testing my code, it seems the LabelField does not get the focus when its parent row has the focus. Maybe a change is needed somewhere else in my code...
To switch color of LabelField we can check if it's selected in it's paint() method. But even then we'll have to repaint every row in ListField. And that's the problem: every time row selection of ListField is changed, there are only two calls of ListFieldCallback.drawRow() method - first for previous selected row (still in selected state) and second for new selected row (already in selected state)...
I've tried to save previous selected row index and redraw it on each call of drawRow(), but by some reason LabelField.paint() method was not triggered then.
So I come with simple, somehow ugly solution: schedule ListField.invalidate() TimerTask. Period in 100 ms is enough and doesn't hit performance as well.
Jason Emerick's code I've been used as a guide to extended ListField.
class LabelListField extends ListField implements ListFieldCallback {
private Vector mValues;
private Vector mRows;
public LabelListField(Vector values) {
super(0);
setRowHeight(70);
setCallback(this);
mValues = values;
fillListWithValues(values);
scheduleInvalidate();
}
private void scheduleInvalidate() {
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
invalidate();
}
}, 0, 100);
}
private void fillListWithValues(Vector values) {
mRows = new Vector();
for (int i = 0; i < values.size(); i++) {
TableRowManager row = new TableRowManager();
String title = "Item# " + String.valueOf(i + 1);
LabelField titleLabel = new LabelField(title);
titleLabel.setFont(Font.getDefault().derive(Font.BOLD));
row.add(titleLabel);
String value = (String) values.elementAt(i);
ListLabel valueLabel = new ListLabel(this, i, value);
valueLabel.setFont(Font.getDefault().derive(Font.ITALIC));
row.add(valueLabel);
mRows.addElement(row);
}
setSize(mRows.size());
}
private class TableRowManager extends Manager {
public TableRowManager() {
super(0);
}
public void drawRow(Graphics g, int x, int y,
int width, int height) {
layout(width, height);
setPosition(x, y);
g.pushRegion(getExtent());
paintChild(g, getField(0));
paintChild(g, getField(1));
g.popContext();
}
protected void sublayout(int width, int height) {
int fontHeight = Font.getDefault().getHeight();
int preferredWidth = getPreferredWidth();
Field field = getField(0);
layoutChild(field, preferredWidth - 5, fontHeight + 1);
setPositionChild(field, 5, 3);
field = getField(1);
layoutChild(field, preferredWidth - 5, fontHeight + 1);
setPositionChild(field, 5, fontHeight + 6);
setExtent(preferredWidth, getPreferredHeight());
}
public int getPreferredWidth() {
return Display.getWidth();
}
public int getPreferredHeight() {
return getRowHeight();
}
}
public void drawListRow(ListField listField, Graphics g,
int index, int y, int width) {
LabelListField list = (LabelListField) listField;
TableRowManager rowManager = (TableRowManager) list.mRows
.elementAt(index);
rowManager.drawRow(g, 0, y, width, list.getRowHeight());
}
public Object get(ListField list, int index) {
return mValues.elementAt(index);
}
public int indexOfList(ListField list, String prefix, int start) {
for (int x = start; x < mValues.size(); ++x) {
String value = (String) mValues.elementAt(x);
if (value.startsWith(prefix)) {
return x;
}
}
return -1;
}
public int getPreferredWidth(ListField list) {
return Display.getWidth();
}
class ListLabel extends LabelField {
int mIndex = -1;
public ListLabel(LabelListField list, int index, String text) {
super(text);
mIndex = index;
}
protected void paint(Graphics graphics) {
if (getSelectedIndex() == mIndex)
graphics.setColor(Color.RED);
else
graphics.setColor(Color.BLUE);
super.paint(graphics);
}
}
}

Resources