How to create a custom drop down in blackberry - blackberry

Can anyone please help me to create a custom drop down similar to the image attached in blackberry 5.0. I have used object choice field but it is coming along with label. Guide me to create custom drop down as show in image below

I have created my customized ChoiceField, using popup Screen. Here is the below code sample
package com.src.java.rim.ui;
import net.rim.device.api.system.Bitmap;
import net.rim.device.api.system.Display;
import net.rim.device.api.ui.DrawStyle;
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.UiApplication;
import net.rim.device.api.ui.XYEdges;
import net.rim.device.api.ui.component.ListField;
import net.rim.device.api.ui.component.ListFieldCallback;
import net.rim.device.api.ui.container.HorizontalFieldManager;
import net.rim.device.api.ui.container.PopupScreen;
import net.rim.device.api.ui.container.VerticalFieldManager;
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 FWCustomChoiceField extends HorizontalFieldManager {
/*space between text and icon*/
final int padding = 10;
String arrowBitmapName = "arrow_state_grey_right.png";
Object choice[] = null;
int index = -1;
String text = "Please select one option";
ListField choiceField = null;
public FWCustomChoiceField(final Object choice[]) {
this.choice = new Object[choice.length];
this.choice = choice;
choiceField = new ListField(){
protected boolean navigationClick(int status, int time) {
Field focus = UiApplication.getUiApplication().getActiveScreen() .getLeafFieldWithFocus();
if (focus instanceof ListField) {
ChoicePopupScreen popup = new ChoicePopupScreen(10, 80, choice);
popup.setChoice(choice);
UiApplication.getUiApplication().pushScreen(popup);
}
return super.navigationClick(status, time);
}
};
choiceField.setSize(1);
choiceField.setCallback(new TestListCallback());
add(choiceField);
}
public void setSelIndex(int index){
this.index = index;
this.text = choice[index].toString();
choiceField.invalidate();
}
public int getSelectedIndex(){
return index;
}
final class TestListCallback implements ListFieldCallback {
TestListCallback() {
}
public void drawListRow(ListField list, Graphics g, int index, int y, int w) {
Bitmap bitmap = Bitmap.getBitmapResource(arrowBitmapName);
int fontWidth = getFont().getAdvance(text);
int width = Display.getWidth() ;
int posX = (width-(fontWidth + padding + bitmap.getWidth()))/2;
int height = list.getRowHeight();
int posY = (height - bitmap.getHeight())/2;
g.drawText(text, posX, y, 0, w);
g.drawBitmap(posX+fontWidth+padding,posY, bitmap.getWidth(), bitmap.getHeight(), bitmap, 0, 0);
}
public Object get(ListField listField, int index) {
return null;
}
public int getPreferredWidth(ListField listField) {
return Graphics.getScreenWidth();
}
public int indexOfList(ListField listField, String prefix, int start) {
return listField.indexOfList(prefix, start);
}
}
public class ChoicePopupScreen extends PopupScreen {
Object []choice = null;
/*holds the position for popup screen*/
private int _posX = 0;
private int _posY = 0;
public ChoicePopupScreen(int posx,int posy, Object[] choice) {
/*calling super class constructor*/
super(new VerticalFieldManager(), Field.FOCUSABLE);
this.setMargin(new XYEdges(1,1,1,1));
this.choice = new Object[choice.length];
this.choice = choice;
/*Setting position for popup screen*/
_posX = posx;
_posY = posy;
/*list field customized to display as choice picker*/
ListField choiceList = new ListField(){
/*list field event handling using navigation click*/
protected boolean navigationClick(int status, int time) {
/*getting the selected list index value*/
int index = this.getSelectedIndex();
/*returning the selected index to the main field*/
setSelIndex(index);
/*removing the popup screen from the screen stack*/
UiApplication.getUiApplication().popScreen(UiApplication.getUiApplication().getActiveScreen());
/*required for event handling*/
return super.navigationClick(status, time);
}
};
/*displays the message when list is empty*/
choiceList.setEmptyString("List is empty", DrawStyle.LEFT);
choiceList.setSize(choice.length);
choiceList.setCallback(new PopUpListCallback());
add(choiceList);
Border border = BorderFactory.createSimpleBorder( new XYEdges(), Border.STYLE_TRANSPARENT);
this.setBorder(border);
}
protected void setChoice(Object []choice) {
this.choice = new Object[choice.length];
this.choice = choice;
}
protected void sublayout(int width, int height) {
super.sublayout(width, height);
/*setting the position for the popup screen*/
setPosition(_posX , _posY);
}
}
private class PopUpListCallback implements ListFieldCallback {
PopUpListCallback() {
}
public void drawListRow(ListField list, Graphics g, int index, int y, int w) {
String text = choice[index].toString();
g.drawText(text, padding, y, 0, w);
}
public Object get(ListField listField, int index) {
return null;
}
public int getPreferredWidth(ListField listField) {
return Graphics.getScreenWidth();
}
public int indexOfList(ListField listField, String prefix, int start) {
return listField.indexOfList(prefix, start);
}
}
}
To use the above class
String choicestrs[] = {"Opt 1", "Opt 2", "Opt 3"};
add(new FWCustomChoiceField(choicestrs));

