Android Ticks: display text vertically

TextView of Android is a text label to display text. But it can show text only horizontally by default, left to right or right to left. There are some chances that we would like to show text vertically, top to bottom or bottom to top, for layout of modern smart phone in particular. In landscape layout, the height is not enough to show all information, we have to arrange them horizontally because width is enough to hold them. But for some label, like date and time label, it would be nicer to display them in only one line, which is impossible to do in landscape. The text is one line though, it grows horizontally to push following layouts out of screen, just like this:

But the ideal layout would be like this: one line label shows itself vertical so in horizontal, it takes up only its height and leaves much free space to put other views:

 

Fortunately, this is totally possible in Android only with a little extra efforts. With graphics library we can draw text in any way we want: rotate in some direction, following a path and so forth. An example TextAlign in APIDemos just shows us the way to draw text following a customized Path. We can inherite TextView and override its onDraw(), then do what ever we like in onDraw. In here, of course, to draw the text in a Path that vertically up from bottom. Here is the code:

[java]
/*
 * for the attributes of TextView, some works some not.
 * 1. setTextsize works
 * 2. setBackgroundColor works
 * 3. setTextColor also works
 * You can adjust the size of TextView by margins and the drawing area by paddings(only paddingTop and paddingBottom works).
 * For other attributes, like lines or maxLines, or ellipsize are not supported currently. To support them, you should get 
 * the attributes value before drawText and apply them.
 */ 
public class VerticalTextView extends TextView { 
    private static final String TAG = "VerticalTextView"; 
 
    public VerticalTextView(Context context, AttributeSet attrs, int defStyle) { 
        super(context, attrs, defStyle); 
    } 
 
    public VerticalTextView(Context context, AttributeSet attrs) { 
        super(context, attrs); 
    } 
 
    public VerticalTextView(Context context) { 
        super(context); 
    } 
     
    @Override 
    protected void onDraw(Canvas canvas) { 
        final ColorStateList csl = getTextColors(); 
        final int color = csl.getDefaultColor(); 
        final int paddingBottom = getPaddingBottom(); 
        final int paddingTop = getPaddingTop(); 
        final int viewWidth = getWidth(); 
        final int viewHeight = getHeight(); 
        final TextPaint paint = getPaint(); 
        paint.setColor(color); 
        final float bottom = viewWidth * 9.0f / 11.0f; 
        Path p = new Path(); 
        p.moveTo(bottom, viewHeight – paddingBottom – paddingTop); 
        p.lineTo(bottom, paddingTop); 
        canvas.drawTextOnPath(getText().toString(), p, 0, 0, paint); 
    } 

/*
 * for the attributes of TextView, some works some not.
 * 1. setTextsize works
 * 2. setBackgroundColor works
 * 3. setTextColor also works
 * You can adjust the size of TextView by margins and the drawing area by paddings(only paddingTop and paddingBottom works).
 * For other attributes, like lines or maxLines, or ellipsize are not supported currently. To support them, you should get
 * the attributes value before drawText and apply them.
 */
public class VerticalTextView extends TextView {
    private static final String TAG = "VerticalTextView";

    public VerticalTextView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public VerticalTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public VerticalTextView(Context context) {
        super(context);
    }
   
    @Override
    protected void onDraw(Canvas canvas) {
        final ColorStateList csl = getTextColors();
        final int color = csl.getDefaultColor();
        final int paddingBottom = getPaddingBottom();
        final int paddingTop = getPaddingTop();
        final int viewWidth = getWidth();
        final int viewHeight = getHeight();
        final TextPaint paint = getPaint();
        paint.setColor(color);
        final float bottom = viewWidth * 9.0f / 11.0f;
        Path p = new Path();
        p.moveTo(bottom, viewHeight – paddingBottom – paddingTop);
        p.lineTo(bottom, paddingTop);
        canvas.drawTextOnPath(getText().toString(), p, 0, 0, paint);
    }
}

This VerticalTextView works much like a TextView, it supports most usual attributes like color, size, background, margin and padding(only paddingTop and paddingBottom). For others, I did not implement but you can get the attributes in onDraw and apply them. Cost efforts though, it is feasible. Here is an example to use it:

[html]
<com.hilton.todo.VerticalTextView 
    android:id="@+id/header" 
    android:layout_height="fill_parent" 
    android:layout_width="30dip" 
    android:textColor="#ffff00" 
    android:textSize="24sp" 
    android:background="#a50909" 
    android:text="Hello, world" 
    android:paddingBottom="40dip" /> 

    <com.hilton.todo.VerticalTextView
        android:id="@+id/header"
        android:layout_height="fill_parent"
        android:layout_width="30dip"
        android:textColor="#ffff00"
        android:textSize="24sp"
        android:background="#a50909"
        android:text="Hello, world"
        android:paddingBottom="40dip" />

There might be some other ways to achieve this like rotation, which I tried first but not with success. This example really works for me and if you ever find another way please share to us.

From this example, we learn that Android is so flexible that we can achieve almost anything we want and the only cost is your efforts.

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。