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
Posts: 113
Registered: ‎09-30-2009
My Device: Bold 9700
Accepted Solution

Custom button field has two tops?!

[ Edited ]

I am trying to create a custom button field so that I can have two lines of text - but I am getting a second top so-to-speak (a second area with the shading/etc. that the top of a button field has).

 

Here is a screen shot of it

 

Screenshot of custom buttons

 

The bottom button is just a regular button.

 

Code for custom button field:

package com.smartmech.bb;

import net.rim.device.api.system.Display;
import net.rim.device.api.ui.Color;
import net.rim.device.api.ui.Font;
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.Ui;
import net.rim.device.api.ui.component.ButtonField;

public class _customButtonField extends ButtonField {
		private int setWidth;
		private int setHeight;
		private boolean disabled = false;
		private String lblTxt1;
		private String lblTxt2 = "";
		
		_customButtonField( String text, int Width, int Height, long setStyle) {
			super(text, setStyle);
			setWidth = Width;
			setHeight = Height;
			lblTxt1 = text;
		} //customButtonField
		
		_customButtonField( String text, String text2, int Width, int Height, long setStyle) {
			super("",setStyle);
			setWidth = Width;
			setHeight = Height;
			lblTxt1 = text;
			lblTxt2 = text2;
		} //customButtonField
		
		public int getPreferredWidth() {
			return setWidth;
		} //getPreferredWidth

		public int getPreferredHeight() {
			return setHeight;
		} //getPreferredWidth
		
		public boolean isFocusable() {
	        if(disabled)
	            return false; 
	        return true;
	    } //isFocusable
		
		public void disable() {
	        disabled=true;
	        super.setVisualState(ButtonField.VISUAL_STATE_DISABLED);
	    } //disable
	    
	    public void enable() {
	        disabled=false;        
	        super.setVisualState(ButtonField.VISUAL_STATE_NORMAL);
	    } //enable
	    
	    protected void layout(int width, int height) {	
			
			String platform = net.rim.device.api.system.DeviceInfo.getPlatformVersion();
			
			if (platform.substring(0,1).equals("5")) {
				setExtent(setWidth, setHeight); //works in v5	
			}
			else if (platform.substring(0,1).equals("6")) {
				super.layout(setWidth, setHeight);
				//setExtent(setWidth, setHeight);
			}
			
		} //layout
	    
	    protected void paint(Graphics g){
	    	
	    	super.paint(g);
	    	
	    	if (lblTxt2 != "") {
	    		
	    		int myY = getPreferredHeight() / 2;
	    		int myX = 0;
	    		
	    		int myFH = g.getFont().getHeight();
	    		if (myFH * 2 > getPreferredHeight()) {
	    			myY = getPreferredHeight() - myFH;
	    		}
	    		myX = (getPreferredWidth() - g.getFont().getBounds(lblTxt1)) / 2; 		
	    		g.drawText(lblTxt1, myX,0,0,this.getWidth());
	    		
	    		myX = (getPreferredWidth() - g.getFont().getBounds(lblTxt2)) / 2;
	    		g.drawText(lblTxt2, myX,myY,0,this.getWidth());
	    		
	    	} //lblTxt2 not blank
	    	
	    } //paint
	    
} //customButtonField

 

And calling it:

_customButtonField summaryBtn = new _customButtonField("Location", "Summary", btnWidth, btnHeight, ButtonField.CONSUME_CLICK);
 summaryBtn.setFont(mainFont);

 

Any ideas as to why this is happening?

Developer
Posts: 16,694
Registered: ‎07-29-2008
My Device: Z10 LE, Z30, Passport
My Carrier: O2 Germany

Re: Custom button field has two tops?!

buttonfield is a complicated class, most likely it will be easier to use a custom field instead
----------------------------------------------------------
feel free to press the like button on the right side to thank the user that helped you.
please mark posts as solved if you found a solution.
@SimonHain on twitter
Developer
Posts: 102
Registered: ‎07-26-2011
My Device: Not a blackberry user
My Carrier: None

Re: Custom button field has two tops?!

[ Edited ]

Greetings.

I am totally agree with simon. And that's because you'll end needing to override completely the paint method in order to achieve your purpose.

Try extending from field and drawing and laying out all from within your 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.
Developer
Posts: 2,268
Registered: ‎07-08-2009
My Device: various
My Carrier: various

Re: Custom button field has two tops?!

I once wrote this as an experiment - feel free to use/modify it:

Large ButtonField with label that wraps around

Good luck!

----------------------------------------------------------
please click 'Accept Solution' on posts that provide the solution to the question you've posted. Don't say "Thanks", press 'Like' button instead!
Developer
Posts: 113
Registered: ‎09-30-2009
My Device: Bold 9700

Re: Custom button field has two tops?!

arkadyz:  Great.  Thanks.

 

I have been playing around with that, trying to get it to behave more like the regular buttons.  I can't figure out how to get the text centered.  I have been trying to find out how wide the actual printed text is, but am not sure how to do that. 

 

Using getBounds from the text doesn't work, b/c is uses the bounds of the entire string.  Since we are possibly printing the string across two lines, this doesn't work.

 

If the field label has two lines, how can I find the width of the longer line?

Developer
Posts: 2,268
Registered: ‎07-08-2009
My Device: various
My Carrier: various

Re: Custom button field has two tops?!