Related

Setting selected value in editfield?

I have made a custom auto suggest list.
I want to set the selcted value in edit field.
I am using this Place holder text on a AutoCompleteField in blackberry
CustomAutoCompleteField.js
package mypackage;
import net.rim.device.api.collection.util.BasicFilteredList;
import net.rim.device.api.collection.util.BasicFilteredListResult;
import net.rim.device.api.system.Application;
import net.rim.device.api.ui.Color;
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.component.AutoCompleteField;
import net.rim.device.api.ui.component.ListField;
class CustomAutoCompleteField extends AutoCompleteField {
private int yOffset = 0;
private int xOffset = 0;
public CustomAutoCompleteField(BasicFilteredList filteredList) {
super(filteredList);
}
protected void paint(Graphics g) {
super.paint(g);
if (xOffset == 0) {
// initialize text offsets once
xOffset = getEditField().getContentLeft();
yOffset = getEditField().getContentTop();
}
String text = getEditField().getText();
if (text == null || text.length() == 0) {
int oldColor = g.getColor();
g.setColor(Color.GRAY);
g.drawText("enter text", xOffset, yOffset);
g.setColor(oldColor);
}
}
public void onSelect(Object selection, int SELECT_TRACKWHEEL_CLICK) {
ListField _list = getListField();
if (_list.getSelectedIndex() > -1) {
final String selectedText = getEditField().getText();
if(selectedText!=null){
final BasicFilteredListResult result = (BasicFilteredListResult) selection;
Application.getApplication().invokeLater(new Runnable() {
public void run() {
selectedText.setText(result._object.toString());
}
});
// selectedText.setText(result._object.toString());
}
}
}
protected void sublayout(int maxWidth, int maxHeight) {
// TODO Auto-generated method stub
super.sublayout(250, 250);
}
}
myscreen.js
public final class MyScreen extends MainScreen
{
/**
* Creates a new MyScreen object
*/
public MyScreen()
{
// Set the displayed title of the screen
BasicFilteredList filterList = new BasicFilteredList();
String[] days = {"Monday(TAS)","Tuesday-(PAQ)","Wednesday-(MAN)",
"Thursday","Friday","Saturday","Sunday(I_)"};
filterList.addDataSet(1,days,"days",BasicFilteredList.COMPARISON_IGNORE_CASE);
HorizontalFieldManager hr =new HorizontalFieldManager();
LabelField userName= new LabelField("hjsdhas");
hr.add(userName);
CustomAutoCompleteField autoCompleteField = new CustomAutoCompleteField(filterList);
hr.add(autoCompleteField);
add(hr);
}
}
CustomAutoCompleteField.java is my custom java class and I call the class from myscreen.java class

In Listfield not able to view the fields in blackberry

