I have created a CustomToolTip with reference to
earlier questions i asked on stack
Custom pop Up
and
Dialog creation
Now , i have created a CustomisedToolTip like as follows
But the issue is the whole screen gets displayed or occupied the space
i need such that the TextField on the previous screen be Active for that moment
The code for Customised Tool Tip i generated is as follows
import net.rim.device.api.system.Bitmap;
import net.rim.device.api.system.Characters;
import net.rim.device.api.ui.Color;
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.Manager;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.component.BitmapField;
import net.rim.device.api.ui.component.ButtonField;
import net.rim.device.api.ui.component.LabelField;
import net.rim.device.api.ui.container.PopupScreen;
import net.rim.device.api.ui.container.VerticalFieldManager;
import net.rim.device.api.ui.decor.Background;
import net.rim.device.api.ui.decor.BackgroundFactory;
public class ToolTip extends PopupScreen{
protected void applyTheme() {
}
private static VerticalFieldManager vfm=new VerticalFieldManager(Manager.NON_FOCUSABLE|Manager.FIELD_HCENTER){
protected void paint(Graphics graphics) {
graphics.setColor(0x00FFFFFF);
graphics.fillRect(0,0,getWidth(),getHeight());
graphics.setColor(0x00000000);
graphics.drawRect(0,0,getWidth(),getHeight());
super.paint(graphics);
}
};
private LabelField lbl;
private static int xPosition;
private static int yPosition;
private String message;
private static Bitmap toolTipImg;
private static BitmapField toolTipBmpFld;
private static ButtonField button;
public ToolTip(final String message,int xPos,int yPos,final Bitmap toolTipImg){
super(vfm);
this.xPosition=xPos;
this.yPosition=yPos;
this.message=message;
this.toolTipImg=toolTipImg;
button=new ButtonField(message,ButtonField.NON_FOCUSABLE){
protected void paint(Graphics graphics) {
graphics.drawBitmap(0,0, toolTipImg.getWidth(), toolTipImg.getHeight(), toolTipImg, 0, 0);
super.paint(graphics);
}
protected void layout(int width, int height) {
super.layout(width, height);
setExtent( toolTipImg.getWidth(), toolTipImg.getHeight());
}
};
vfm.add(button);
}
protected void sublayout(int width, int height) {
super.sublayout(width, height);
setPosition(xPosition, yPosition);
}
protected boolean keyChar(char c, int status, int time) {
// TODO Auto-generated method stub
if(c==Characters.ESCAPE)
{
UiApplication.getUiApplication().popScreen(UiApplication.getUiApplication().getActiveScreen());
}
return super.keyChar(c, status, time);
}
}
Can i get a pop up like this in Blackberry
Overriding the protected void paint(Graphics graphics) method of MainScreen can be helpful in this case.
When a Field get focus, you can tell the MainScreen (parent screen) to draw a tooltip on specified position after it completes it own drawing. And when the Field lost focus, you can avoid tooltip painting. Also a timer can be introduced for removing the tooltip after some time.
Check following implementation. The implementation needs to be improved, currently it's only represents my idea.
public final class MyScreen extends MainScreen implements TooltipProtocol {
private TooltipProtocol tooltipProtocolInstance;
public MyScreen() {
tooltipProtocolInstance = this;
ButtonField bfOne = getButtonField("ButtonField One", "Tooltip One", 200, 20);
ButtonField bfTwo = getButtonField("ButtonField Two", "Tooltip Two", 200, 60);
add(bfOne);
add(bfTwo);
}
private ButtonField getButtonField(String text, final String tooltiptext, final int x, final int y) {
ButtonField bf = new ButtonField(text) {
protected void onFocus(int direction) {
tooltipProtocolInstance.showToolTipText(tooltiptext, x, y);
super.onFocus(direction);
}
protected void onUnfocus() {
tooltipProtocolInstance.hideToolTipText();
super.onUnfocus();
}
};
return bf;
}
private String toolTipText;
private int xTooptip;
private int yTooptip;
private Timer tooltipTimer;
public void showToolTipText(String text, int x, int y) {
toolTipText = text;
xTooptip = x;
yTooptip = y;
if (tooltipTimer != null) {
tooltipTimer.cancel();
tooltipTimer = null;
}
tooltipTimer = new Timer();
tooltipTimer.schedule(new TimerTask() {
public void run() {
hideToolTipText();
}
}, 2000);
invalidate();
}
public void hideToolTipText() {
toolTipText = null;
invalidate();
}
protected void paint(Graphics graphics) {
super.paint(graphics);
if (toolTipText != null) {
int oldColor = graphics.getColor();
graphics.setColor(Color.GREEN);
graphics.drawText(toolTipText, xTooptip, yTooptip);
graphics.setColor(oldColor);
}
}
}
interface TooltipProtocol {
public void showToolTipText(String text, int x, int y);
public void hideToolTipText();
}
Following are output of the above code:
When first button got focus
When first button lost focus, second button got focus
When timer hides tooltip of the second button
As far I understand the question, you want to create a tool tip kind popup screen, but you want user to interact with your LoginScreen UI elements without blocking the whole screen by the tool tip.
This cannot be achievable in Blackberry. PropupScreen acts like a dialog. As we are pushing the instance of the popup screen to the screen stack to make it visually appear, it always block the delegate screen. Unless you remove the popup from the screen stack you cannot interact with your LoginScreen UI components, though they are visually available.
Visit Blackberry java docs for more details: http://www.blackberry.com/developers/docs/6.0.0api/net/rim/device/api/ui/container/PopupScreen.html
Edit:1
You can create a ToolTip screen giving the timer. You can google around and i am sure you will get many code samples. I have listed one link below.
http://v4ks1n.wordpress.com/2011/01/28/tooltips-class-for-blackberry/
Related
I am working on BB OS v5.0. I have managed to get the list to appear on the screen. I am getting data from webservice and adding it into a Vector.
Now I want to find out onclick, which is the item that is clicked and accordingly perform some operation. For that i am trying to display an alert. But I'm not getting the alert.
Here is my code :
In my mainscreen , i added fieldmanager=new VerticalFieldManager(); and add(fieldmanager);
void fetchAlbumsForLetter(String letter) {
Status.show("Processing ....", 3000);
fieldManager.deleteAll();
VerticalFieldManager top = new VerticalFieldManager(Manager.NO_HORIZONTAL_SCROLL | Manager.NO_HORIZONTAL_SCROLLBAR | Manager.VERTICAL_SCROLL | Manager.VERTICAL_SCROLLBAR | Field.USE_ALL_WIDTH){
public void paint(Graphics graphics) {
graphics.setBackgroundColor(0x00290008);
graphics.setColor(Color.WHITE);
graphics.clear();
graphics.drawBitmap(0, 0, sha.getWidth(),
sha.getHeight(), sha, 0, 0);
super.paint(graphics);
}
};
add(top);
CustomListField4 list4 = new CustomListField4(null){
protected boolean navigationClick(int status, int time) {
getValue4();
return true;
}
};
fieldmanager.add(list4);
}
protected void getValue4() {
Field f = getFieldWithFocus();
if (f instanceof ListField) {
ListField l = (ListField) f;
final int index = l.getSelectedIndex();
HistoryItem _contactslist = (HistoryItem) CustomListField4.val4.elementAt(index);
final String id = _contactslist.getName();
Dialog.alert(id+"");
}
}
Please help me to resolve this
EDIT
class CustomListField4 extends ListField implements ListFieldCallback {
public CustomListField4(Vector data) {
super(0, ListField.MULTI_SELECT);
final TableRowManager row = new TableRowManager() {
public void paint(Graphics g) {
// g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(0x0f3e19b);
g.clear();
super.paint(g);
}
};
Bitmap icon = Bitmap.getBitmapResource("Devil Skype.png");
HorizontalFieldManager h=new HorizontalFieldManager();
h.add(new BitmapField(icon));
//h.add(new BitmapField(song.getThumb()));
h.add(new LabelField(song.getAlbumName()));
//h.add(new LabelField(row1.getLanguage()));
//h.setMargin(0,0,50,0);
//Dialog.alert(song.getName());
VerticalFieldManager vfm=new VerticalFieldManager();
vfm.add(h);
//vfm.add(new LabelField(song.getArtist()));
row.add(vfm);
contacts.addElement(row);
}
setSize( contacts.size());
}
// ListFieldCallback Implementation
public void drawListRow(ListField listField, Graphics g, int index, int y, int width) {
listField.setRowHeight(index,107);
CustomListField4 list = (CustomListField4) listField;
TableRowManager rowManager = (TableRowManager) CustomListField4.contacts.elementAt(index);
rowManager.drawRow(g, 0, y, width, list.getRowHeight());
}
public class TableRowManager extends Manager {
public TableRowManager() {
super(0);
}
You are calling getFieldWithFocus() which will give you the manager. You need to get the leaf field
protected void getValue4() {
Field f = getLeafFieldWithFocus();
if (f instanceof ListField) {
//Your code
}
}
I think your hierarchy of Field and Manager objects is incorrect, and this is causing problems with your detection of field focus/selection.
It wasn't obvious from the original code you posted, but by looking at your update, I assume that you are calling fetchAlbumsForLetter() once for every row. That's not right.
fetchAlbumsForLetter() is creating a new CustomListField4 each time it's called. And, CustomListField4 is a ListField.
A ListField is not meant to represent only one row. It's meant to represent all the rows. You should only create one instance of CustomListField4.
I would do either one of two things:
1. Continue to Use a ListField
If you want CustomListField4 to be a ListField (extends ListField), then in your implementation of
public void drawListRow(ListField listField, Graphics g, int index, int y, int width);
you should actually draw graphics objects, using all the Graphics#draw methods. These are primitive graphics items, like filled areas, lines, text, or bitmaps. You would not be using Field objects inside each ListField row, as you're trying to do with your TableRowManager class.
See here for a sample ListField, or here for a more sophisticated example
2. Imitate ListField with a Manager
change your code to
public class CustomListField4 extends VerticalFieldManager {
or
public class CustomListField4 extends Manager {
Then, you can use a TableRowManager for each row, and add LabelField or BitmapField objects to it.
See here for an example of this
If you fix these problems, then I think the way you are overriding navigationClick() will work fine for detecting the row click, and doing something with the selected row.
You can try this
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
Dialog.alert(id+"");
}
});
Hi, I want to create a Login Screen which has a Username and Password
and a Sign in Button
But when a user fails to enter correct information inside the TextField of Username or Password a pop up like the image chat dialog should pop up from corner of TextField's right side displaying appropriate message How can this Customization be achieved?
i am giving you a simple way. If it is not perfect to your question you just ignore this answer.
Here i made logic like following. i gave you two buttons
1)Login
2)remove
I think you know how to validate your text fields right or wrong; keep one if condition ,write your logic if right no need any field
else wrong then you have three conditions
1)id is wrong
2)password is wrong
or 3)both wrong
according two that condition you can add particular tooltip box on above text field .
I am providing sample for both wrong condition and remove condition also
make it as your requirements
Resources :
chat.png image is required for background
Sample code:
package mypackage;
import net.rim.device.api.system.Bitmap;
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.FieldChangeListener;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.XYEdges;
import net.rim.device.api.ui.component.BasicEditField;
import net.rim.device.api.ui.component.ButtonField;
import net.rim.device.api.ui.container.MainScreen;
import net.rim.device.api.ui.container.VerticalFieldManager;
import net.rim.device.api.ui.decor.Border;
import net.rim.device.api.ui.decor.BorderFactory;
/**
* A class extending the MainScreen class, which provides default standard
* behavior for BlackBerry GUI applications.
*/
public final class MyScreen extends MainScreen implements FieldChangeListener
{
/**
* Creates a new MyScreen object
*/
private BasicEditField id,password;
private ButtonField login,cancel;
private VerticalFieldManager id_mgr,pass_mgr;
private PopupField id_hint,pass_hint;
public static Bitmap img;
public MyScreen()
{
img=Bitmap.getBitmapResource("chat.png");
// Set the displayed title of the screen
setTitle("Login Page");
Border b=BorderFactory.createRoundedBorder(new XYEdges(5, 5, 5, 5), Border.STYLE_SOLID);
id_hint=new PopupField("Wrong Id", img);
pass_hint=new PopupField("Wrong password", img);
id_mgr=new VerticalFieldManager();
id=new BasicEditField(){
protected void layout(int width, int height) {
super.layout(120, 40);
setExtent(120, 40);
}
};
id.setBorder(b);
add(id_mgr);
add(id);
pass_mgr=new VerticalFieldManager();
password=new BasicEditField(){
protected void layout(int width, int height) {
super.layout(120, 40);
setExtent(120, 40);
}
};
password.setBorder(b);
add(pass_mgr);
add(password);
login=new ButtonField("Login");
login.setChangeListener(this);
add(login);
cancel=new ButtonField("Remove");
cancel.setChangeListener(this);
add(cancel);
}
public void fieldChanged(Field field, int context) {
if(field==login)
{
try {
// id_mgr.add(new NullField(Field.FOCUSABLE));
id_mgr.add(id_hint);
id_mgr.setPadding(0, 0, 0, 50);
pass_mgr.add(pass_hint);
pass_mgr.setPadding(0, 0, 0, 50);
id_hint.setFocus();
} catch (IllegalStateException e) {
return;
}
}else if(cancel==field)
{
synchronized (UiApplication.getEventLock()) {
id_mgr.deleteAll();
pass_mgr.deleteAll();
}
}
}
}
and class for PopupField.java is
package mypackage;
import net.rim.device.api.system.Bitmap;
import net.rim.device.api.ui.Color;
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.component.BitmapField;
public class PopupField extends BitmapField{
private Bitmap img,scalled_img;
private String message;
private int layout_width;
public PopupField(String message,Bitmap img)
{
this.message=message;
layout_width=this.getFont().getAdvance(message)+40;
scalled_img=new Bitmap(layout_width, img.getHeight());
img.scaleInto(scalled_img, Bitmap.FILTER_BILINEAR);
this.img=scalled_img;
}
protected void layout(int width, int height) {
super.layout(img.getWidth(), img.getHeight());
setExtent(img.getWidth(), img.getHeight());
}
protected void paint(Graphics graphics) {
graphics.drawBitmap(0, 0, img.getWidth(), img.getHeight(), img,0,0);
graphics.setColor(Color.RED);
graphics.drawText(message,20,20);
super.paint(graphics);
}
}
output image :
keep helping to others
Other solution is this link will tell you
http://v4ks1n.wordpress.com/2011/01/28/tooltips-class-for-blackberry/
I have listfield which contains several rows.
It is working fine when i am using in blackberry torch(I can scroll the listfield and can select(click) any row).
But the same application when i am using for blackberry storm 9500 I can not scroll because as soon as i am trying to scroll the row is getting selected(click).please tell me the reason why it is happening or the way to use listfield in storm
thank you
My lisfield class is
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.UiApplication;
import net.rim.device.api.ui.XYRect;
import net.rim.device.api.ui.component.Dialog;
import net.rim.device.api.ui.component.ListField;
import net.rim.device.api.ui.component.ListFieldCallback;
public class SpeakersList implements ListFieldCallback
{
private String[] products;
private int rgb=Color.BLACK;
Bitmap arraow;
Bitmap placeholder;
Bitmap holder[];
int i=0;
ImageLoad load;
public Bitmap _bmap;
ListField listField;
TaskWorker taskWorker;
public SpeakersList(String[] products)
{
this.products=products;
arraow= Bitmap.getBitmapResource("arrow.png");
DynamicImages images=new DynamicImages();
placeholder=Bitmap.getBitmapResource(images.defaultimage);
holder=new Bitmap[QandAScreen.imglist.length];
taskWorker = new TaskWorker();
taskWorker.addTask(new ImageDowload());
}
public void drawListRow(ListField listField, Graphics graphics, int index,
int y, int width)
{
this.listField=listField;
final String text=(String) get(listField, index);
if (graphics.isDrawingStyleSet(Graphics.DRAWSTYLE_FOCUS))
{
if(holder[index]==null)
{
holder[index]=placeholder;
}
graphics.setColor(0xC0C0C0);
graphics.fillRect(0,y+0,480,59);
graphics.setColor(rgb);
graphics.setFont(Utility.getBigFont(15));
graphics.drawBitmap(3,y+7,placeholder.getWidth(), placeholder.getHeight(),holder[index], 0, 0);
graphics.drawText(text,70,y+20);
if(Display.getWidth()==480){
graphics.drawBitmap(460,y+20,arraow.getWidth(), arraow.getHeight(),arraow, 0, 0);
}
else if(Display.getWidth()==360)
{
graphics.drawBitmap(330,y+20,arraow.getWidth(), arraow.getHeight(),arraow, 0, 0);
}
else
{
graphics.drawBitmap(300,y+20,arraow.getWidth(), arraow.getHeight(),arraow, 0, 0);
}
graphics.drawLine(0, y+59, Display.getWidth(), y+59);
}
else
{
if(holder[index]==null)
{
holder[index]=placeholder;
}
graphics.setColor(rgb);
graphics.setFont(Utility.getBigFont(15));
graphics.drawBitmap(3,y+7,placeholder.getWidth(), placeholder.getHeight(),holder[index], 0, 0);
graphics.drawText(text,70,y+20);
if(Display.getWidth()==480){
graphics.drawBitmap(460,y+20,arraow.getWidth(), arraow.getHeight(),arraow, 0, 0);
}
else if(Display.getWidth()==360)
{
graphics.drawBitmap(330,y+20,arraow.getWidth(), arraow.getHeight(),arraow, 0, 0);
}
else
{
graphics.drawBitmap(300,y+20,arraow.getWidth(), arraow.getHeight(),arraow, 0, 0);
}
graphics.drawLine(0, y+59, Display.getWidth(), y+59);
}
}
public Object get(ListField listField, int index)
{
return products[index];
}
public int getPreferredWidth(ListField listField)
{
return Display.getWidth()+10;
}
public int indexOfList(ListField listField, String prefix, int start)
{
return -1;
}
class ImageDowload extends Task
{
void doTask()
{
for(;i<QandAScreen.imglist.length;i++)
{
String imgpath=QandAScreen.imglist[i];
if(imgpath==null || imgpath.length()==0)
{
continue;
}
load=new ImageLoad(QandAScreen.imglist[i]+Const.getExtra());
if(load.getData()!=null)
{
UiApplication.getUiApplication().invokeLater(new Runnable()
{
public void run()
{
_bmap=load.getBitmap(40,40);
listField.invalidate(i-1);
holder[i-1]=_bmap;
}
});
}
}
}
}
}
Are you testing with the simulators or real devices? If my memory serves, the 9500 Storm uses the SureClick -display, where the display actually has a small microswitch underneath it, so it can detect touch and clicking (pressing the display) as separate actions. In the simulator, you need to use right mouse button to simulate touch and left to simulate click (or was it the other way around?). Torch (9800) hasn't got the SureClick-thingamabob, so the list can be scrolled with both right and left mouse buttons in the simulator (although they did have some distinction, other worked as touch and other sends continuous 'taps' to the screen or something).
I have a question about the BlackBerry VerticalScrollField and scrolling which seems to lock or make the UI unstable. The following code is a BlackBerry screen with worlds as content on the left (in a scroll field) and a jumpbar off to the right that allows clicking into the content.
When a jump letter is clicked the setVerticalScroll method is called, it performs the scroll but has the unfortunate side effect of rendering the UI unstable or unusable. The scroll call is done on the UI thread so its not clear what the source of the error is. The app is being tested in a 6.0 simulator.
I've included the class which can be copied into BB Eclipse for hacking/testing.
The section that kicks of the scrolling can be found towards the bottom with the following code:
UiApplication.getUiApplication().invokeLater(new Runnable(){
public void run() {
scroller.setVerticalScroll(y, true);
}});
Here's the full class:
package test;
import java.util.Vector;
import net.rim.device.api.system.ApplicationManager;
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.Font;
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.TouchEvent;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.component.LabelField;
import net.rim.device.api.ui.component.Status;
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 Startup extends UiApplication {
private int[] jump;
static final String[] words = new String[]{
"auto", "apple", "bear", "car", "farm", "ferret", "gold",
"green", "garden", "hedge", "happy", "igloo", "infrared",
"jelly", "kangaroo", "lemon", "lion", "marble", "moon",
"nine", "opera", "orange", "people", "puppy", "pear",
"quince", "race", "run", "sunset", "token", "willow", "zebra"
};
private final static String[] alphabet = new String[]{"A","B","C","D","E",
"F","G","H","I","J","K","L","M","N","O","P","Q","R",
"S","T","U","V","W","X","Y","Z","#"};
private VerticalFieldManager scroller;
public Startup() {
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
UiApplication.getUiApplication().pushScreen(new ScrollScreen());
}
});
}
public static void main(String[] args) {
ApplicationManager app = ApplicationManager.getApplicationManager();
while (app.inStartup()) {
try { Thread.sleep(200); } catch (Throwable e) {}
}
Startup startup = new Startup();
startup.enterEventDispatcher();
}
/**
* Screen with content in a scrollbar left and a letters on the right that
* can be used to jump into the content.
*/
class ScrollScreen extends MainScreen {
public ScrollScreen() {
super(NO_HORIZONTAL_SCROLL | NO_VERTICAL_SCROLL);
HorizontalFieldManager hfm = new HorizontalFieldManager(USE_ALL_HEIGHT | NO_VERTICAL_SCROLL | NO_HORIZONTAL_SCROLL){
protected void sublayout(int maxWidth, int maxHeight) {
Field scroll = getField(0);
Field alpha = getField(1);
layoutChild(alpha, maxWidth, maxHeight);
layoutChild(scroll, maxWidth-alpha.getWidth(), maxHeight);
setPositionChild(scroll, 0, 0);
setPositionChild(alpha, maxWidth-alpha.getWidth(), 0);
setExtent(maxWidth, maxHeight);
}
};
hfm.add(createScrollContent());
hfm.add(createAlphabetJumpBar());
add(hfm);
}
private Field createScrollContent() {
Vector vocabulary = new Vector();
for (int ii=0; ii<alphabet.length; ii++)
vocabulary.addElement(alphabet[ii]);
scroller = new VerticalFieldManager(VERTICAL_SCROLL | USE_ALL_WIDTH) {
protected void sublayout(int maxWidth, int maxHeight) {
// Record the jump offsets
int y = 0;
for (int ii=0; ii<getFieldCount(); ii++) {
Field field = getField(ii);
layoutChild(field, maxWidth, maxHeight);
setPositionChild(field, 0, y);
if (field instanceof WordField) {
WordField object = (WordField)field;;
char character = object.getWord().toLowerCase().charAt(0);
int offset = ((int)character)-(int)alphabet[0].toLowerCase().charAt(0);
if (offset < 0 || offset > jump.length)
offset = jump.length-1;
while (offset >= 0 && offset < jump.length && jump[offset] == 0) {
jump[offset] = y;
offset--;
}
}
y += field.getHeight();
}
int offset = jump.length-1;
do {
jump[offset] = y;
offset--;
} while (offset >= 0 && jump[offset] == 0);
setExtent(maxWidth, maxHeight);
setVirtualExtent(maxWidth, y+10);
}
};
jump = new int[alphabet.length];
Font largeFont = Font.getDefault().derive(Font.PLAIN, 46);
for (int ii=0; ii<words.length; ii++) {
WordField wordField = new WordField(words[ii]);
wordField.setFont(largeFont);
scroller.add(wordField);
}
return scroller;
}
private Field createAlphabetJumpBar() {
VerticalFieldManager vfm = new VerticalFieldManager() {
protected void sublayout(int maxWidth, int maxHeight) {
int y = 0;
int width = 0;
double allowedAlphaHeight = (double)maxHeight / (double)getFieldCount();
for (int ii=0; ii<getFieldCount(); ii++) {
WordField field = (WordField)getField(ii);
layoutChild(field, maxWidth, (int)allowedAlphaHeight);
setPositionChild(field, 0, y);
y += field.getHeight();
double paddedY = Math.floor(allowedAlphaHeight*(ii+1));
if (y < paddedY) y = (int)paddedY;
width = Math.max(width, field.getWidth());
}
setExtent(width, maxHeight);
}
};
for (int ii=0; ii<alphabet.length; ii++) {
vfm.add(new AlphaField(alphabet[ii]){
protected boolean touchEvent(TouchEvent message) {
if (message.getEvent() == TouchEvent.UP) {
int startOffset = (int)alphabet[0].charAt(0);
int offset = ((int)getWord().charAt(0)) - startOffset;
final int y = offset == 0 ? 0 : jump[offset - 1];
UiApplication.getUiApplication().invokeLater(new Runnable(){
public void run() {
scroller.setVerticalScroll(y, true);
}});
}
return true;
}
});
}
return vfm;
}
class WordField extends LabelField {
private final String word;
public WordField(String word) {
super(word);
this.word = word;
}
public String getWord() { return word; }
}
Font alphaFont = null;
class AlphaField extends WordField {
public AlphaField(String word) {
super(word);
}
protected void layout(int width, int height) {
if (alphaFont == null)
alphaFont = Font.getDefault().derive(Font.PLAIN, height);
setExtent(alphaFont.getAdvance(getWord()), alphaFont.getHeight());
}
protected void paint(Graphics graphics) {
graphics.setFont(alphaFont);
graphics.drawText(getWord(), 0, 0);
}
}
/**
* For debugging.
* #see net.rim.device.api.ui.Screen#keyChar(char, int, int)
*/
protected boolean keyChar(char c, int status, int time) {
if ('o' == c) { // shows the jump offsets into the scroll field
UiApplication.getUiApplication().invokeLater(new Runnable(){
public void run() {
StringBuffer buf = new StringBuffer();
for (int ii=0; ii<jump.length; ii++) {
buf.append(alphabet[ii]+"="+jump[ii]);
if (ii<jump.length-1)
buf.append(",");
}
Status.show("offsets="+buf.toString());
}});
}
return super.keyChar(c, status, time);
}
}
}
You're using UiApplication.invokeLater in a few places where you're already on the UI event thread, so those are redundant - the debug code in keyChar and the setVerticalScroll call from the touchEvent handler. The Runnable is executed synchronously when you do an invokeLater from the UI thread, with no delay specified.
Are you sure you want to set the scroll explicitly? One option would be to set the focus on the WordField you are interested in, by calling setFocus(), then the OS will do the scrolling events to move that field on screen for you.
If you really need to explicitly set the vertical scroll, your problem may be that the touch event is already causing scroll, so setting it again causes problems. You can get around this by specifying a one millisecond delay for your invokeLater(...). This means your Runnable will be added to the event queue, instead of executing synchronously. That way the scroll won't be changed in the middle of another event call-stack.
Finally tracked down the issue - if the touchEvent for the alphabet label field returns a true then it locks up the main scroll field, if however return super.touchEvent(message) is called the scrolling happens and the scroll field can still be scrolled up and down by clicking on the screen.
This may be a bug in the BlackBerry OS or just the simulator. The Field.touchEvent() documentation for 6.0 recommends returning true if the method consumes the event; however doing so (at least in the above code) causes another UI field to loose the ability to detect touch events which would cause it to scroll.
i am developing custom toolbar manager, but i want to adjust the fields alignment to be centered not aligned to the left , any advice
below is the code of toolbar
package galaxy.bb.ui.container;
import net.rim.device.api.ui.Color;
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.XYEdges;
import net.rim.device.api.ui.container.HorizontalFieldManager;
import net.rim.device.api.ui.decor.Background;
import net.rim.device.api.ui.decor.BackgroundFactory;
import net.rim.device.api.ui.decor.Border;
import net.rim.device.api.ui.decor.BorderFactory;
public class ToolBarManager extends HorizontalFieldManager {
private int bgColor = Color.BLACK;
private int borderColor = Color.WHITE;
private int borderStyle= Border.STYLE_FILLED;
public ToolBarManager(){
super(USE_ALL_WIDTH);
}
public ToolBarManager(int bgColor) {
super(USE_ALL_WIDTH);
this.bgColor = bgColor;
}
public ToolBarManager(int bgColor, int borderStyle) {
super(USE_ALL_WIDTH);
this.bgColor = bgColor;
this.borderStyle = borderStyle;
}
public int getBgColor() {
return bgColor;
}
public void setBgColor(int bgColor) {
this.bgColor = bgColor;
}
public int getBorderColor() {
return borderColor;
}
public void setBorderColor(int borderColor) {
this.borderColor = borderColor;
}
public int getBorderStyle() {
return borderStyle;
}
public void setBorderStyle(int borderStyle) {
this.borderStyle = borderStyle;
}
protected void paint(Graphics graphics) {
super.paint(graphics);
XYEdges padding = new XYEdges(5, 5, 5, 5);
Border roundedBorder = BorderFactory.createRoundedBorder(padding,
borderColor, borderStyle);
this.setBorder(roundedBorder);
Background bg = BackgroundFactory.createSolidBackground(bgColor);
this.setBackground(bg);
}
}
You can force the fields to be displayed in the center by specifying FIELD_HCENTER when creating each field. Or by using FIELD_HCENTER when creating the manager. In the latter case, the manager will be center itself, but each fields in it will be left-adjusted. It is mostly the same end results, but under some conditions it may be displayed differently.
You can go ahead with the positioning of the contents at the center position
for eg:
When i want to place any field at the center of screen then i do
(Display.getWidth()-field.getWidth())/2
You can try positioning like this,if it helps in your case.