How to draw focus to a VerticalFieldManager in BlackBerry.
I have tried this but not working.
VerticalFieldManager vv=new VerticalFieldManager(Manager.focusFOCUSABLE);
You can try calling Field.setFocus on it, but since a manager is a container, I'm not sure you are going to see "the focus" over it.
If it doesn't work, you can try also overriding the paint method and draw your own custom focus when isFocus returns true.
this is the way to do it:
VerticalFieldManager vv=new VerticalFieldManager(FOCUSABLE) {
protected void paintBackground(Graphics g) {
int prevColor = g.getColor();
int bgColor;
if (isFocus()) {
bgColor = Color.Blue;
} else {
bgColor = Color.White;
}
g.setColor(bgColor);
g.fillRoundRect(0, 0, getPreferredWidth(), getPreferredHeight(), 0, 0);
g.setColor(prevColor);
}
public void onFocus(int direction) {
super.onFocus(direction);
this.invalidate();
}
public void onUnfocus() {
super.onUnfocus();
this.invalidate();
}
};
_focusAnchor = new NullField(FOCUSABLE);
add(_focusAnchor);
try this -
VerticalFieldManager vv=new VerticalFieldManager(FOCUSABLE);
then add items to the vv.
Related
I have a very strange problem at the moment.
Basically when I scroll in a screen, the fields don't get redrawn completely or consistently.
I have a Screen (NO_VERTICAL_SCROLL), with a manager as a titlebar. Below that I have a vertical field manager (VERTICAL_SCROLL) with labelfields. When I scroll the vfm one or two lines of the labelfields, which were already visible, get redrawn. The section I'm scrolling down to has absolutely nothing drawn.
I tried invalidate(), and calling doPaint in a scrollchangelistener, but its actually much worse. It results in the titlebar only being partially redrawn.
In the code below I used a custom FontManager, DimenManager, and ImageResourceManager to return values dependent on screen size. I used a custom BitmapButtonField and ClickableLabel in order to change the state of a field when a click is being held in.
public class BaseScreen extends MainScreen implements StringsResource
{
protected ResourceBundle resources;
public BaseScreen(long style)
{
super(style);
StandardTitleBar titlebar = new StandardTitleBar();
titlebar.addSignalIndicator();
titlebar.addClock();
titlebar.addNotifications();
setTitle(titlebar);
resources = ResourceBundle.getBundle(BUNDLE_ID, BUNDLE_NAME);
}
}
public class TandCScreen extends BaseScreen
{
final String copy_text1 = "long text here";
final String copy_text2 = "even longer text here";
ColoredLabelField label_title;
ColoredLabelField label_subtitle;
ColoredLabelField label1;
ColoredLabelField label2;
ClickableLabel label3;
public TandCScreen()
{
super(NO_VERTICAL_SCROLL | NO_VERTICAL_SCROLLBAR);
label_title = new ColoredLabelField(resources.getString(STRING_APP_NAME), Color.WHITE, DrawStyle.HCENTER | USE_ALL_WIDTH);
label_title.setBackground(BackgroundFactory.createSolidBackground(0x60223b));
label_subtitle = new ColoredLabelField(resources.getString(STRING_TANDC_TITLE), 0x58585b, DrawStyle.HCENTER | USE_ALL_WIDTH);
label1 = new ColoredLabelField(copy_text1, 0x58585b, USE_ALL_WIDTH);
label2 = new ColoredLabelField("", 0xa7a9ab, USE_ALL_WIDTH);
label3 = new ClickableLabel("Read more...")
{
protected void unclick()
{
super.unclick();
UiApplication.getUiApplication().invokeLater(new Runnable()
{
public void run()
{
ColoredLabelField label = new ColoredLabelField(copy_text2, 0xa7a9ab, 0);
label.setFont(FontManager.body());
label.setMargin(0, 0, DimenManager.interField(), 0);
label2.getManager().replace(label2, label);
label3.getManager().delete(label3);
}
});
}
};
label_title.setFont(FontManager.subtitle());
label_subtitle.setFont(FontManager.subtitle());
label1.setFont(FontManager.body());
label2.setFont(FontManager.body());
label3.setFont(FontManager.body());
BitmapButtonField button_accept = new BitmapButtonField(ImageResourceManager.buttonAccept(), ImageResourceManager.buttonAcceptHover(), FIELD_HCENTER)
{
protected void click()
{
super.click();
setImage(ImageResourceManager.buttonAcceptSelected());
setFocusImage(ImageResourceManager.buttonAcceptSelected());
}
protected void unclick()
{
super.unclick();
PersistentStoreManager.setTandCAccepted(true);
UiApplication.getUiApplication().pushScreen(new LoginScreen());
close();
}
};
BitmapButtonField button_decline = new BitmapButtonField(ImageResourceManager.buttonDecline(), ImageResourceManager.buttonDeclineHover(), FIELD_HCENTER)
{
protected void click()
{
super.click();
setImage(ImageResourceManager.buttonDeclineSelected());
setFocusImage(ImageResourceManager.buttonDeclineSelected());
}
protected void unclick()
{
super.unclick();
close();
}
};
int margin = (VariableManager.DISPLAY_WIDTH - button_accept.getPreferredWidth()) / 2;
// calculate where to put ellipsis
Font font = label2.getFont();
int max_length = (VariableManager.DISPLAY_WIDTH - margin * 2) * 2;
int i = copy_text2.length() - 1;
while (font.getAdvance(copy_text2.substring(0, i)) + font.getAdvance("...") >= max_length)
i--;
label2.setText(copy_text2.substring(0, i).trim() + "...");
VerticalFieldManager vfm = new VerticalFieldManager(VERTICAL_SCROLL | VERTICAL_SCROLLBAR);
vfm.add(new NullField());
vfm.add(label_subtitle);
vfm.add(new Seperator());
vfm.add(label1);
vfm.add(label2);
vfm.add(label3);
vfm.add(button_accept);
vfm.add(button_decline);
vfm.setMargin(0, margin, 0, margin);
// paddings
int padding = (DimenManager.header() - label_title.getPreferredHeight()) / 2;
label_title.setPadding(padding, 0, padding, 0);
label_subtitle.setPadding(DimenManager.interField(), 0, DimenManager.interField(), 0);
label1.setMargin(DimenManager.interField(), 0, DimenManager.interField(), 0);
label3.setMargin(DimenManager.interField(), 0, DimenManager.interField(), button_accept.getPreferredWidth() - label3.getPreferredWidth());
button_decline.setMargin(DimenManager.interField(), 0, DimenManager.interButton(), 0);
add(label_title);
add(vfm);
}
protected boolean onSavePrompt()
{
return false;
}
protected void makeMenu(Menu menu, int instance)
{
if (instance == Menu.INSTANCE_CONTEXT)
{
ContextMenu contextMenu = ContextMenu.getInstance();
contextMenu.setTarget(this);
contextMenu.clear();
this.makeContextMenu(contextMenu);
menu.deleteAll();
menu.add(contextMenu);
}
else
{
super.makeMenu(menu, instance);
}
}
protected void makeContextMenu(ContextMenu contextMenu)
{
}
/**
* Clickable labelfield which changes color on down press, and fires action
* on release. Action is canceled if touch moves outside field bounds.
*
* #author kevin
*
*/
private class ClickableLabel extends LabelField
{
private boolean canceled = true;
private boolean consumed = false;
protected boolean pressed = false;
public ClickableLabel(String label)
{
super(label, LabelField.FOCUSABLE | USE_ALL_WIDTH);
setFont(FontManager.body());
}
protected void paint(Graphics g)
{
// background
if (pressed)
{
g.setColor(0x2C1721);
}
else if (isFocus())
{
g.setColor(0x993C6B);
}
else
{
g.setColor(0x60223B);
}
int padding_y = (getPreferredHeight() - getFont().getHeight()) / 2;
int padding_x = getPaddingLeft();
g.drawText(getText(), padding_x, padding_y);
}
public int getPreferredHeight()
{
return ImageResourceManager.highlight().getHeight();
}
protected void layout(int width, int height)
{
height = getPreferredHeight();
super.layout(width, height);
setExtent(width, height);
}
// --------- Highlight selected row ---------
protected void onFocus(int direction)
{
super.onFocus(direction);
invalidate();
}
protected void onUnfocus()
{
super.onUnfocus();
invalidate();
}
// --------------------------------------------
protected void drawFocus(Graphics graphics, boolean on)
{
}
/**
* Called when trackpad pressed, or touchscreen touched
*/
protected void click()
{
pressed = true;
invalidate();
}
/**
* Called when trackpad released, or touchscreen released
*/
protected void unclick()
{
cancel();
}
protected void cancel()
{
pressed = false;
invalidate();
}
protected boolean navigationClick(int status, int time)
{
if (status != 0)
{
if (consumed)
{
consumed = false;
}
else
{
click();
}
}
return true;
}
protected boolean navigationUnclick(int status, int time)
{
if (status != 0)
{
if (consumed)
consumed = false;
else
unclick();
}
return true;
}
protected boolean touchEvent(TouchEvent message)
{
int x = message.getX(1);
int y = message.getY(1);
if (x < 0 || y < 0 || x > getExtent().width || y > getExtent().height)
{
// Outside the field
if (!canceled)
{
cancel();
}
canceled = true;
return false;
}
if (message.getEvent() == TouchEvent.UP)
{
if (canceled)
cancel();
else
unclick();
consumed = true;
return true;
}
if (message.getEvent() == TouchEvent.DOWN)
{
click();
consumed = true;
canceled = false;
return true;
}
return super.touchEvent(message);
}
}
private class Seperator extends SeparatorField
{
protected void paint(Graphics graphics)
{
graphics.setColor(0xa7a9ab);
super.paint(graphics);
}
}
}
Thanks in advance for any suggestions
I don't think it is possible to do anything but guess at your problem without looking at your code. But whatever your problem is, I am confident that it is based on a misunderstanding of how to use Managers within a Screen. So I recommend that you review the following articles to improve your knowledge in this area and so hopefully resolve the problem yourself:
Start here:
UI Introduction
This provides the Background around Managers and Fields.
Then read this article:
MainScreen Explained
I suspect as a result of reading this article, you may be able to discard your 'title bar' and use setTitle() or setBanner() to provide this function.
I hope this resolves your problems.
A few other points:
In all my years of BB programming, I have never had to use doPaint() to get something painting the way I wanted. I can't think of a situation that this will in fact help. So if you think you need it, try invalidate() instead.
I have used invalidate() when I making a change to the Field that will change its on screen appearance (but not its size). I have used it in a scroll change listener. But it is a method of last resort.
Remember that LabelFields are not focusable, so in OS's before 6, that made them a problem to scroll.
Found the issue. On the labelfields, there was a setExtent(getPreferredWidth(), getPreferredHeight()); that was reducing the size of the area to redraw. Very stupid mistake.
Thanks to everyone who tried to help.
I built custom edit field because i want to change the background color.
first, second and third shown unstable, sometime display when focusing, disappear when lost focusing.
I want the result like third image where the focusing at where also static display all the field.
Here is my Custom_EditField:
public class Custom_EditField extends EditField {
private int width, row, color;
private boolean isfocus;
Custom_EditField(long style, int width, int row) {
super(style);
this.width = width;
this.row = row;
}
public int getPreferredHeight() {
return Font.getDefault().getHeight() * row;
}
public int getPreferredWidth() {
return width;
}
protected void onFocus(int direction) {
color = Color.GRAY;
isfocus = true;
}
protected void onUnfocus() {
color = Color.GOLD;
isfocus = false;
}
protected void layout(int maxWidth, int maxHeight) {
super.layout(maxWidth,
Math.min(maxHeight, Font.getDefault().getHeight() * row));
super.setExtent(maxWidth,
Math.min(maxHeight, Font.getDefault().getHeight() * row));
}
protected void paint(Graphics graphics) {
int rectHeight = getPreferredHeight();
int rectWidth = getPreferredWidth();
try {
if (isfocus) {
graphics.setBackgroundColor(color);
} else {
graphics.setBackgroundColor(color);
}
color = Color.BLACK;
graphics.setColor(color);
graphics.drawRect(0, 0, rectWidth, rectHeight);
super.paint(graphics);
} finally {
graphics.setColor(color);
}
}
}
I'm not 100% sure which problem you're asking about:
how to draw your own focus background colors for an EditField, or
how to fix the problem with fields disappearing as you move focus
1) If it's the second problem (disappearing), then I would guess that you're having the same problem as in your other question, with the Custom_TopField buttons disappearing
So, if these Custom_EditField objects are created by a manager that extends VerticalFieldManager, but also implements sublayout() itself to perform all the positioning, then try the solution I suggested in the other question (don't extend VerticalFieldManager, just extend Manager).
2) If that doesn't work, it's possible that your paint() method is not getting triggered when it should. Try adding a call to invalidate() in your focus methods, along with a call to the superclass methods onFocus() and onUnfocus():
protected void onFocus(int direction) {
color = Color.GRAY;
isfocus = true;
invalidate();
super.onFocus(direction);
}
protected void onUnfocus() {
color = Color.GOLD;
isfocus = false;
invalidate();
super.onUnfocus();
}
3) And, you might need to implement this, too:
public boolean isFocusable() {
return true;
}
But, first, check your manager class, to be sure this isn't the same problem as in your other question.
Also ...
In this class, you are basing the height of the edit field on the row number. Is this really what you want? Row 0 would be 0 size, and each row after that would get taller and taller. Is that really the UI? Normally, you would have all the rows' edit fields be the same size, and simply lay them out with a different y offset. Most likely, this class should not need to know which row it has been placed on. That information is normally the responsibilty of a manager object.
protected EditField getEditField() {
EditField edit_field = new EditField("", "", 10, EditField.NO_NEWLINE
| BasicEditField.FIELD_VCENTER) {
protected boolean navigationClick(int status, int time) {
}
protected void onFocus(int direction) {
Set the boolean during focus
}
protected void onUnfocus() {
}
protected void paintBackground(Graphics graphics_paint) {
if(that boolean is true)
{
Set your custom background during focus.
}else{
Set your custom background during unfocus.
}
}
protected void paint(Graphics graphics_paint) {
int old_color = graphics_paint.getColor();
try {
if(that boolean is true)
{
Set your custom Font color during any event like focus and click.
}else{
Set your custom background Font color during any event like unfocus.
}
super.paint(graphics_paint);
} finally {
graphics_paint.setColor(old_color);
}
}
public void layout(int width, int height) {
}
};
This is may be old question but i dont get proper solution
if it is wrong please ignore otherwise please halp me
I have one main screen with two verticleManagers
1)For browserField
2)one button
first i add successfully My Browserfield to First verticlemanger and also add button to second verticlemanager
finally two verticlemanager added to main screen.
in OS6 i dont get any problem it works fine
but in OS5 i got problem that is
once the Browserfield is getting focus, it never release its focus so i am unable to navigate downside of the Browserfield. Means i am unable to click on blackberry advertisement Banner.i am unable to navigate down from browserfield using trackpad
this is my sample code
class browserScreen extends MainScreen
{
String url;
BrowserField browserField;
public browserScreen() {
VerticalFieldManager main_mgr=new VerticalFieldManager(){
protected void sublayout(int maxWidth, int maxHeight) {
super.sublayout(Display.getWidth(),Display.getHeight());
setExtent(Display.getWidth(),Display.getHeight());
}
};
VerticalFieldManager browserfield_mgr=new VerticalFieldManager(){
protected void sublayout(int maxWidth, int maxHeight) {
super.sublayout(Display.getWidth(),Display.getHeight()-50);
setExtent(Display.getWidth(),Display.getHeight()-50);
}
};
url="http://www.google.com";
BrowserFieldConfig browserFieldConfig = new BrowserFieldConfig();
browserFieldConfig.setProperty(BrowserFieldConfig.NAVIGATION_MODE, BrowserFieldConfig.NAVIGATION_MODE_POINTER);
browserFieldConfig.setProperty(BrowserFieldConfig.JAVASCRIPT_ENABLED,Boolean.TRUE);
browserFieldConfig.setProperty(BrowserFieldConfig.ALLOW_CS_XHR,Boolean.TRUE);
browserField=new BrowserField(browserFieldConfig);
browserField.requestContent(url);
browserfield_mgr.add(browserField);
main_mgr.add(browserfield_mgr);
VerticalFieldManager button_mgr=new VerticalFieldManager(){
protected void sublayout(int maxWidth, int maxHeight) {
super.sublayout(Display.getWidth(),50);
setExtent(Display.getWidth(),50);
}
};
button_mgr.add(new SeparatorField());
ButtonField btn=new ButtonField("BUTTON MANAGER");
button_mgr.add(btn);
main_mgr.add(button_mgr);
add(main_mgr);
}
}
any help can be appreciated
After i googled a lot i conclude that This is OS 5 issue. it wont resolve it in OS5. It resolved In OS6. You have to provide a way to move the focus off the BrowserField yourself. I have tried a variety of mechanisms to do this, like detecting Escape in the Screen's keyChar method, the best I have found so far is to use the Menu and give the users the option of swapping focus out of the BrowserField. In general I do not recommend sharing the Screen between a Web Field and any other.
public class LoadingScreen extends MainScreen
{
VerticalFieldManager vertical;
HorizontalFieldManager hor;
String url;
BrowserField browserField;
Banner bannerAd ;
private static boolean flag=false;
public LoadingScreen()
{
//
VerticalFieldManager Veret=new VerticalFieldManager(Manager.NO_VERTICAL_SCROLL|Manager.NO_HORIZONTAL_SCROLL){
protected void sublayout(int maxWidth, int maxHeight) {
super.sublayout(Display.getWidth(),Display.getHeight());
setExtent(Display.getWidth(),Display.getHeight());
}
};
//Veret.setBackground(BackgroundFactory.createSolidBackground(Color.BLACK));
VerticalFieldManager main_mgr=new VerticalFieldManager(Manager.NO_VERTICAL_SCROLL|Manager.NO_HORIZONTAL_SCROLL){
protected void sublayout(int maxWidth, int maxHeight) {
super.sublayout(Display.getWidth(),Display.getHeight()-50);
setExtent(Display.getWidth(),Display.getHeight()-50);
}
};
url="http://www.google.com";
BrowserFieldConfig browserFieldConfig = new BrowserFieldConfig();
browserFieldConfig.setProperty(BrowserFieldConfig.NAVIGATION_MODE, BrowserFieldConfig.NAVIGATION_MODE_POINTER);
browserFieldConfig.setProperty(BrowserFieldConfig.JAVASCRIPT_ENABLED,Boolean.TRUE);
browserFieldConfig.setProperty(BrowserFieldConfig.ALLOW_CS_XHR,Boolean.TRUE);
browserField=new BrowserField(browserFieldConfig);
browserField.requestContent(url);
main_mgr.add(browserField);
Veret.add(main_mgr);
final Bitmap ad_bg=Bitmap.getBitmapResource("add_bg.png");
VerticalFieldManager add_back=new VerticalFieldManager(USE_ALL_WIDTH|Field.FOCUSABLE){
protected void paint(Graphics graphics) {
graphics.drawBitmap(0, 0, ad_bg.getWidth(), ad_bg.getHeight(), ad_bg, 0, 0);
super.paint(graphics);
}
protected void sublayout(int maxWidth, int maxHeight) {
super.sublayout(ad_bg.getWidth(), ad_bg.getHeight());
setExtent(ad_bg.getWidth(), ad_bg.getHeight());
}
};
try{
Bitmap customPlaceholder = Bitmap.getBitmapResource("add_bg.png");
bannerAd = new Banner(31848, null, 100000, customPlaceholder);
bannerAd.setBorderColor(Color.RED);
int i=(Display.getWidth()-320)/2;
bannerAd.setPadding(0, 0, 0, i);
bannerAd.setBannerTransitionColor(Color.RED);
bannerAd.setMMASize(Banner.MMA_SIZE_EXTRA_LARGE);
// Dialog.inform(""+bannerAd.getMMASize());
}catch (Exception e) {
Dialog.inform(e.getMessage());
}
add_back.add(bannerAd);
Veret.add(add_back);
add(Veret);
}
protected void makeMenu(Menu menu, int instance)
{
int i=Integer.parseInt(StartUp.getOsVersion().substring(0, 1));
if(i<6)
menu.add(_testItem);
}
private MenuItem _testItem = new MenuItem("Go to Advertise", 100, 9)
{
public void run(){
bannerAd.setFocus();
}
};
}
This is a bug in OS5. Its been fixed in os6 and upwards . These are the reasons why you are seeing the strange behaviour. You cannot get the same behaviour in os5. The only thing you could do is a hack, which is to setfocus on the button_mgr . The code will look like this.
// override the invokeAction method
public boolean invokeAction(int action) {
Field f = getFieldWithFocus();
// check the type of field you are looking for ,
//here i am checking if its a verticalfieldmanager
if (f instanceof VerticalFieldManager) {
button_mgr.setFocus();
return true;
}
return super.invokeAction(action);
}
this will setfocus on your button.
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);
}
};
I have created a custom button field for my BlackBerry project. I would like to change the picture displayed on the button after it is drawn, but cannot figure out how. I have code that changes the member variable that stores the bitmap, but do not know how to tell the blackberry to update it.
// CODE TO CHANGE BUTTONS Image
Bitmap image2 = Bitmap.getBitmapResource("aftera.png");
MyBut.image=image2;
// don’t know how to redraw buttn?????
// BUTTON CODE
public class cPictureButton extends Field{
public Bitmap image;
public cPictureButton( Bitmap image, long style)
{
super(style);
this.image=image;
}
public int getPreferredHeight()
{
return image.getHeight();
// return getFont().getHeight();
}
public int getPreferredWidth()
{
return image.getWidth();
// return getFont().getAdvance(label)+8;
}
protected void drawFocus(Graphics g, boolean on)
{
}
protected void paint(Graphics g)
{
int w=image.getWidth();
int h=image.getHeight();
g.drawBitmap(0, 0, w, h, image, 0, 0);
if (isFocus() )
g.drawRect(0,0,image.getWidth(), image.getHeight());
}
protected void layout(int width, int height) {
// TODO Auto-generated method stub
setExtent(Math.min(width, getPreferredWidth()),
Math.min(height, getPreferredWidth()));
}
public boolean isFocusable() {
return true;
}
protected boolean navigationClick(int status, int time)
{
fieldChangeNotify(0);
return true;
}
}
Calling invalidate() on your button field should take care of it.
Also, you still have the bug in your layout() method that I pointed out in your earlier question: Why does my rectangular bitmap get clipped to a square when I draw it?