i have tried this link How to customize a ListField in BlackBerry? to create the ListField with Three lablefields for every list row.but iam not able see the list field items.but i can say that listfield is added.because on navigation click i am able get the selected index of the listfield.please anybody help where iam doing mistake.The code i have tried is...
public class InboxWithOutCheckboxeslistfield extends ListField implements ListFieldCallback {
private Vector rows;
private TableRowManager row ;
private LabelField UserName,Message,Timestamp;
/**
* Creates a new MyScreen object
*/
public InboxWithOutCheckboxeslistfield() {
// TODO Auto-generated constructor stub
super(0, ListField.MULTI_SELECT);
setRowHeight(80);
setCallback(this);
rows = new Vector();
for (int x = 0; x < 10; x++) {
row = new TableRowManager();
UserName = new LabelField("" + String.valueOf(x),
DrawStyle.ELLIPSIS | LabelField.USE_ALL_WIDTH
| DrawStyle.LEFT);
UserName.setText("name");
row.add(UserName);
Message = new LabelField("" + String.valueOf(x),
DrawStyle.ELLIPSIS | LabelField.USE_ALL_WIDTH
| DrawStyle.RIGHT);
Message.setText("hai");
row.add(Message);
Timestamp = new LabelField("" + String.valueOf(x),
DrawStyle.ELLIPSIS | LabelField.USE_ALL_WIDTH
| DrawStyle.RIGHT);
Timestamp.setText("hai");
row.add(Timestamp);
rows.addElement(row);
}
setSize(rows.size());
}
public void drawListRow(ListField listField, Graphics graphics, int index,
int y, int width) {
// TODO Auto-generated method stub
InboxWithOutCheckboxeslistfield list = (InboxWithOutCheckboxeslistfield) listField;
TableRowManager rowManager = (TableRowManager) list.rows.elementAt(index);
rowManager.drawRow(graphics, 0, y, width, list.getRowHeight());
}
public Object get(ListField listField, int index) {
// TODO Auto-generated method stub
return null;
}
public int getPreferredWidth(ListField listField) {
// TODO Auto-generated method stub
return 0;
}
public int indexOfList(ListField listField, String prefix, int start) {
// TODO Auto-generated method stub
return 0;
}
private class TableRowManager extends Manager {
protected TableRowManager(){super(0);
// TODO Auto-generated constructor stub}
}
public void drawRow(Graphics graphics, int i, int y, int width,
int rowHeight) {
// TODO Auto-generated method stub
// Arrange the cell fields within this row manager.
layout(width, rowHeight);
// Place this row manager within its enclosing list.
setPosition(i, y);
// Apply a translating/clipping transformation to the graphics
// context so that this row paints in the right area.
graphics.pushRegion(getExtent());
// Paint this manager's controlled fields.
subpaint(graphics);
graphics.setColor(0x00CACACA);
graphics.drawLine(0, 0, getPreferredWidth(), 0);
// Restore the graphics context.
graphics.popContext();
}
protected void sublayout(int width, int height) {
// TODO Auto-generated method stub
// set the size and position of each field.
int fontHeight = Font.getDefault().getHeight();
int preferredWidth = getPreferredWidth();
Field field = getField(0);
layoutChild(field, preferredWidth - 16, fontHeight + 1);
setPositionChild(field, 34, 3);
// set the list name label field
field = getField(1);
layoutChild(field, 150, fontHeight + 1);
setPositionChild(field, 34, fontHeight + 6);
// set the due time name label field
field = getField(2);
layoutChild(field, 150, fontHeight + 1);
setPositionChild(field, preferredWidth - 152, fontHeight + 6);
setExtent(getPreferredWidth(), getPreferredHeight());
}
// The preferred width of a row is defined by the list renderer.
public int getPreferredWidth()
{
return getWidth();
}
// The preferred height of a row is the "row height" as defined in the
// enclosing list.
public int getPreferredHeight()
{
return getHeight();
}
}
protected boolean navigationClick(int status, int time) {
int index1 = getSelectedIndex();
System.out.println("The Clikced item is:"+index1);
return true;
}
}
and the mainscreen class is
public class InboxWithOutCheckboxes extends MainScreen{
private InboxWithOutCheckboxeslistfield inboxWithOutCheckboxeslistfield;
public InboxWithOutCheckboxes(){
super();
inboxWithOutCheckboxeslistfield = new InboxWithOutCheckboxeslistfield();
add(inboxWithOutCheckboxeslistfield);
add(new SeparatorField());
}
}
Try This code -
Add lists on Main Screen-
InboxWithOutCheckboxeslistfield InboxWithOutCheckboxeslistfield = new InboxWithOutCheckboxeslistfield ();
add(InboxWithOutCheckboxeslistfield );
add(new SeparatorField());
Click event listener of list -
protected boolean navigationClick(int status, int time) {
getValue();
return true;
}
protected void getValue() {
Field f = getFieldWithFocus();
if (f instanceof ListField) {
ListField l = (ListField) f;
final int index = l.getSelectedIndex();
FriendsRequestObject _contactslist = (FriendsRequestObject) FriendsRequest_fields.vector.elementAt(index);
final String _name = _contactslist.getSender_name();
final String _id = _contactslist.getSender_id();
//Dialog.alert(_name);
Application.getApplication().invokeLater(new Runnable() {
public void run() {
Dialog.alert(_name);
}
});
// Dialog.alert("The selected element is: "+Integer.toString(l.getSelectedIndex()));
}
}
import java.util.Vector;
import net.rim.device.api.ui.Color;
import net.rim.device.api.ui.DrawStyle;
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.Manager;
import net.rim.device.api.ui.component.LabelField;
import net.rim.device.api.ui.component.ListField;
import net.rim.device.api.ui.component.ListFieldCallback;
class InboxWithOutCheckboxeslistfield extends ListField implements ListFieldCallback {
private Vector contacts;
static Vector vector = new Vector();
private int contactslist_size = 0;
private String name_ = "", id_="", status_="";
public InboxWithOutCheckboxeslistfield () {
super(0, ListField.MULTI_SELECT);
setRowHeight(60);
setEmptyString("Empty List", DrawStyle.HCENTER);
setCallback(this);
contacts = new Vector();
vector.addElement(new FriendsRequestObject("1", "hai1", ""));
vector.addElement(new FriendsRequestObject("2", "hai2", ""));
vector.addElement(new FriendsRequestObject("3", "hai3", ""));
vector.addElement(new FriendsRequestObject("4", "hai4", ""));
contactslist_size = vector.size();
for (int x = 0; x < contactslist_size; x++) {
FriendsRequestObject b = (FriendsRequestObject) vector.elementAt(x);
id_ = b.getSender_id().toString();
name_ = b.getSender_name().toString();
status_ = b.getimage().toString();
TableRowManager row = new TableRowManager() {
public void paint(Graphics g) {
g.setBackgroundColor(Color.BLACK);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(Color.BLACK);
g.clear();
super.paint(g);
}
};
LabelField name1 = new LabelField(id_, DrawStyle.ELLIPSIS);
name1.setFont(Font.getDefault().derive(Font.PLAIN));
row.add(name1);
LabelField name = new LabelField(name_, DrawStyle.ELLIPSIS);
name.setFont(Font.getDefault().derive(Font.PLAIN));
row.add(name);
// add to the table
contacts.addElement(row);
}
setSize(contacts.size());
}
// ListFieldCallback Implementation
public void drawListRow(ListField listField, Graphics g, int index, int y, int width) {
InboxWithOutCheckboxeslistfield list = (InboxWithOutCheckboxeslistfield ) listField;
TableRowManager rowManager = (TableRowManager) list.contacts.elementAt(index);
rowManager.drawRow(g, 0, y, width, list.getRowHeight());
}
private class TableRowManager extends Manager {
public TableRowManager() {
super(0);
}
// Causes the fields within this row manager to be layed out then
// painted.
public void drawRow(Graphics g, int x, int y, int width, int height) {
// Arrange the cell fields within this row manager.
layout(width, height);
// Place this row manager within its enclosing list.
setPosition(x, y);
// Apply a translating/clipping transformation to the graphics
// context so that this row paints in the right area.
g.pushRegion(getExtent());
// Paint this manager's controlled fields.
subpaint(g);
g.setColor(0x00CACACA);
g.drawLine(0, 0, getPreferredWidth(), 0);
// Restore the graphics context.
g.popContext();
}
// Arrages this manager's controlled fields from left to right within
// the enclosing table's columns.
protected void sublayout(int width, int height) {
// set the size and position of each field.
int fontHeight = Font.getDefault().getHeight();
int preferredWidth = getPreferredWidth();
/* positioning of fields in list */
// Status
Field field = getField(0);
layoutChild(field, preferredWidth, 50);
setPositionChild(field, 10, 5);
// Name
field = getField(1);
layoutChild(field, 150, fontHeight + 1);
//setPositionChild(field, 1, 2);
setPositionChild(field, 80, fontHeight );
setExtent(preferredWidth, getPreferredHeight());
}
// The preferred width of a row is defined by the list renderer.
public int getPreferredWidth() {
return Graphics.getScreenWidth();
}
// The preferred height of a row is the "row height" as defined in the
// enclosing list.
public int getPreferredHeight() {
return getRowHeight();
}
}
public Object get(ListField listField, int index) {
return null;
}
public int getPreferredWidth(ListField listField) {
return 0;
}
public int indexOfList(ListField listField, String prefix, int start) {
return 0;
}
}
FriendsRequestObject is given below -
public class FriendsRequestObject {
private String sender_id;
private String sender_name;
private String image;
public FriendsRequestObject(String sender_id, String sender_name, String image){
this.sender_id = sender_id;
this.sender_name =sender_name;
this.image =image;
}
public String getimage() {
return image;
}
public void setimage(String image) {
this.image = image;
}
public String getSender_id() {
return sender_id;
}
public void setSender_id(String sender_id) {
this.sender_id = sender_id;
}
public String getSender_name() {
return sender_name;
}
public void setSender_name(String sender_name) {
this.sender_name = sender_name;
}
}
Edit your implementation of TableRowManager. You need to change the getPreferredWidth(), and getPreferredHeight(). getWidth() and getHeight() will return wrong value if the sublayout() method execution doesn't finish earlier.
// The preferred width of a row is defined by the list renderer.
public int getPreferredWidth() {
return Display.getWidth();
}
// The preferred height of a row is the "row height" as defined in the
// enclosing list.
public int getPreferredHeight() {
return getRowHeight();
}

