Android: button with rotated (vertical) text

13 10 2012

If you want to build button with vertical text like that:

Vertical Button

You can override standard button and its onDraw() method. There you have to rotate text before drawing it. Same thing can be done with TextView – since button actually is extended TextView.

1. Write your own Button implementation

Here is code that actually you can copy-paste to your poject:

public class VerticalButton extends Button{
	final boolean topDown;

	public VerticalButton(Context context, AttributeSet attrs){
		super(context, attrs);
		final int gravity = getGravity();
		if(Gravity.isVertical(gravity) && (gravity&Gravity.VERTICAL_GRAVITY_MASK) == Gravity.BOTTOM) {
			setGravity((gravity&Gravity.HORIZONTAL_GRAVITY_MASK) | Gravity.TOP);
			topDown = true;
		}else
			topDown = false;
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){
		super.onMeasure(heightMeasureSpec, widthMeasureSpec);
		setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());
	}

	@Override
	protected void onDraw(Canvas canvas){
		TextPaint textPaint = getPaint(); 
		textPaint.setColor(getCurrentTextColor());
		textPaint.drawableState = getDrawableState();

		canvas.save();

		if(topDown){
			canvas.translate(getWidth(), 0);
			canvas.rotate(90);
		}else {
			canvas.translate(0, getHeight());
			canvas.rotate(-90);
		}

		canvas.translate(getCompoundPaddingLeft(), getExtendedPaddingTop());
		getLayout().draw(canvas);
		canvas.restore();
	}
}

As you see – there is topDown flag. Depending on it the text will be rotated left or right (read from top to down or from down to top). This flag is set depending on the gravity defined in your layout.xml (set grafity to BOTTOM or TOP to see difference).

2. Place vertical button in activity

Do it by drag and drop in graphical layout editor (choose Custom & Library Views – Vertical button will be visible here since it extends some standard android view):

Vertical Button in graphical editor

or write xml code in layout.xml:

<pl.looksok.utils.VerticalButton
    android:id="@+id/verticalButton"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/verticalButton" />

please notice that package name of VerticalButton.java has to be written here (pl.looksok.utils).

3. That’s all!

Note: This code was found somewhere in the Internet (I can’t claim credit) – I really don’t remember wherefrom I took it :)

Did I help you?
I manage this blog and share my knowledge for free sacrificing my time. If you appreciate it and find this information helpful, please consider making a donation in order to keep this page alive and improve quality

Donate Button with Credit Cards

Thank You!

Advertisements

Actions

Information

6 responses

24 10 2013
Tomas

Hi, how i center text in this button?
Thanks

24 10 2013
Jacek Milewski

Sincerely… I don’t know good way how to do it. I did this with paddings inside button

20 08 2014
armin aray

Thanks for the code. i did some changes to center the button Text. i only changed the “onDraw(Canvas)”. Here is the code. I hope you like it.
@SuppressLint(“DrawAllocation”)
@Override
protected void onDraw(Canvas canvas){
TextPaint textPaint = getPaint();
textPaint.setColor(getCurrentTextColor());
textPaint.drawableState = getDrawableState();

Rect bounds = new Rect();
textPaint.getTextBounds(getText().toString(), 0, getText().length(), bounds);
int textWidth= bounds.height();
int widthLocation =Math.abs( ((getMeasuredWidth()/2)-(textWidth/2)));

canvas.save();

if(topDown){
canvas.translate(getWidth(), 0);
canvas.rotate(90);
}else {
canvas.translate(0, getHeight());
canvas.rotate(-90);
}

canvas.translate(getCompoundPaddingLeft(), widthLocation);
getLayout().draw(canvas);
canvas.restore();
}

20 08 2014
Jacek Milewski

thanks for sharing!

2 04 2015
RaikeN

Hi, the text isn’t centered with that snippet either if you set a padding.
Try to replace this line:

int widthLocation =Math.abs( ((getMeasuredWidth()/2)-(textWidth/2)));

with:

int widthLocation =Math.abs(((getMeasuredWidth()-(getCompoundPaddingLeft()/2))/2)-(bounds.height()/2));

You could probably check with an if statement if a padding is set.
(Only works if all 4 paddings are the same size)

2 04 2015
RaikeN

Edit:
int widthLocation =Math.abs(((getMeasuredWidth()-(getCompoundPaddingLeft()/2))/2)-(textWidth/2));

deleted the line above, so bounds.height() is wrong.

Give Your feedback:

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s




%d bloggers like this: