i m writing one application in which i have created custom list field for displaying listview. my CustomListField contains one image and text in a row. i m gettiing field change listener on click of listfield row but i want to put fieldchange listener on image too.. can anyone tell me how can i do that.
here is my code.
public class CustomListField extends ListField implements ListFieldCallback {
private Vector _listData;
private int _MAX_ROW_HEIGHT = 60;
public CustomListField(Vector data) {
_listData = data;
setSize(_listData.size());
setSearchable(true);
setCallback(this);
setRowHeight(_MAX_ROW_HEIGHT);
}
protected void drawFocus(Graphics graphics, boolean on) {
XYRect rect = new XYRect();
graphics.setGlobalAlpha(150);
graphics.setColor(Color.BLUE);
getFocusRect(rect);
drawHighlightRegion(graphics, HIGHLIGHT_FOCUS, true, rect.x, rect.y, rect.width, rect.height);
}
public int moveFocus(int amount, int status, int time) {
this.invalidate(this.getSelectedIndex());
return super.moveFocus(amount, status, time);
}
public void onFocus(int direction) {
super.onFocus(direction);
}
protected void onUnFocus() {
this.invalidate(this.getSelectedIndex());
}
public void refresh() {
this.getManager().invalidate();
}
public void drawListRow(ListField listField, Graphics graphics, int index, int y, int w) {
listField.setBackground(BackgroundFactory.createBitmapBackground(Bitmap.getBitmapResource("listing_bg.png")));
ListRander listRander = (ListRander) _listData.elementAt(index);
graphics.setGlobalAlpha(255);
graphics.setFont(Font.getDefault().getFontFamily().getFont(Font.PLAIN, 24));
final int margin = 5;
final Bitmap thumb = listRander.getListThumb();
final String listHeading = listRander.getListTitle();
final Bitmap nevBar = listRander.getNavBar();
// list border
graphics.setColor(Color.GRAY);
graphics.drawRect(0, y, w, _MAX_ROW_HEIGHT);
// thumbnail border & thumbnail image
graphics.setColor(Color.BLACK);
// graphics.drawRoundRect(margin-2, y+margin-2,thumb.getWidth()+2, thumb.getHeight()+2, 5, 5);
graphics.drawBitmap(margin, y + margin, thumb.getWidth(), thumb.getHeight(), thumb, 0, 0);
// drawing texts
// graphics.setFont(Font.BOLD);
graphics.drawText(listHeading, margin + thumb.getWidth(), y + margin);
graphics.setColor(Color.GRAY);
// graphics.setFont(Font.smallFont); // graphics.drawText(listDesc, 2*margin+thumb.getWidth(), y+ margin+20); // //
// graphics.drawText(listDesc2, 2*margin+thumb.getWidth(), y+ margin+32);
// draw navigation button
final int navBarPosY = y + (_MAX_ROW_HEIGHT / 2 - nevBar.getHeight() / 2);
final int navBarPosX = Graphics.getScreenWidth() - nevBar.getWidth() + margin;
graphics.drawBitmap(navBarPosX, navBarPosY, nevBar.getWidth(), nevBar.getHeight(), nevBar, 0, 0);
}
public Object get(ListField listField, int index) {
String rowString = (String) _listData.elementAt(index);
return rowString;
}
public int indexOfList(ListField listField, String prefix, int start) {
for (Enumeration e = _listData.elements(); e.hasMoreElements();) {
String rowString = (String) e.nextElement();
if (rowString.startsWith(prefix)) {
return _listData.indexOf(rowString);
}
}
return 0;
}
public int getPreferredWidth(ListField listField) {
return 3 * listField.getRowHeight();
}
/*
protected boolean trackwheelClick(int status, int time) {
invalidate(getSelectedIndex());
Dialog.alert(" U have selected :" + getSelectedIndex());
return super.trackwheelClick(status, time);
}
*/
}
i want to put click listner on star image of listfield row
and following is output of abbove code.
Unlike Android's
ListView
the BB'sListField
is not designed to have a focusable/clickable fields inside of list items. So any attempt to workaround this will have some negative side effects.A relatively easy/quick workaround would be to switch to
VerticalFieldManager
(check this other stack overflow question). But if the list is too long (more than several hundreds, I believe) you risk to "eat" too much memory.If the app is designed for touch screens only, then you can try to stay with
ListField
+ do some manual tracking of touch event coordinates. So when you detect a list field click (in a way you would normally do it) you can check whether the touch coordinates correspond to the star image area (at least on the X axis). I am not going to invent/provide an implementation, but just giving an idea.I did something very similar to this on a past project:
Background
As Arhimed said in his answer, and as you can read about on the BlackBerry forums here, you can't have full-fledged
Field
objects within theListField
. The content ofListField
rows is just drawn directly indrawListRow()
as text, and Bitmaps, etc. The contents aren'tField
instances, and therefore, are not focusable.So, what I did was to replace
ListField
with a subclass ofManager
. Originally, I used aVerticalFieldManager
, but I ran into problems with that. I've also been seeing a lot of issues on stack overflow, where people subclassVerticalFieldManager
, customize just one small behaviour, and everything starts breaking. It seems to me thatVerticalFieldManager
works well if you accept its normal behaviour, and if you need something more, just extendManager
directly. Performing layout for vertically stacked rows is pretty easy.I then made each row its own
Manager
, and implemented custom layout insublayout()
to place the row'sField
s where I wanted them. I could then also make the row focusable, and then a bitmap/button on the row separately focusable (like your star). Clicking the row invokes one action, and clicking the star invokes another one.I will note, however, that in my app, performance was not an issue, because I only had 10-20 rows. Also, I did have to modify my code to match your example, so consider this code only lightly tested. However, I did build it into an app, so it should perform fine as long as my assumptions, and your description were valid.
Implementation
First, it wasn't clear to me what your
ListRander
is (you didn't show that code). However, in my code, I need a data class to contain details about one row. It looked like that's how you usedListRander
, so that's what I used:Then, I replaced your
CustomListField
class with my own:Finally, one row is represented by my
CustomListRow
class:Usage
This is how you might use the whole list field (maybe in a
Screen
class):In my app, it made sense for the
CustomListRow
itself to handle the equivalent of your star click. However, for me, it did not make sense to have the row click handled that way. So, I let you set aFieldChangeListener
on theCustomListField
itself, which is called back when any row is selected. See the example above in my screen class. If you want to handle the row click inside theCustomListRow
class, too, that's fine. I laid out aonRowClicked()
method there. Search in the code for where that's commented out, and you can reactivate, an implement that method (onRowClicked()
).Issues
ListField
has. But, I didn't test it. That's your job, if you need it. I just got you started with theCustomListField
implementation (seeindexOfList()
).CustomListRow
class implementsgetPreferredWidth()
and requests the full screen width. Change if you like.