10-12-2010 09:53 AM
Hi,
I have 2 bitmapfields and a buttonfield. I want all fields to trap click events. Initially I had added only fieldChangeListeners to all fields, but bitmap field didn't respond to them (despite making them Focusable). I added touchevent to handle click events for all the fields, now all fields respond only touchEvents. Even buttonfield doesn't respond to fieldChange which it was responding before adding of touchEvent.
Can anyone help me know the problem and the solution for the same. I want all fields to respond to click events via touch or normal. Also in touchEvent, as navigationClick id added, so the menu doesn't come, but otherwise with the other click only menu comes which shouldn't and the fieldchangelistener should be handled. Below is the code.
private BitmapField signOffBtn, profileBtn;
private ButtonField btn;
public LoggedUserScreen(UserBean user) {
super();
this.loggedUser = user;
System.out.println("Into LoggedUserScreen : Got user");
init();
this.add(signOffBtn);
this.add(profileBtn);
this.add(btn);
}
private void init() {
signOffBtn = new BitmapField (Bitmap.getBitmapResource("icon.png"), BitmapField.FOCUSABLE ) {
protected boolean navigationClick(int status, int time) {
return true; // handle click event
}
};
profileBtn = new BitmapField (Bitmap.getBitmapResource("icon.png"), BitmapField.FOCUSABLE ) {
protected boolean navigationClick(int status, int time) {
return true; // handle click event
}
};
btn = new ButtonField("button", BitmapField.HIGHLIGHT_SELECT | BitmapField.FOCUSABLE);
signOffBtn.setChangeListener(this);
profileBtn.setChangeListener(this);
btn.setChangeListener(this);
}
public void fieldChanged(Field field, int context) {
if (field == signOffBtn) {
System.out.println("********* SIGN OFF CLICKED");
} else if (field == profileBtn) {
System.out.println("********* PROFILE CLICKED");
} else if (field == btn) {
System.out.println("********* button CLICKED");
System.exit(0);
}
}
public int getFieldAtLocation(int x, int y) {
XYRect rect = new XYRect();
int index = getFieldCount() -1;
while (index >= 0) {
getField(index).getExtent(rect);
if (rect.contains(x, y))
break;
--index;
}
return index;
}
protected boolean touchEvent(TouchEvent event) {
switch(event.getEvent()) {
case TouchEvent.DOWN:
return true;
case TouchEvent.MOVE:
return true;
case TouchEvent.UP:
return true;
case TouchEvent.CLICK:
int index = getFieldAtLocation(event.getX(1), event.getY(1));
// Ignore click events outside any fields
if (index == -1)
return true;
Field field = getField(index);
if (field == signOffBtn) {
System.out.println("Touched SignOff");
} else if (field == profileBtn) {
System.out.println("Touched Profile");
} else if (field == btn) {
System.out.println("Touched Button");
}
return true;
}
return false;
}
Thanks
Solved! Go to Solution.
10-12-2010 10:52 AM
A couple of thoughts:
1) You don't need to create your own int getFieldAtLocation(int, int) - any Manager already has that.
2) Don't process event.CLICK - process event.DOWN by setting focus to the touched field (which is the default action but you seem to have some custom Manager, so I'm not sure in your case). Something like this:
case TouchEvent.DOWN:
int index = getFieldAtLocation(event.getX(1), event.getY(1));
// Ignore click events outside any fields
if (index == -1)
return super.touchEvent(event);
Field field = getField(index);
if (field.isFocusable()) field.setFocus();
3) See that return super.touchEvent(...)? That is the right way to do it - don't return true from touchEvent except from complex events like MOVE and GESTURE. By returning true from DOWN you disrupt the processing of complex events.
10-12-2010 12:00 PM
arkadyz,
I am just creating a banner that can be used for all screens in the application. But ya, this will be definetely part of other screens.
I tried your idea i.e. removed from Click & imeplemented in Down as you have showed. I also got added an ImageButton from http://supportforums.blackberry.com/t5/Java-Develo
My filedChanged code is :
public void fieldChanged(Field field, int context) {
if (field == signOffBtn) {
System.out.println("********* SIGN OFF CLICKED");
} else if (field == profileBtn) {
System.out.println("********* PROFILE CLICKED");
} else if (field == btn) {
System.out.println("********* button CLICKED");
System.exit(0);
} else if (field == imageBtn) {
System.out.println("************ IMAGE BTN CLICKED");
}
}
My touchevent is :
protected boolean touchEvent(TouchEvent event) {
switch(event.getEvent()) {
case TouchEvent.DOWN:
int index = getFieldAtLocation(event.getX(1), event.getY(1));
if (index == -1)
return super.touchEvent(event);
Field field = getField(index);
System.out.println("Down Event Field = " + field);
if (field.isFocusable())
field.setFocus();
return true;
case TouchEvent.MOVE:
return true;
case TouchEvent.UP:
return true;
case TouchEvent.CLICK:
/*
int index = getFieldAtLocation(event.getX(1), event.getY(1));
// Ignore click events outside any fields
if (index == -1)
return true;
Field field = getField(index);
if (field == signOffBtn) {
System.out.println("Touched SignOff");
} else if (field == profileBtn) {
System.out.println("Touched Profile");
} else if (field == btn) {
System.out.println("Touched Button");
} else if (field == imageBtn) {
System.out.println("Touched Image Button");
}
return true;
*/
}
return false;
}
If I activate the TouchEvent.Down, I press left click or right click I can see only "Down Event Field = ...." except for ButtonField, for left click System.exit(0) is executed.
If I disable Down & activate Click event, on left click I get to see "Touched ...." SOP's and on right click, no action. Plus fieldChange for buttonField is also never acticvated (System.exit(0))
What to do ??
10-12-2010 03:23 PM
Don't ever return true; from touchEvent for such simple events as DOWN (haven't I said that in my previous post?). Use return super.touchEvent(...)!
Also, if you return true; from CLICK, fieldChanged() will not be called - the BlackBerry framework calls that only if it gets to process the event, which you just don't allow.
What are you trying to achieve? It seems that you are adding too much complexity to some really simple stuff. Could you just override navigationClick() on your Manager and branch according to your getFieldWithFocus()?
10-13-2010 05:08 AM
Hi,
All I want am trying to do is, handle touch and click events for each buttons. Code FieldChangeListener handles cliekc events and touchEvent for touch clicks. As Simulator says "use left mouse button to click the screen and right mouse button to touch". Looking at this I belive on left click, fieldChanged() will be executed & on right click, touchEvent() will be executed. I have already added navigationClick() for 2 bitmapFields. With the below code, with left mouse clikc I get following results but don't get any results on right mouse click :
Touched SignOff
Touched Profile
Touched Image Button
Touched Button
********* button CLICKED
/*
* LoggedUserScreen.java
*/
package gd;
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.system.Bitmap;
import backend.UserBean;
public class LoggedUserScreen extends MainScreen implements FieldChangeListener {
private UserBean loggedUser = null;
private BitmapField signOffBtn, profileBtn;
private ButtonField btn;
private ImageButton imageBtn;
public LoggedUserScreen(UserBean user) {
super();
this.loggedUser = user;
System.out.println("Into LoggedUserScreen : Got user");
init();
this.add(signOffBtn);
this.add(profileBtn);
this.add(btn);
this.add(imageBtn);
}
private void init() {
signOffBtn = new BitmapField (Bitmap.getBitmapResource("icon.png"), BitmapField.FOCUSABLE | ButtonField.FIELD_LEFT) {
protected boolean navigationClick(int status, int time) {
return true; // handle click event
}
};
profileBtn = new BitmapField (Bitmap.getBitmapResource("icon.png"), BitmapField.FOCUSABLE | ButtonField.FIELD_RIGHT ) {
protected boolean navigationClick(int status, int time) {
return true; // handle click event
}
};
imageBtn = new ImageButton(Bitmap.getBitmapResource("icon.png"), Bitmap.getBitmapResource("icon.png"));
btn = new ButtonField("button", BitmapField.HIGHLIGHT_SELECT | BitmapField.FOCUSABLE | ButtonField.FIELD_RIGHT);
signOffBtn.setChangeListener(this);
profileBtn.setChangeListener(this);
imageBtn.setChangeListener(this);
btn.setChangeListener(this);
}
public void fieldChanged(Field field, int context) {
if (field == signOffBtn) {
System.out.println("********* SIGN OFF CLICKED");
SignOff();
} else if (field == profileBtn) {
System.out.println("********* PROFILE CLICKED");
} else if (field == btn) {
System.out.println("********* button CLICKED");
System.exit(0);
} else if (field == imageBtn) {
System.out.println("************ IMAGE BTN CLICKED");
}
}
private void disposeAll() {
loggedUser = null;
return;
}
private void SignOff() {
int response = Dialog.ask(Dialog.D_YES_NO, "Sure Sign Off ?");
if (response == -1) { // No
} else{ // Yes
//SaveUserInfo();
disposeAll();
System.exit(0);
}
}
public int getFieldAtLocation(int x, int y) {
XYRect rect = new XYRect();
int index = getFieldCount() -1;
while (index >= 0) {
getField(index).getExtent(rect);
if (rect.contains(x, y))
break;
--index;
}
return index;
}
protected boolean touchEvent(TouchEvent event) {
boolean returnValue = super.touchEvent(event);
switch(event.getEvent()) {
case TouchEvent.DOWN:
return true;
case TouchEvent.MOVE:
return true;
case TouchEvent.UP:
return true;
case TouchEvent.CLICK:
int index = getFieldAtLocation(event.getX(1), event.getY(1));
// Ignore click events outside any fields
if (index == -1)
return returnValue;
Field field = getField(index);
if (field == signOffBtn) {
System.out.println("Touched SignOff");
//SignOff();
} else if (field == profileBtn) {
System.out.println("Touched Profile");
} else if (field == btn) {
System.out.println("Touched Button");
fieldChanged(field, 0);
} else if (field == imageBtn) {
System.out.println("Touched Image Button");
}
return returnValue;
}
return returnValue;
}
}
/* * ImageButton.java * * Code is taken from : http://supportforums.blackberry.com/t5/Java-Development/issue-with-using-image-as-button/td-p/393157 * */ package gd; import net.rim.device.api.system.Bitmap; import net.rim.device.api.ui.FieldChangeListener; import net.rim.device.api.ui.container.MainScreen; import net.rim.device.api.ui.Field; import net.rim.device.api.ui.Color; import net.rim.device.api.system.EncodedImage; import net.rim.device.api.system.Characters; import net.rim.device.api.ui.component.BitmapField; import net.rim.device.api.ui.Graphics; import net.rim.device.api.system.Display; import net.rim.device.api.ui.container.VerticalFieldManag er; import net.rim.device.api.ui.Manager; public class ImageButton extends Field { private Bitmap _currentPicture; private Bitmap _onPicture; private Bitmap _offPicture; private int id; public ImageButton (Bitmap onImage, Bitmap offImage) { super(Field.FOCUSABLE); _offPicture = offImage; _onPicture = onImage; _currentPicture = _onPicture; } public void setButtonId(int id) { this.id = id; } public int getButtonId() { return this.id; } public int getPreferredHeight() { return _onPicture.getHeight(); } public int getPreferredWidth() { return _onPicture.getWidth(); } protected void onFocus(int direction) { _currentPicture = _offPicture; invalidate(); } protected void onUnfocus() { _currentPicture = _onPicture; invalidate(); } protected void drawFocus(Graphics g, boolean on) { g.setBackgroundColor(Color.BLACK); } protected void layout(int width, int height) { setExtent(Math.min( width, getPreferredWidth()), Math.min( height, getPreferredHeight())); } protected void paint(Graphics graphics) { graphics.setBackgroundColor(Color.BLACK); graphics.clear(); graphics.fillRect(0, 0, getWidth(), getHeight()); graphics.drawBitmap(0, 0, getWidth(), getHeight(), _currentPicture, 0, 0); } protected boolean navigationClick(int status, int time) { fieldChangeNotify(0); return true; } public boolean keyChar(char key, int status, int time) { if (key == Characters.ENTER) { fieldChangeNotify(0); return true; } return false; } }
Shouldn't both the clicks respond in click & touch event ? Where am I going wrong to manage the normal click (fieldChanged) after adding touchEvent ? Should I have to call fieldChanged(field, 0) for other buttons also in touchEvent as added for btn and is working also ? fieldChangeNotify(0) is already added in ImageButton, but that also doesn't work.
Also, if I am wrong in understanding the click and touch click hanadled by left & right mouse click kindly let me know for better understanding.
Thanks,
10-13-2010 09:43 AM
Well - your overriding of navigationClick in ImageButton is correct. And since it is entirely sufficient to invoke your fieldChanged(), you don't have to override touchEvent() at all! When you press and click a focusable field on a touch screen, the default BB framework reaction is to first set focus to that field (thanks to DOWN event always preceding CLICK event) and then to invoke navigationClick (and later navigationUnclick - that's where BB framework often performs its own stuff).
Now, if you absolutely need to perform some additional stuff on touch, you can do that. By the way, I think that invoking super.touchEvent(...) before your own processing is not the best approach - just put break; in each case and in the end, after the switch statement, return super.touchEvent(...).
10-13-2010 10:22 AM
Ok, modified the touchEvent replacing return statements in switch with break & removed handling for imageBtn.
On click on imageBtn, its fieldChanged() get fired. But then the focus stays on it only. I mean if I click somewhere else then also, "IMAGE BTN CLICKED" is displayed. So the focus doesn't go away after event is fired. I guess in fieldChanged(), after all activities are done the focus should be removed from it.
How to remove the focus from ImageButton once fieldChanged is fired ?
Also, if you have idea to access files from local web server, can you have a look at http://supportforums.blackberry.com/t5/Java-Develo
and help me if possible.
Thanks a lot. Just now Image Btn should lose its focus on completing its work.
10-13-2010 11:17 AM
You cannot call removeFocus - it is hidden deep in BlackBerry framework. However, you can call somethingElse.setFocus() if you wish...
10-13-2010 11:47 AM
Ya I already looked for it, their is nothing like removeFocus or setFocus(false) or so. But yes, your something.setFocus gave me the idea to setFocus to the screen itself so the focus is removed from the button also and not on any component that can trap the event.
So, if I add fieldChangeNotify(0); in navigationclick of signOffBtn, profileBtn & btn, then I totally don't need to implement touchEvent ?
private void init() {
signOffBtn = new BitmapField (Bitmap.getBitmapResource("icon.png"), BitmapField.FOCUSABLE | ButtonField.FIELD_LEFT) {
protected boolean navigationClick(int status, int time) {
fieldChangeNotify(0);
return super.navigationClick(status, time); // handle click event
}
};
profileBtn = new BitmapField (Bitmap.getBitmapResource("icon.png"), BitmapField.FOCUSABLE | ButtonField.FIELD_RIGHT ) {
protected boolean navigationClick(int status, int time) {
fieldChangeNotify(0);
return super.navigationClick(status, time); // handle click event
}
};
imageBtn = new ImageButton(Bitmap.getBitmapResource("icon.png"), Bitmap.getBitmapResource("icon.png"));
btn = new ButtonField("button", BitmapField.HIGHLIGHT_SELECT | BitmapField.FOCUSABLE | ButtonField.FIELD_RIGHT) {
protected boolean navigationClick(int status, int time) {
fieldChangeNotify(0);
return super.navigationClick(status, time); // handle click event
}
};
signOffBtn.setChangeListener(this);
profileBtn.setChangeListener(this);
imageBtn.setChangeListener(this);
btn.setChangeListener(this);
}
touchEvent is totally removed & navigationClick is implemented for each button.
Thanks. Just want to confirm, with this, will my all componetns work for touchscreen & non-touch screen properly. in 9530 Simulator touch screen (left mouse click) is responding but non-touch i.e. a click (right muose clisk) doesn't respond anything. So wondering.....
10-13-2010 01:26 PM
trupti wrote:
So, if I add fieldChangeNotify(0); in navigationclick of signOffBtn, profileBtn & btn, then I totally don't need to implement touchEvent ?
That's the idea - to let the framework do its job. I wouldn't bother too much about simulator not working properly - check on a real phone and see. Simulators do a good job mimicking the real UI interactions, but sometimes they fail.
Once you are satisfied with the results, can you mark this thread as solved?