Blackberry displaying list in alphabetical oreder - blackberry

The code below is for saving friends list from facebook.
Profile[] f=user.getFriends();
for(int i=0;i<f.length;i++){
String id=f[i].getId();
String name=f[i].getName();
vector.addElement(new FriendsRequestObject(id,name));
}
Now i want to display the friends list with checkboxes.
VerticalFieldManager vfm=new VerticalFieldManager(Manager.VERTICAL_SCROLL | Manager.VERTICAL_SCROLLBAR);
boolean checked = false;
for(int i=0;i<vector.size();i++){
FriendsRequestObject co_vec = (FriendsRequestObject)vector.elementAt(i);
String name=co_vec.getSender_name();
String id=co_vec.getSender_id();
box = new CheckboxField(" "+name , checked, Field.USE_ALL_WIDTH){
public void paint(Graphics graphics) {
graphics.setColor(Color.WHITE);
super.paint(graphics);
}
};
box1.addElement(box);
// box.setMargin(6, 0, 0, 4);
vfm.add(box);
}
vfmMiddle.add(vfm);
How to arrange the List in Alphabetical order ?.

A simple way would be to use a SimpleSortingVector instead of a Vector, define and set the Comparitor you want to establish the desired order.
For an example have a look here.

Related

How to create a number of Fields dynamically in Blackberry Java SDK 5.0?

I'm trying to create a couple of BasicEditField objects after i get the number of fields that i want from an ObjectChoiceField.
Problem: the BasicEditField fields that i add to my screen don't refresh unless i do it in the listener from my ObjectChoiceField.
what i want to do :
select the number of BasicEditFields that i want.
refresh the screen so the fields added appear.
PD: if you need more info, just tell me, and sorry about my english. I'm new at developing for the BlackBerry plataform
public final class MyScreen extends MainScreen
{
private int fields_lenght;
public MyScreen()
{
// Set the displayed title of the screen
setTitle("Example");
fields_lenght =0;
final String shortcodes[] = {"1","2","3"};
final ObjectChoiceField dropdownlist=new ObjectChoiceField("Select a number of fields",shortcodes);
this.add(dropdownlist);
dropdownlist.setChangeListener( new FieldChangeListener() {
public void fieldChanged( Field arg0, int arg1 ) {
if(arg1 != PROGRAMMATIC){
fields_lenght= Integer.parseInt(shortcodes[dropdownlist.getSelectedIndex()]);
}
}
} );
// how to refresh the screen with the new fields ???
BasicEditField fields[]=new BasicEditField [fields_lenght] ;
for(int i = 0; i<fields.length;i++){
fields[i]=new BasicEditField("Campo "+i,"");
this.add(fields[i]);
}
}
}
You really should add or delete the fields from within your ObjectChoiceField listener. That's when you know what the proper number of fields is. (Certainly, if you just want to keep your code neat and clean, you could define a separate method, that is called from the choice field listener ... that's not much different).
Try something like this:
public final class MyScreen extends MainScreen {
/** A cached vector of the BasicEditFields, to make deleting easier */
private Vector fields;
public MyScreen() {
super(MainScreen.VERTICAL_SCROLL | MainScreen.VERTICAL_SCROLLBAR);
setTitle("Example");
final String shortcodes[] = {"1","2","3"};
final ObjectChoiceField dropdownlist = new ObjectChoiceField("Select a number of fields", shortcodes);
add(dropdownlist);
fields = new Vector();
final Screen screen = this;
dropdownlist.setChangeListener( new FieldChangeListener() {
public void fieldChanged( Field field, int context ) {
if (context != PROGRAMMATIC) {
// how many fields has the user chosen?
int fieldsLength = Integer.parseInt(shortcodes[dropdownlist.getSelectedIndex()]);
while (fieldsLength > fields.size()) {
// we need to ADD more fields
Field f = new BasicEditField("Campo " + fields.size(), "");
fields.addElement(f);
screen.add(f);
}
while (fieldsLength < fields.size()) {
// we need to DELETE some fields
Field f = (Field)fields.elementAt(fields.size() - 1);
fields.removeElement(f);
screen.delete(f);
}
}
}
});
}
I defined a new member named fields, which just makes it easier to keep track of the basic edit fields (in case this screen has many other fields, too).
When the choice field listener is called, I determine how many fields the user wants; if they need more, I add them to the screen, and to the fields Vector. If they want fewer, I delete some fields from the end of the Vector, and remove them from the Screen.
Note: there should be no need to call invalidate() here. Calling Screen#add() or Screen#delete() should add/delete the fields and cause repainting.

List field in blackberry , event click listener not working

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+"");
}
});