Blackberry: how to filter rows represented by a ListField?

I'm trying to create an app displaying few extra rows on the top of a list of items with a "live search" field on the top:
Of course I've tried using a KeywordFilterField with overriden setSize() for that at first. But this didn't work well - because I couldn't control, when and how setSize() was called by the KeywordFilterField and this has given me drawing issues (a row was not drawn when I had a keyword entered and added a new item to the list, etc.)
So I am trying to "go back to the roots" and use a ListField (and a BasicEditField on the top) this time, because there I can control myself, when and how setSize() is called.
Below is my simplified test code - src\mypackage\MyList.java and border.png.
The code works well, except for the filtering issue - which I will describe below.
package mypackage;
import java.util.*;
import net.rim.device.api.collection.*;
import net.rim.device.api.collection.util.*;
import net.rim.device.api.system.*;
import net.rim.device.api.ui.*;
import net.rim.device.api.ui.component.*;
import net.rim.device.api.ui.container.*;
import net.rim.device.api.ui.decor.*;
import net.rim.device.api.util.*;
public class MyList extends UiApplication {
public static void main(String args[]) {
MyList app = new MyList();
app.enterEventDispatcher();
}
public MyList() {
pushScreen(new MyScreen());
}
}
class MyScreen extends MainScreen {
static final int EXTRA_ROWS = 3;
BasicFilteredList myFilter = new BasicFilteredList();
Background myBg = BackgroundFactory.createSolidBackground(0x111111);
StringProvider myProvider = new StringProvider("Search");
BasicEditField myFind = new BasicEditField(USE_ALL_WIDTH) {
protected void paint(Graphics g) {
if (getTextLength() == 0) {
g.setColor(Color.LIGHTGRAY);
g.drawText(myProvider.toString(), 0, 0);
}
g.setColor(Color.BLACK);
super.paint(g);
}
};
MyItemList myItems = new MyItemList();
// add 1 row for the "* Empty *" string
ListField myList = new ListField(EXTRA_ROWS + 1) {
protected boolean navigationClick(int status, int time) {
int index = getSelectedIndex();
if (index >= EXTRA_ROWS && myItems.size() > 0) {
String str = ((MyItem) myItems.getAt(
index - EXTRA_ROWS)).toString();
Status.show("You have clicked - " + str);
}
return true;
}
};
Border myBorder = BorderFactory.createBitmapBorder(
new XYEdges(12, 12, 12, 12),
Bitmap.getBitmapResource("border.png"));
public MyScreen() {
getMainManager().setBackground(myBg);
myFind.setBorder(myBorder);
setTitle(myFind);
myItems.doAdd(new MyItem(1, "Eins"));
myItems.doAdd(new MyItem(2, "Zwei"));
myItems.doAdd(new MyItem(3, "Drei"));
myItems.doAdd(new MyItem(4, "Vier"));
myList.setCallback(new MyListFieldCallback());
add(myList);
myFilter.addDataSet(1, myItems.getElements(), "Test",
BasicFilteredList.COMPARISON_IGNORE_CASE);
}
protected boolean keyChar(char key, int status, int time) {
if (key == Characters.BACKSPACE && myFind.getTextLength() == 0) {
Status.show("Kill kill kill!");
return true;
}
if (myFind.getTextLength() > 0) {
System.err.println("XXX filter for " + myFind.getText());
}
return super.keyChar(key, status, time);
}
private class MyListFieldCallback implements ListFieldCallback {
public void drawListRow(ListField list, Graphics g, int index, int y, int width) {
Font i = getFont().derive(Font.ITALIC);
g.setColor(Color.DIMGRAY);
g.drawLine(0, y-9, width, y-9);
g.setColor(Color.WHITE);
if (index < EXTRA_ROWS) {
g.setFont(i);
g.drawText("Add Item", 0, y, DrawStyle.ELLIPSIS|DrawStyle.HCENTER, width);
return;
}
if (myItems.size() == 0) {
g.setFont(i);
g.drawText(list.getEmptyString(), 0, y, DrawStyle.ELLIPSIS|DrawStyle.HCENTER, width);
return;
}
MyItem item = (MyItem) myItems.getAt(index - EXTRA_ROWS);
g.drawText(item.toString(), 0, y, DrawStyle.ELLIPSIS|DrawStyle.HCENTER, width);
}
public Object get(ListField list, int index) {
return myItems.getAt(index);
}
public int getPreferredWidth(ListField list) {
return Display.getWidth();
}
public int indexOfList(ListField list, String prefix, int start) {
return 0;
}
}
class MyItemList extends SortedReadableList {
public MyItemList() {
super(new MyItem.MyComparator());
}
protected void doAdd(Object obj) {
super.doAdd(obj);
myList.setSize(size() + EXTRA_ROWS);
}
protected boolean doRemove(Object obj) {
// if the list is empty, add 1 row for "* Empty *" string
int size = (size() == 0 ? EXTRA_ROWS + 1 : size() - 1 + EXTRA_ROWS);
myList.setSize(size);
return super.doRemove(obj);
}
protected Object[] getElements() {
return super.getElements();
}
}
}
class MyItem {
int _num;
String _name;
public MyItem(int num, String name) {
_num = num;
_name = name;
}
public String toString() {
return _num + ": " + _name;
}
static class MyComparator implements Comparator {
public int compare(Object obj1, Object obj2) {
MyItem item1 = (MyItem) obj1;
MyItem item2 = (MyItem) obj2;
return item1.toString().compareTo(item2.toString());
}
}
static class MyProvider implements KeywordProvider {
public String[] getKeywords(Object obj) {
MyItem item = (MyItem) obj;
return new String[]{ Integer.toString(item._num), item._name };
}
}
}
My problem is that I do not know how to add filtering.
For example when a user enters "E" into myFind, my code will detect this event in the keyChar() and also I understand, that I will have to call myList.setSize(EXTRA_ROWS + 1) because there will be 1 filtered result.
But how do I filter the items displayed by myList, how to implement this?
Maybe I could use BasicFilteredList and its method
public void addDataSet(int id,
Object[] objects,
String name,
long style)
but I'm not sure how to apply it here?
UPDATE:
I've added a BasicFilteredList to my test code above, but am still not sure how to marry it with a ListField.
You have to do the filtering in code somewhere, and then store the result. Override myFind.update(int) to run the filtering when the filtering text changes. In addition to myItems, you need to store myFilteredItems. After filtering, call setSize() on the listfield. The listfield drawing code also needs to draw from the filtered collection. Then you should be set.
I've ended up with this code which seems to work well for me (except 2 minor issues listed below) and the green answer mark goes to Michael Donohue for his valuable suggestions.
I use 2 Vectors: myData and myFilteredData. And for UI I use a ListField and a BasicEditField:
border.png:
src\mypackage\MyList.java:
package mypackage;
import java.util.*;
import net.rim.device.api.collection.*;
import net.rim.device.api.collection.util.*;
import net.rim.device.api.system.*;
import net.rim.device.api.ui.*;
import net.rim.device.api.ui.component.*;
import net.rim.device.api.ui.container.*;
import net.rim.device.api.ui.decor.*;
import net.rim.device.api.util.*;
public class MyList extends UiApplication {
public static void main(String args[]) {
MyList app = new MyList();
app.enterEventDispatcher();
}
public MyList() {
pushScreen(new MyScreen());
}
}
class MyScreen extends MainScreen {
static final int EXTRA_ROWS = 3;
Background myBg = BackgroundFactory.createSolidBackground(0x111111);
StringProvider myProvider = new StringProvider("Search");
BasicEditField myFind = new BasicEditField(USE_ALL_WIDTH|TextField.NO_NEWLINE) {
protected void paint(Graphics g) {
if (getTextLength() == 0) {
g.setColor(Color.LIGHTGRAY);
g.drawText(myProvider.toString(), 0, 0);
}
g.setColor(Color.BLACK);
super.paint(g);
}
protected void update(int delta) {
filterData(getText());
}
};
Vector myData = new Vector();
final static SimpleSortingVector myFilteredData = new SimpleSortingVector();
// add 1 row for the "* Empty *" string
ListField myList = new ListField(EXTRA_ROWS + 1) {
protected boolean navigationClick(int status, int time) {
int index = getSelectedIndex();
if (index >= EXTRA_ROWS && myFilteredData.size() > 0) {
String str = ((MyItem) myFilteredData.elementAt(index - EXTRA_ROWS)).toString();
Status.show("You have clicked - " + str);
}
return true;
}
};
Border myBorder = BorderFactory.createBitmapBorder(
new XYEdges(12, 12, 12, 12),
Bitmap.getBitmapResource("border.png"));
public MyScreen() {
getMainManager().setBackground(myBg);
myFind.setBorder(myBorder);
setTitle(myFind);
myData.addElement(new MyItem(1, "Eins"));
myData.addElement(new MyItem(2, "Zwei"));
myData.addElement(new MyItem(3, "Drei"));
myData.addElement(new MyItem(4, "Vier"));
myFilteredData.setSortComparator(new MyItem.MyComparator());
filterData("");
myList.setCallback(new MyListFieldCallback());
add(myList);
}
private void filterData(String prefix) {
myFilteredData.removeAllElements();
if (prefix == null || prefix.length() == 0) {
// no prefix specified - copy everything
for (int i = myData.size() - 1; i >= 0; i--) {
MyItem item = (MyItem) myData.elementAt(i);
myFilteredData.addElement(item);
}
} else {
// copy only strings starting with prefix
for (int i = myData.size() - 1; i >= 0; i--) {
MyItem item = (MyItem) myData.elementAt(i);
String name = item.name.toLowerCase();
if (name.startsWith(prefix.toLowerCase())) {
myFilteredData.addElement(item);
}
}
}
myFilteredData.reSort();
// if the list is empty, add 1 row for "* Empty *" string
int size = (myFilteredData.size() == 0 ? EXTRA_ROWS + 1 : myFilteredData.size() + EXTRA_ROWS);
myList.setSize(size);
}
protected boolean keyChar(char key, int status, int time) {
if (key == Characters.BACKSPACE && myFind.getTextLength() == 0) {
int index = myList.getSelectedIndex();
if (index >= EXTRA_ROWS && myFilteredData.size() > 0) {
String str = ((MyItem) myFilteredData.elementAt(index - EXTRA_ROWS)).toString();
Status.show("You're deleting - " + str);
}
return true;
}
return super.keyChar(key, status, time);
}
static class MyListFieldCallback implements ListFieldCallback {
public void drawListRow(ListField list, Graphics g, int index, int y, int width) {
Font i = g.getFont().derive(Font.ITALIC);
g.setColor(Color.DIMGRAY);
g.drawLine(0, y-9, width, y-9);
g.setColor(Color.WHITE);
if (index < EXTRA_ROWS) {
g.setFont(i);
g.drawText("Add Item", 0, y, DrawStyle.ELLIPSIS|DrawStyle.HCENTER, width);
return;
}
if (myFilteredData.size() == 0) {
g.setFont(i);
g.drawText(list.getEmptyString(), 0, y, DrawStyle.ELLIPSIS|DrawStyle.HCENTER, width);
return;
}
MyItem item = (MyItem) myFilteredData.elementAt(index - EXTRA_ROWS);
g.drawText(item.toString(), 0, y, DrawStyle.ELLIPSIS|DrawStyle.HCENTER, width);
}
public Object get(ListField list, int index) {
return myFilteredData.elementAt(index);
}
public int getPreferredWidth(ListField list) {
return Display.getWidth();
}
public int indexOfList(ListField list, String prefix, int start) {
return myFilteredData.indexOf(prefix, start);
}
}
}
class MyItem {
int num;
String name;
public MyItem(int num, String name) {
this.num = num;
this.name = name;
}
public String toString() {
return num + ": " + name;
}
static class MyComparator implements Comparator {
public int compare(Object obj1, Object obj2) {
MyItem item1 = (MyItem) obj1;
MyItem item2 = (MyItem) obj2;
String name1 = item1.toString().toLowerCase();
String name2 = item2.toString().toLowerCase();
return name1.compareTo(name2);
}
}
}
My minor problems are:
Why do I need to subtract 9 in drawListRow() to draw the lines?
Why does the caret disappear in BasicEditField after using it?