To center the text, you can make _label a RichTextField instead of TextField and use TEXT_ALIGH_HCENTER as an additional style bit. If you want to find out the width of the longest line, use _label.getWidth() after layoutChild(_label, ...) call.

----------------------------------------------------------
please click 'Accept Solution' on posts that provide the solution to the question you've posted. Don't say "Thanks", press 'Like' button instead!
Developer
Posts: 113
Registered: ‎09-30-2009
My Device: Bold 9700

Re: Custom button field has two tops?!

Using a RTF worked.  But getWidth doesn't work in this scenario as the label is actually bigger than the text that is in it, so the width is not usable in this way/scenario.

Developer
Posts: 113
Registered: ‎09-30-2009
My Device: Bold 9700

Re: Custom button field has two tops?!

Made a few tweaks, so for anyone looking to have a custom button look more like the regular one (w/o the fade background though) here it is:

package com.smartmech.bb;

import net.rim.device.api.ui.Color;
import net.rim.device.api.ui.Graphics;
import net.rim.device.api.ui.Manager;
import net.rim.device.api.ui.XYRect;
import net.rim.device.api.ui.component.NullField;
import net.rim.device.api.ui.component.RichTextField;
import net.rim.device.api.ui.component.TextField;

public class _multiLineButtonField extends Manager {
	private final static int MAX_LABEL_PADDING = 8; // pixels
	private final static int MIN_LABEL_PADDING = 2; // pixels again
	private final static int NON_FOCUS_COLOR = Color.LIGHTGRAY;
	private final static int FOCUS_COLOR = Color.BLUE;
	private final static int DISABLED_COLOR = Color.GRAY;
	private final static int FONT_COLOR = Color.WHITE;
	private final static int FONT_COLOR_NONFOCUS = Color.BLACK;
	private RichTextField _label;
	private NullField _focusAnchor;
	private int _width;
	private int _height;
	private int _padding;
	int _round = 20; //can be overridden when calling
	private String _labelText;

	public _multiLineButtonField(String labelText, int width, int height, long style) {
		super(style & (FIELD_HALIGN_MASK | FIELD_VALIGN_MASK | USE_ALL_WIDTH | USE_ALL_HEIGHT));
		_label = new RichTextField(style & SPELLCHECKABLE_MASK | READONLY | NON_FOCUSABLE | RichTextField.TEXT_ALIGN_HCENTER);
		_label.setText(labelText);
		add(_label);
		
		_labelText = labelText;
		
		_focusAnchor = new NullField(style & FOCUSABLE_MASK) {
			protected void onFocus(int direction) {
				getManager().invalidate();
				super.onFocus(direction);
			}

			protected void onUnfocus() {
				getManager().invalidate();
				super.onUnfocus();
			}
		};
		add(_focusAnchor);
		_width = width;
		_height = height;
		if (_width < 2 * MIN_LABEL_PADDING) {
			throw new IllegalArgumentException("Not enough width to lay out MultiLineButtonField");
		}
	}

	protected int nextFocus(int direction, int axis) {
		invalidate();
		return -1;
	}

	protected void sublayout(int width, int height) {
		XYRect childRect;
		if ((width < 2 * MIN_LABEL_PADDING) || (height < 2 * MIN_LABEL_PADDING)) {
			throw new IllegalArgumentException("Not enough room to lay out MultiLineButtonField");
		}
		
		layoutChild(_label, Math.min(_width, width) - 2 * MIN_LABEL_PADDING, height - 2 * MIN_LABEL_PADDING);
		
		childRect = _label.getExtent();
		int myWidth = width;
		int myHeight = height;
		if (!isStyle(USE_ALL_WIDTH)) {
			myWidth = Math.min(width, childRect.width + 2 * MAX_LABEL_PADDING);
		}
		if (!isStyle(USE_ALL_HEIGHT)) {
			myHeight = Math.min(height, childRect.height + 2 * MAX_LABEL_PADDING);
		}
		
		_padding = Math.min((myWidth - childRect.width), (myHeight - childRect.height)) / 2;
		setPositionChild(_label, _padding, _padding);
		
		layoutChild(_focusAnchor, 0, 0);
		setPositionChild(_focusAnchor, 0, 0);
		
		//Force button to desired size overall
		myWidth = Math.max(myWidth, _width);
		myHeight = Math.max(myHeight, _height);
		
		setExtent(myWidth, myHeight);
		
	}

	protected void paintBackground(Graphics g) {
		int prevColor = g.getColor();
		int bgColor;
		if (_focusAnchor.isFocusable()) {
			if (_focusAnchor.isFocus()) {
				bgColor = FOCUS_COLOR;
			} else {
				bgColor = NON_FOCUS_COLOR;
			}
		} else {
			bgColor = DISABLED_COLOR;
		}
		g.setColor(bgColor);
		g.fillRoundRect(0, 0, getWidth(), getHeight(), _round, _round);
		g.setColor(prevColor);
	}

	protected void paint(Graphics g) {
		int prevColor = g.getColor();
		int fontColor;
		if (_focusAnchor.isFocusable()) {
			if (_focusAnchor.isFocus()) {
				fontColor = FONT_COLOR;
			} else {
				fontColor = FONT_COLOR_NONFOCUS;
			}
		} else {
			fontColor = FONT_COLOR_NONFOCUS;
		}
		g.setColor(fontColor);
		
		super.paint(g);
		g.setColor(prevColor);
	}
}