Blackberry: Drawing TableModel focus properly

I need help with drawing the focus of the selected row properly.
Currently if I select the first item of a category the separatorrow gets highlighted too. So how can I implement my custom focus drawing so that only the selected row gets focused/highlighted?
I am using the posted source code from here: Blackberry Tablemodel gets messed up when scrolling
I am using the Eclipse IDE from RIM and JRE 7.0.0
public class ProductsScreen extends MainScreen
{
private TableModel _tableModel;
private static final int ROW_HEIGHT = 40;
public ProductsScreen(MainCategory mc)
{
super(Manager.NO_VERTICAL_SCROLL | Manager.HORIZONTAL_SCROLL);
DBManager dbman = DBManager.getInstance();
AllProductByCategory[] products = null;
try {
products = dbman.getProducts(mc.getID().intValue());
} catch (DatabaseException e) {
System.out.println(e.getMessage());
e.printStackTrace();
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
setTitle(mc.getName());
_tableModel = new TableModel();//(StringComparator.getInstance(true), 0);
if(products != null)
{
for(int i = 0; i < products.length; i++)
{
ViewableData[] data = products[i].getData().getViewableData();
for(int j = 0; j < data.length; j++)
{
_tableModel.addRow(new Object[] {products[i].getCategoryName(), data[j].getTitle2()});
}
}
}
RegionStyles style = new RegionStyles(BorderFactory.createSimpleBorder(new XYEdges(1, 1, 1, 1), Border.STYLE_SOLID), null, null,
null, RegionStyles.ALIGN_LEFT, RegionStyles.ALIGN_TOP);
TableView tableView = new TableView(_tableModel);
final TableController tableController = new TableController(_tableModel, tableView);
tableController.setFocusPolicy(TableController.ROW_FOCUS);
tableController.setCommand(new Command(new CommandHandler()
{
public void execute(ReadOnlyCommandMetadata metadata, Object context)
{
}
}));
tableView.setController(tableController);
DataTemplate dataTemplate = new DataTemplate(tableView, 2, 2)
{
public Field[] getDataFields(int modelRowIndex)
{
final Object[] data = (Object[]) _tableModel.getRow(modelRowIndex);
Field[] fields = new Field[3];
String rowGroup = (String)data[0];
// we're in a new group if this is the very first row, or if this row's
// data[0] value is different from the last row's data[0] value
boolean isNewGroup = (modelRowIndex == 0) ||
(rowGroup.compareTo((String) ((Object[])_tableModel.getRow(modelRowIndex - 1))[0]) != 0);
if (isNewGroup) {
// make a separator row
fields[0] = new HeaderField((String)data[0],
Field.USE_ALL_WIDTH | Field.NON_FOCUSABLE);
} else {
// this is in the same group as the last product, so don't add anything here
fields[0] = new NullField();
}
// now, add the actual product information
fields[1] = new LabelField((String)data[1],
Field.USE_ALL_WIDTH | Field.FOCUSABLE | Field.USE_ALL_HEIGHT | DrawStyle.ELLIPSIS);
fields[2] = new BitmapField(Bitmap.getBitmapResource("img/bullet_arrow_right.png"));
return fields;
}
};
dataTemplate.createRegion(new XYRect(0, 0, 2, 1)); // group separator (maybe a null field)
dataTemplate.createRegion(new XYRect(0, 1, 1, 1)); // actual rows with product information
dataTemplate.createRegion(new XYRect(1, 1, 1, 1));
dataTemplate.setColumnProperties(0, new TemplateColumnProperties(95, TemplateColumnProperties.PERCENTAGE_WIDTH));
dataTemplate.setColumnProperties(1, new TemplateColumnProperties(5, TemplateColumnProperties.PERCENTAGE_WIDTH));
dataTemplate.setRowProperties(0, new TemplateRowProperties(ROW_HEIGHT)); // separator
dataTemplate.setRowProperties(1, new TemplateRowProperties(ROW_HEIGHT)); // product data
dataTemplate.useFixedHeight(false);
tableView.setDataTemplate(dataTemplate);
add(tableView);
}
}
SOLUTION:
I was able to solve the problem on my own with the following approach.
I just added a overridden LabelField as headerfield and didn't implement its focus drawing. So only the "subfields" get the focus drawn.
Maybe some people would implement it in another way (take a look at the answer from Nate) but it worked for me.
So, I didn't have time to fully integrate your new code sample, which has data model code that I don't have, and which appears to have added a DataTemplate column for a BitmapField. Hopefully, you can adapt what I have to reintegrate those changes.
I'm sure there's more than one way to do this, and I'm not claiming this method to be the highest performance. However, it seems to draw the focus as you would expect, without the separator row getting highlighted when the row directly under it is focused.
What I did was abandon the concept of using multiple regions, and just made my data template 1 row by 1 column. If you want, you can probably make it 1 row by 2 columns, where the column I don't show is the BitmapField.
But, what I did was to place a VerticalFieldManager in the first row in each new group/category. That VerticalFieldManager then contained a separator/header row, a separator field (just a horizontal line), and then the actual product row. If the row was not the first in the group/category, I would just return a simple Field, not a VerticalFieldManager with three Field objects inside it.
Then, I changed the TableController focus policy to FIELD_FOCUS, not ROW_FOCUS. This allows focus to be taken by the VerticalFieldManager, when we're on the first row in a new group/category. However, inside that manager, only the actual product row is focusable. The separator row is not focusable, and will therefore not be drawn with focus.
Here's the code that changed. The rest is the same as in the previous sample I gave you:
_tableController.setFocusPolicy(TableController.FIELD_FOCUS);
_tableView.setController(_tableController);
DataTemplate dataTemplate = new DataTemplate(_tableView, 1, 1) // 1 row now!
{
public Field[] getDataFields(int modelRowIndex)
{
final Object[] data = (Object[]) _tableModel.getRow(modelRowIndex);
String rowGroup = (String)data[0];
// we're in a new group if this is the very first row, or if this row's data[0] value is
// different from the last row's data[0] value
boolean isNewGroup = (modelRowIndex == 0) ||
(rowGroup.compareTo((String) ((Object[])_tableModel.getRow(modelRowIndex - 1))[0]) != 0);
if (isNewGroup) {
LabelField header = new LabelField((String)data[0], Field.USE_ALL_WIDTH | Field.NON_FOCUSABLE);
SeparatorField line = new SeparatorField(Field.USE_ALL_WIDTH) {
public void paint(Graphics g) {
g.setColor(Color.BLACK);
super.paint(g);
}
};
LabelField productRow = new LabelField((String)data[1],
Field.USE_ALL_WIDTH | Field.FOCUSABLE | DrawStyle.HCENTER);
VerticalFieldManager manager = new VerticalFieldManager(Field.USE_ALL_WIDTH | Field.FOCUSABLE |
Manager.NO_VERTICAL_SCROLL | Manager.NO_VERTICAL_SCROLLBAR);
manager.add(header);
manager.add(line);
manager.add(productRow);
return new Field[] { manager };
} else {
return new Field[] { new LabelField((String)data[1],
Field.USE_ALL_WIDTH | Field.FOCUSABLE | DrawStyle.HCENTER) };
}
}
};
// create just one region, with one row and one full-width column
dataTemplate.createRegion(new XYRect(0, 0, 1, 1), _style); // may be a product row, or a product row + separator
dataTemplate.setColumnProperties(0, new TemplateColumnProperties(100, TemplateColumnProperties.PERCENTAGE_WIDTH));
dataTemplate.setRowProperties(0, new TemplateRowProperties(2 * ROW_HEIGHT)); // max height if row + separator
_tableView.setDataTemplate(dataTemplate);
dataTemplate.useFixedHeight(false);
The scrolling is a little funny when you get down to the bottom of the page, but I'm pretty sure I've built VerticalFieldManager subclasses before that acted like lists, that needed some custom scroll handling ... if I get some time tomorrow, I'll try to add that in.
One step at a time, though ...

Editfield scroll fails to reach top in blackberry

I am having 2 EditFields in my login form with names Email: and Password:. Just below email I have login button. Suppose I come down till login, I can scroll back only till password field.The cursor fails to reach Email field. In simulator, I tried using arrow keys as well as trackpad. Please help how to scroll back to first editfield
AbsoluteFieldManager ab = new AbsoluteFieldManager();
add(ab);
new SeparatorField();
et=new EditField("Email-id:","");
pwd=new PasswordEditField("Password:","");
ab.add(et,35,110);
ab.add(pwd,35,150);
I am using AbsoluteFieldManager and developing for OS 6.0. I want the loginscreen to look like facebook login page.
Kindly let me know what can possibly be the reason for not able to scroll up
Maybe it is a RIM bug with the AbsoluteFieldManager. Never used it before so I don't know about it. You can create a work around to solve this problem. Find it below:
et=new EditField("Email-id:","");
pwd=new PasswordEditField("Password:","") {
protected int moveFocus(int amount, int status, int time) {
int cursorPosition = this.getCursorPosition();
if ((cursorPosition == 0) && (amount < 0)) {
et.setFocus();
return 0;
}
else {
return super.moveFocus(amount, status, time);
}
}
};
In this way, when you arrive to the first element in the password edit field, you will oblige the email field to get focused. This will work for you as a work around.
Another way to solve the problem is to add the two fields in an horizontal field manager, in that way I guess this will work for you for sure. If not use the first method. You can find below the code for HorizontalFieldManager:
et=new EditField("Email-id:","");
pwd=new PasswordEditField("Password:","");
HorizontalFieldManager manager = new HorizontalFieldManager();
manager.add(et);
manager.add(pwd);
ab.add(manager, yourX, yourY);
It also may be a RIM bug. What OS do you use? Is it OS 5+? Do you use custom paddings/margins/borders for some of the UI elements on the screen (including the screen itself)? If yes, try to comment out any code that sets paddings/margins/borders to check whether this it the case.
You can use this code for your login page:
public class loginscreen extends MainScreen implements FieldChangeListener {
private int deviceWidth = Display.getWidth();
private int deviceHeight = Display.getHeight();
private VerticalFieldManager subManager;
private VerticalFieldManager mainManager;
public long mycolor = 0x00FFFFFF;
Screen _screen = home.Screen;
TextField heading = new TextField(Field.NON_FOCUSABLE);
TextField username_ef = new TextField();
PasswordEditField password_ef = new PasswordEditField();
CheckboxField rememberpass = new CheckboxField();
public ButtonField login_bt = new ButtonField("Login", ButtonField.CONSUME_CLICK);
public ButtonField register_bt = new ButtonField("Register", ButtonField.CONSUME_CLICK);
public loginscreen()
{
super();
final Bitmap backgroundBitmap = Bitmap.getBitmapResource("bgd.png");
HorizontalFieldManager hfm = new HorizontalFieldManager(Manager.NO_VERTICAL_SCROLL | Manager.NO_VERTICAL_SCROLLBAR )
{
protected void sublayout(int width, int height)
{
Field field;
int numberOfFields = getFieldCount();
int x = 245;
int y = 0;
for (int i = 0;i < numberOfFields;i++)
{
field = getField(i);
setPositionChild(field,x,y);
layoutChild(field, width, height);
x +=_screen.getWidth()-381;
y += 0;//l17
}
width=_screen.getWidth();
height=48;//w19
setExtent(width, height);
}
};
mainManager = new VerticalFieldManager(Manager.NO_VERTICAL_SCROLL | Manager.NO_VERTICAL_SCROLLBAR )
{
public void paint(Graphics graphics)
{
graphics.clear();
graphics.drawBitmap(0, 0, deviceWidth, deviceHeight, backgroundBitmap, 0, 0);
super.paint(graphics);
}
};
//this manger is used for adding the componentes
subManager = new VerticalFieldManager(Manager.VERTICAL_SCROLL | Manager.VERTICAL_SCROLLBAR )
{
protected void sublayout( int maxWidth, int maxHeight )
{
int displayWidth = deviceWidth;
int displayHeight = deviceHeight;
super.sublayout( displayWidth, displayHeight);
setExtent( displayWidth, displayHeight);
}
public void paint(Graphics graphics)
{
graphics.setColor((int) mycolor);
super.paint(graphics);
}
};
username_ef.setLabel("Username: ");
password_ef.setLabel("Password: ");
rememberpass.setLabel("Remember Password");
heading.setLabel("Please enter your credentials: ");
username_ef.setMaxSize(8);
password_ef.setMaxSize(20);
subManager.add(heading);
subManager.add(username_ef);
subManager.add(password_ef);
subManager.add(rememberpass);
subManager.add(new SeparatorField());
login_bt.setChangeListener(this);
register_bt.setChangeListener(this);
hfm.add(login_bt);
hfm.add(register_bt);
subManager.add(hfm);
mainManager.add(subManager);
this.add(mainManager);
}
public boolean onSavePrompt()
{
return true;
}
public void fieldChanged(Field field, int context) {
// TODO Auto-generated method stub
if(field == login_bt)
{
//do your code for login button click
}
if(field == register_bt)
{
//code for register button click
}
}}
What you have described is not normal behavior.
My conclusion is that your code has one or more bugs, in order to solve your problem you should modify your code to fix the bugs. You will then be able to scroll up and down through the various fields.
note: As this question stands it's not possible for me to be more specific about the exact bugs. So instead I will show you an example of the layout you described that would scroll properly and you can use as a default to determine which of your deviations have caused your bugs.
// inside MainScreen constructor
add(new EditField("Username:","",0));
add(new EditField("Password:","",0));
add(new ButtonField(buttonBMP,ButtonField.CONSUME_CLICK));

Blackberry Editfield keep cursor on righthandside

I want to create an editfield whose cursor keeps at righthandside of it.
To illustrate if i want to write "blackberry", result should be like this.
<-----------width-of-editfield------>
b
bl
bla
blac
black
blackb
blackbe
blackber
blackberr
blackberry
Thanks
Because of non-sense of lack of reputation thing, i can not answer my own question.
Any way, I found an easy way. width refers to width of the manager which holds this edit field.
editField = new EditField("","",maxChars,EditField.NO_NEWLINE | EditField.NON_SPELLCHECKABLE){
protected boolean keyChar(char key, int status, int time) {
editField.setPadding(0, 0, 0, width - (getFont().getAdvance(this.getText())) - 10);
invalidate();
return super.keyChar(key, status, time);
}
};
You will have to create your own Manager, unfortunately. There is no simple or obvious way to do this.
A solution with source code was posted on the BlackBerry forums.
Just like Swati's solution. I did like this:
editField = new EditField("", "", maxChars, EditField.NO_NEWLINE | EditField.NON_SPELLCHECKABLE){
protected boolean keyChar(char key, int status, int time){
switch (key){
case Characters.BACKSPACE:{
try {
text = text.substring(0,text.length()-1);
invalidate();
} catch (IndexOutOfBoundsException e) {}
return true;
}
}
text = text + key;
invalidate();
return true;
}
protected void paint(Graphics graphics) {
graphics.drawText(text,0, 0, DrawStyle.RIGHT, width - 10);
super.paint(graphics);
}
};

Resources