Displaying extra rows in a ListField

I'm trying to display an extra row at the top of a ListField - called "Add Item" and it almost works, but the very last row "Item 4" of my data is not displayed.
How would you fix this issue?
Please see my very simple test code MyList.java below:
package mypackage;
import java.util.*;
import net.rim.device.api.collection.*;
import net.rim.device.api.collection.util.*;
import net.rim.device.api.system.*;
import net.rim.device.api.ui.*;
import net.rim.device.api.ui.component.*;
import net.rim.device.api.ui.container.*;
import net.rim.device.api.ui.decor.*;
import net.rim.device.api.util.*;
public class MyList extends UiApplication {
public static void main(String args[]) {
MyList app = new MyList();
app.enterEventDispatcher();
}
public MyList() {
pushScreen(new MyScreen());
}
}
class MyScreen extends MainScreen {
ObjectListField myList = new ObjectListField() {
public void drawListRow(ListField list,
Graphics g,
int index,
int y,
int width) {
if (index == 0) {
Font i = getFont().derive(Font.ITALIC);
g.setFont(i);
g.drawText("Add Item", 0, y);
} else {
String str = (String) get(this, index - 1);
g.drawText(str, 0, y);
}
}
protected boolean navigationClick(int status, int time) {
int index = myList.getSelectedIndex();
String str = (index > 0 ? (String) get(this, index - 1) :
"Add item");
Status.show("You have clicked: " + str);
return true;
}
};
public MyScreen() {
setTitle("How to display an extra row?");
myList.set(new String[]{"Item 1","Item 2","Item 3","Item 4",});
// myList.setSize(5);
add(myList);
}
}
I've tried adding myList.setSize(5); but get an ArrayIndexOutOfBoundsException thrown by Vector.elementAt(4)
UPDATE:
On Michael's suggestion I've switched from ObjectListField to KeywordFilterField (which is what I actually use in my real program) and now I can call myList.setSize(5) without any exception being thrown.
But the last row is still not displayed:
package mypackage;
import java.util.*;
import net.rim.device.api.collection.*;
import net.rim.device.api.collection.util.*;
import net.rim.device.api.system.*;
import net.rim.device.api.ui.*;
import net.rim.device.api.ui.component.*;
import net.rim.device.api.ui.container.*;
import net.rim.device.api.ui.decor.*;
import net.rim.device.api.util.*;
public class MyList extends UiApplication {
public static void main(String args[]) {
MyList app = new MyList();
app.enterEventDispatcher();
}
public MyList() {
pushScreen(new MyScreen());
}
}
class MyScreen extends MainScreen {
static final int EXTRA_ROWS = 1;
MyItemList myItems = new MyItemList();
KeywordFilterField myList = new KeywordFilterField() {
protected boolean navigationClick(int status, int time) {
int index = getSelectedIndex();
String str = (index < EXTRA_ROWS ? "Add item" :
((MyItem) getElementAt(index - EXTRA_ROWS)).toString());
Status.show("You have clicked - " + str);
return true;
}
};
public MyScreen() {
setTitle(myList.getKeywordField());
myList.setSourceList(myItems, new MyItem.MyProvider());
myItems.doAdd(new MyItem(1, "Eins"));
myItems.doAdd(new MyItem(2, "Zwei"));
myItems.doAdd(new MyItem(3, "Drei"));
myItems.doAdd(new MyItem(4, "Vier"));
myList.setSourceList(myItems, new MyItem.MyProvider());
myList.setCallback(new MyListFieldCallback());
myList.setSize(myItems.size() + EXTRA_ROWS);
myList.updateList();
add(myList);
}
private class MyListFieldCallback implements ListFieldCallback {
public void drawListRow(ListField list, Graphics g, int index, int y, int width) {
if (index < EXTRA_ROWS) {
Font i = getFont().derive(Font.ITALIC);
g.setFont(i);
g.drawText("Add Item", 0, y);
return;
}
if (index >= EXTRA_ROWS) {
MyItem item = (MyItem) ((KeywordFilterField) list).getElementAt(index - EXTRA_ROWS);
g.drawText(item.toString(), 0, y);
return;
}
g.drawText(list.getEmptyString(), 0, y);
}
public Object get(ListField listField, int index) {
return null;
}
public int getPreferredWidth(ListField listField) {
return 0;
}
public int indexOfList(ListField listField, String prefix, int start) {
return 0;
}
}
}
class MyItemList extends SortedReadableList {
public MyItemList() {
super(new MyItem.MyComparator());
}
protected void doAdd(Object obj) {
super.doAdd(obj);
}
protected boolean doRemove(Object obj) {
return super.doRemove(obj);
}
}
class MyItem {
int _num;
String _name;
public MyItem(int num, String name) {
_num = num;
_name = name;
}
public String toString() {
return _num + ": " + _name;
}
static class MyComparator implements Comparator {
public int compare(Object obj1, Object obj2) {
MyItem item1 = (MyItem) obj1;
MyItem item2 = (MyItem) obj2;
return item1.toString().compareTo(item2.toString());
}
}
static class MyProvider implements KeywordProvider {
public String[] getKeywords(Object obj) {
MyItem item = (MyItem) obj;
return new String[]{ Integer.toString(item._num), item._name };
}
}
}
I have a feeling, that setSize(4) (instead of 5) is called inbetween - because I see the last row for a moment and then it disappears again.
Thank you!
Alex
You don't want to use an ObjectListField, go up one level in the type hierarchy to ListField, and then you can do setSize() as you please.
I guess this should work:
public MyScreen() {
setTitle("How to display an extra row?");
myList.set(new String[] { "Add Item", "Item 1","Item 2","Item 3","Item 4"});
add(myList);
}
Or am I missing smth? :)
Here is my own solution - override the setSize() of the ListField:
(the screenshot above has EXTRA_ROWS = 3, which still works ok).
package mypackage;
import java.util.*;
import net.rim.device.api.collection.*;
import net.rim.device.api.collection.util.*;
import net.rim.device.api.system.*;
import net.rim.device.api.ui.*;
import net.rim.device.api.ui.component.*;
import net.rim.device.api.ui.container.*;
import net.rim.device.api.ui.decor.*;
import net.rim.device.api.util.*;
public class MyList extends UiApplication {
public static void main(String args[]) {
MyList app = new MyList();
app.enterEventDispatcher();
}
public MyList() {
pushScreen(new MyScreen());
}
}
class MyScreen extends MainScreen {
static final int EXTRA_ROWS = 3;
MyItemList myItems = new MyItemList();
KeywordFilterField myList = new KeywordFilterField() {
protected boolean navigationClick(int status, int time) {
int index = getSelectedIndex();
String str = (index < EXTRA_ROWS ? "Add item" :
((MyItem) getElementAt(index - EXTRA_ROWS)).toString());
Status.show("You have clicked - " + str);
return true;
}
public void setSize(int count) {
super.setSize(count + EXTRA_ROWS);
}
};
public MyScreen() {
setTitle(myList.getKeywordField());
myList.setSourceList(myItems, new MyItem.MyProvider());
myItems.doAdd(new MyItem(1, "Eins"));
myItems.doAdd(new MyItem(2, "Zwei"));
myItems.doAdd(new MyItem(3, "Drei"));
myItems.doAdd(new MyItem(4, "Vier"));
myList.setSourceList(myItems, new MyItem.MyProvider());
myList.setCallback(new MyListFieldCallback());
add(myList);
}
private class MyListFieldCallback implements ListFieldCallback {
public void drawListRow(ListField list, Graphics g, int index, int y, int width) {
if (index < EXTRA_ROWS) {
Font i = getFont().derive(Font.ITALIC);
g.setFont(i);
g.drawText("Add Item", 0, y);
return;
}
if (index >= EXTRA_ROWS) {
MyItem item = (MyItem) ((KeywordFilterField) list).getElementAt(index - EXTRA_ROWS);
g.drawText(item.toString(), 0, y);
return;
}
g.drawText(list.getEmptyString(), 0, y);
}
public Object get(ListField listField, int index) {
return null;
}
public int getPreferredWidth(ListField listField) {
return 0;
}
public int indexOfList(ListField listField, String prefix, int start) {
return 0;
}
}
}
class MyItemList extends SortedReadableList {
public MyItemList() {
super(new MyItem.MyComparator());
}
protected void doAdd(Object obj) {
super.doAdd(obj);
}
protected boolean doRemove(Object obj) {
return super.doRemove(obj);
}
}
class MyItem {
int _num;
String _name;
public MyItem(int num, String name) {
_num = num;
_name = name;
}
public String toString() {
return _num + ": " + _name;
}
static class MyComparator implements Comparator {
public int compare(Object obj1, Object obj2) {
MyItem item1 = (MyItem) obj1;
MyItem item2 = (MyItem) obj2;
return item1.toString().compareTo(item2.toString());
}
}
static class MyProvider implements KeywordProvider {
public String[] getKeywords(Object obj) {
MyItem item = (MyItem) obj;
return new String[]{ Integer.toString(item._num), item._name };
}
}
}

Add A ticker to Blackberry Display

im new to blackberry,So
Please give a blackberry code for adding ticker to blackberry display bottom part of the disply ??
Need Only for how to Create a Ticker.??
Thank you
try this
import java.util.Timer;
import java.util.TimerTask;
import net.rim.device.api.system.Display;
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.Font;
import net.rim.device.api.ui.Graphics;
public class Ticker extends Field {
String text;
final int screenWidth = Display.getWidth();
int offset = screenWidth;
Timer timer = new Timer();
final int delay = 30;
public void setText(String text) {
this.text = text;
}
public String getText() {
return text;
}
Ticker(String text) {
this.text = text;
final int width = Font.getDefault().getAdvance(text);
TimerTask timerTask = new TimerTask() {
public void run() {
offset--;
if (offset + width == 0) {
offset = screenWidth;
}
invalidate();
}
};
timer.scheduleAtFixedRate(timerTask, delay, delay);
}
protected void layout(int width, int height) {
int w = Display.getWidth();
int h = Font.getDefault().getHeight();
setExtent(w, h);
}
protected void paint(Graphics graphics) {
graphics.drawText(text, offset, 0);
}
}

Resources