Welcome!

Welcome to the official BlackBerry Support Community Forums.

This is your resource to discuss support topics with your peers, and learn from each other.

inside custom component

Java Development

Reply
Developer
mapleleafs90
Posts: 374
Registered: ‎02-12-2011
My Device: Bold 9780
Accepted Solution

CustomFields and getPreferredHeight() override

I have some fields that I need to find out the height to properly layout my user interface as its being created, I do not know how I can override it and just return the default height.


I have 4 buttons each in their own vertical field manager.


Then those 4 vertical managers inside 1 HorizontalFieldManager so the buttons can be horizontally aligned. (Each button has its own VFM so I can set a custom width by overriding getPreferredWidth so they can all be of equal size no matter what length of text)


In the end it looks like

 

_____

|[] [] [] []|

|_____|

 

When I call HorizontalManager.getPreferredHeight() (after all buttons are added to the VFM and after the VFM are added to the HorizontalManager, it returns 18. 


18 though is incorrect, because after I check again (I have a listener in one of the buttons and I output the height of the HorizontalManager then, it is 38) .

 

Buttons... (They are all the same except the name)  4 of them

ButtonField Button 1= new ButtonField("Button 1", ButtonField.CONSUME_CLICK | ButtonField.USE_ALL_WIDTH)
{
	public int getPreferredWidth()
	{
		return 100; //Will actually be 1/4 of screen, not 100
	}
	//No set preferredheight - I want default	
};

 VerticalFieldManagers which the buttons go inside (four of these, differ by name)

 

VerticalFieldManager Button1VFM = new VerticalFieldManager(USE_ALL_WIDTH) {
	protected void sublayout(int maxWidth, int maxHeight) {
	        super.sublayout((Display.getWidth() / 4), getPreferredHeight()); //each button will be 1/4 of screen
	}
	public int getPreferredHeight()
	{
		return super.getPreferredHeight();
	}
};

 

Finally.

 

final HorizontalFieldManager hfm1 = new HorizontalFieldManager();
			
hfm1.add(Button1VFM);
hfm1.add(Button2VFM);
hfm1.add(Button3VFM);
hfm1.add(Button4VFM);

 

If I do this..

VerticalFieldManager Button1VFM = new VerticalFieldManager(USE_ALL_WIDTH) {
	protected void sublayout(int maxWidth, int maxHeight) {
	        super.sublayout((Display.getWidth() / 4), getPreferredHeight()); //each button will be 1/4 of screen
	}
	public int getPreferredHeight()
	{
		return 38;
	}
};

 And return 38 then it works great, the problem is depending on the device 38 will be too big for a smaller screen. I want the default.

 

So how can I override it and return the default height. You would thing either not overriding it or returning super.getPreferredHeight() would work but I have no clue why it returns 18 at first.

Please use plain text.
Developer
johanguzman07
Posts: 102
Registered: ‎07-26-2011
My Device: Not a blackberry user

Re: CustomFields and getPreferredHeight() override

Greetings.

 

In your VerticalFieldManager sublayout method don't call the parent sublayout method (super); instead, use the methods layoutChild (to set the size of every button), setPositionChild (to locate the buttons within the manager) and setExtent (to give the manager the appropriate size).

 

That will help you with your issue.

 

In case you need some help with those method, see the JavaDocs for the Manager class.


Let me know if this was helpful or if you have a solution.

Johan Guzmán - In case my answer pleased you, give a press to the LIKE button, please!! Mark this post as solution if it solved your problem.
Please use plain text.
Developer
mapleleafs90
Posts: 374
Registered: ‎02-12-2011
My Device: Bold 9780

Re: CustomFields and getPreferredHeight() override

VerticalFieldManager newVFM = new VerticalFieldManager(USE_ALL_WIDTH) {
	protected void sublayout(int maxWidth, int maxHeight) {
		layoutChild(Button1, maxWidth, maxHeight);
		setPositionChild(Button1, maxWidth, maxHeight);
		setExtent(maxWidth, maxHeight);
		//super.sublayout((Display.getWidth() / 4), getPreferredHeight());
	}
	
        public int getPreferredHeight()
	{
	        return super.getPreferredHeight();
	}
};

 I dont know if this is what you mean but it doesnt work. You said to remove the super.sublayout call from the sublayout override and replace it with layoutChild setting the dimensions of the buttons and setPositionChild also and finally setExtent.

 

Remember, I do not have a specific dimension for the buttons, I want the default.

Please use plain text.
Developer
mapleleafs90
Posts: 374
Registered: ‎02-12-2011
My Device: Bold 9780

Re: CustomFields and getPreferredHeight() override

Is there another way I could set the button width without enclosing it in a vertical field manager.

Please use plain text.
Developer
johanguzman07
Posts: 102
Registered: ‎07-26-2011
My Device: Not a blackberry user

Re: CustomFields and getPreferredHeight() override

Of course!

The Field class has a getPreferredWidth public method, if you want to see the net width of your button field, just call that method; in case you want to retrieve a exact or calculated value, override that method.

First case: buttonField.getPrefferedWidth().

Second case:
ButtonField bttnField = new ButtonField() {
public int getPreferredWidth() {
return getFont().getAdvance(this.getLabel()) + TOTAL_PADDING;
}
}

I hope this help. Good luck.

Let me know if this was helpful or if you have a solution.

Johan Guzmán - In case my answer pleased you, give a press to the LIKE button, please!! Mark this post as solution if it solved your problem.
Please use plain text.
Developer
mapleleafs90
Posts: 374
Registered: ‎02-12-2011
My Device: Bold 9780

Re: CustomFields and getPreferredHeight() override

final ButtonField Button1 = new ButtonField("Button 1", ButtonField.CONSUME_CLICK | ButtonField.USE_ALL_WIDTH)
			{
				public int getPreferredWidth()
				{
					return Display.getWidth()/4;
				}
			};

 Yes I remember I have tried this, and see how I want it 1/4 of the screen, I add 4 buttons but 2 of them take up 3/4 of the width of the screen , and the last button doesnt even appear.

Please use plain text.
Developer
johanguzman07
Posts: 102
Registered: ‎07-26-2011
My Device: Not a blackberry user

Re: CustomFields and getPreferredHeight() override

[ Edited ]

Can you explain me why you need to have a VerticalFieldManager for each button? You have some specific need for that?

 

Anyway, in my first post in this thread, I was trying to prompt you to do something like this:

 

HorizontalFieldManager manager = new HorizontalFieldManager(Field.USE_ALL_WIDTH) {
protected void sublayout(int maxWidth, int maxHeight) {
int nextAvailablePosition = 0;
int fieldCount = this.getFieldCount();
for (int i = 0; i < fieldCount; i++) {
layoutChild(getField(i), (maxWidth / 4), getPreferredHeightOfChild(getField(i)));
setPositionChild(getField(i), nextAvailablePosition, 0);
nextAvailablePosition += (maxWidth / 4);
}
setExtent(getScreen().getHeight(), getPreferredHeight());
}
};
manager.add(new ButtonField("Button 1"));
manager.add(new ButtonField("Button 2"));
manager.add(new ButtonField("Button 3"));
manager.add(new ButtonField("Button 4"));

And yes, I suggest you to forget about the VerticalFieldManager because I don't see it's usefulness.

 

I hope this one solves your issue. I tested it and it worked for me.


Let me know if this was helpful or if you have a solution.

Johan Guzmán - In case my answer pleased you, give a press to the LIKE button, please!! Mark this post as solution if it solved your problem.
Please use plain text.
Developer
mapleleafs90
Posts: 374
Registered: ‎02-12-2011
My Device: Bold 9780

Re: CustomFields and getPreferredHeight() override

[ Edited ]

Hi, yes it works for laying out the buttons. I used VFM originally because getPreferredWidth in the buttons was screwy, with the padding and all it was difficult to set the correct width.

Your solution works partially.

Problem is in a custom field you need to override getPreferredHeight()

In your solution above, getpreferredheight returns 21 at first (after I added all the buttons) and then once the screen is actually active and I can see it its much bigger than 21 (about 40 pixels).

If I override getPreferredHeight for this manager and return 40, after I add the buttons it does return 40 and after the screen is active it returns 40 too. So when I am setting up my background using this height I get the correct height at first.

Without overriding getPreferredHeight, at first check in the constructor where I create these fields it returns 21 for the manager you posted, then I create my background according to this incorrect information. Then after it is really 40 so the background is not right.

See this
http://www.blackberry.com/developers/docs/5.0.0api/net/rim/device/api/ui/Field.html

It has to do with this

Creating your own custom fields
To design your own custom field, you must (at least) implement the layout and paint abstract methods to provide the behavior needed by your field.

You should also override the getPreferredWidth and getPreferredHeight methods, to ensure proper layout within some of the layout managers.

Thank you again!

Please use plain text.
Developer
johanguzman07
Posts: 102
Registered: ‎07-26-2011
My Device: Not a blackberry user

Re: CustomFields and getPreferredHeight() override

Hello again, guy.

 

I tried with a custom button field and my result was constant: 29 before and after screen got activated.

 

You probably could have some bad layout code or something. Take this as an example (actually, this is the code working for me) and figure out what you are missing.

 

The custom field laying out methods:

 

import net.rim.device.api.ui.Color;
import net.rim.device.api.ui.Field;
import net.rim.device.api.ui.Graphics;

public class CustomButtonField extends Field {

	private static final int Y_PADDING = 8;
	private static final int X_PADDING = 8;
	
	private String label;
	private int backgroundColor;
	private int foregroundColor;
	private int focusedForegroundColor;
	private int focusedBackgroundColor;
	
	public CustomButtonField(String label, long style) {
		super(style);
		this.label = label;
		this.backgroundColor = Color.LIGHTGRAY;
		this.foregroundColor = Color.BLACK;
		this.focusedForegroundColor = Color.WHITE;
		this.focusedBackgroundColor = Color.BLACK;
	}

	protected void layout(int width, int height) {		
		setExtent(getPreferredWidth(), getPreferredHeight());
	}

	protected void paint(Graphics graphics) {
		int bgColor = 0;
		int fgColor = 0;
		if (isFocus()) {
			bgColor = focusedBackgroundColor;
			fgColor = focusedForegroundColor;
		}
		else {
			bgColor = backgroundColor;
			fgColor = foregroundColor;
		}
		graphics.setColor(bgColor);
		graphics.fillRoundRect(1, 1, getPreferredWidth() - 2, getPreferredHeight() - 2, 12, 12);
		graphics.setColor(Color.WHITE);
		graphics.setGlobalAlpha(100);
		graphics.fillRoundRect(3, 3, getPreferredWidth() - 6, getPreferredHeight() / 2, 12, 12);
		graphics.setGlobalAlpha(255);
		graphics.setColor(fgColor);
		graphics.drawText(label, X_PADDING / 2, Y_PADDING / 2);
	}
	
	public int getPreferredHeight() {
		return getFont().getHeight() + Y_PADDING;
	}
	
	public int getPreferredWidth() {
		return getFont().getAdvance(label) + X_PADDING;
	}

          //The other methods you have to implement to manage focus and key listening go here
}

 

 I used the code provided in my previous post to set a manager to these buttons, but making instances of CustomButtonField class instead of ButtonField.

 

Check it out and let me know if it works.

 


Let me know if this was helpful or if you have a solution.

Johan Guzmán - In case my answer pleased you, give a press to the LIKE button, please!! Mark this post as solution if it solved your problem.
Please use plain text.