Recently I was working on a project where I had free reign over the UI, and felt that it would be very nice to have some vertically oriented text. On searching through the Android API docs, I found that rotating Views isn’t supported directly, but a quick Google search found a number of approaches. In this article we’ll explore a couple of different methods for displaying vertical text in Android.
Before we begin, let’s discuss what I was trying to achieve. I wanted the text rotated through 90 degrees anti-clockwise. To achieve this we need to move our text to the right by a distance equal to its own height, down by a distance equal to its own width, and then rotate it by -90 around its bottom left corner. So, if we start with the following text:
We want this to appear as follows:
As I have often said on this blog: There are usually multiple was of achieving your desired results on Android, and this case is no different.
Let’s start by creating a new 4.0.3 project with minSdk=”1.6″ named VerticalText, with a package name of
com.stylingandroid.verticaltext, and a default activity named VerticalTextActivity.
Next, we’ll create a style in res/values/styles.xml which we’l use later:
<?xml version="1.0" encoding="utf-8"?>
Next we’ll replace the default string named
hello with one named
text to res/values/strings.xml:
<?xml version="1.0" encoding="utf-8"?>
<string name="text">Vertical Text</string>
We’re now ready to look at how we achieve the rotation of the text that we require. The first option that I found was on StackOverflow where a user named “mice” outlined a custom control to display rotated text. Let’s create a new class named
VerticalTextView which is an exact copy of mice’s solution
public class VerticalTextView extends TextView
final boolean topDown;
public VerticalTextView( Context context,
AttributeSet attrs )
super( context, attrs );
final int gravity = getGravity();
if ( Gravity.isVertical( gravity )
&& ( gravity & Gravity.VERTICAL_GRAVITY_MASK )
== Gravity.BOTTOM )
( gravity & Gravity.HORIZONTAL_GRAVITY_MASK )
| Gravity.TOP );
topDown = false;
topDown = true;
protected void onMeasure( int widthMeasureSpec,
int heightMeasureSpec )
protected void onDraw( Canvas canvas )
TextPaint textPaint = getPaint();
textPaint.setColor( getCurrentTextColor() );
textPaint.drawableState = getDrawableState();
if ( topDown )
canvas.translate( getWidth(), 0 );
canvas.rotate( 90 );
canvas.translate( 0, getHeight() );
canvas.rotate( -90 );
getLayout().draw( canvas );
This is quite straightforward. In the constructor it is tweaking the gravity of the underlying TextView to switch the orientation of the gravity to match the rotation of the text. It overrides the
onMeasure() method to swap the width and height of the control to match the final dimensions of the rotated text. Finally it overrides
onDraw() and applies a rotation dependent on the gravity setting.
We can now change our main layout in res/layout/main.xml to include a VerticalTextView control:
We are using the style and string values that we defined earlier, and we need to set the gravity to
bottom|right in order to get the text in the orientation that we want. Please feel free to have a play with different values here to explore how the gravity affects things.
If we run this, we get the desired result:
This works quite nicely but, as mice says in his answer, it does have certain limitations such as handling marquees. There are also some other similar approaches in other answers to the same question, but they all have certain limitations of one kind or another. I’m not going to bother explaining them all here because they are all variations upon the same concept of creating a custom control.
In the concluding part of this series we’ll look at another method which uses a standard TextView control and doesn’t break any of its functionality.
The source code for this article can be found here.
© 2012, Mark Allison. All rights reserved.
Copyright © 2012 Styling Android. All Rights Reserved.
Information about how to reuse or republish this work may be available at http://blog.stylingandroid.com/license-information.