Освой программирование играючи

Сайт Александра Климова

Шкодим

/* Моя кошка замечательно разбирается в программировании. Стоит мне объяснить проблему ей - и все становится ясно. */
John Robbins, Debugging Applications, Microsoft Press, 2000

Вертикальный TextView

Создадим новый компонент на основе TextView, который будет выводить текст вертикально.

Сначала создадим стили для будущего вертикального текста:

res/values/styles.xml


<?xml version="1.0" encoding="utf-8"?>
<resources
    xmlns:android="http://schemas.android.com/apk/res/android">
    <style name="verticalTextStyle"
        parent="android:Widget.TextView">
        <item name="android:padding">20dp</item>
        <item name="android:textSize">20sp</item>
    </style>
</resources>

Также создайте строковый ресурс в файле res/values/strings.xml:


<string name="vtext">Вертикальный текст</string>

Далее напишем отдельный класс для нового компонента. В старом варианте, который писался несколько лет назад, я использовал TextView, но сейчас студия стала советовать использовать AppCompatTextView и я согласился:


package ru.alexanderklimov.verticaltext;

import android.content.Context;
import android.graphics.Canvas;
import android.support.annotation.Nullable;
import android.support.v7.widget.AppCompatTextView;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.view.Gravity;

public class VerticalTextView extends AppCompatTextView {

    final boolean topDown;
    TextPaint textPaint = getPaint();

    public VerticalTextView(Context context, @Nullable 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 = false;
        } else {
            topDown = true;
        }
    }

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

    @Override
    protected void onDraw(Canvas canvas) {

        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();
    }
}

Чтобы добавить компонент в режиме дизайна, выбираем Advanced и переносим на форму элемент <view>, откроется диалоговое окно, в котором нужно найти свой класс. В таком варианте компонент будет представлен следующим образом.


<view
    android:id="@+id/verticalTextView2"
    style="@style/verticalTextStyle"
    class="ru.alexanderklimov.helloworld.VerticalTextView"
... />

Можно использовать другой привычный формат. Чтобы менять направление текста, поиграйтесь с атрибутом android:gravity:


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal" >

    <ru.alexanderklimov.verticaltext.VerticalTextView
        android:id="@+id/verticalTextView1"
        style="@style/verticalTextStyle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/vtext" />

    <ru.alexanderklimov.verticaltext.VerticalTextView
        android:id="@+id/verticalTextView2"
        style="@style/verticalTextStyle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="bottom|right"
        android:text="@string/vtext" />

</LinearLayout>

Вертикальный текст

Пример может послужить отправной точкой для дальнейшего улучшения.

Текст под углом

Для развлечения напишем новый компонент, который будет выводить текст под разными углами, образуя солнышко.


package ru.alexanderklimov.custom;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.support.v7.widget.AppCompatTextView;
import android.text.TextPaint;
import android.util.AttributeSet;

public class RotateTextView extends AppCompatTextView {

    private TextPaint mPaint = getPaint();

    public RotateTextView(Context context) {
        super(context);

        init();
    }

    public RotateTextView(Context context, AttributeSet attrs) {
        super(context, attrs);

        init();
    }

    public RotateTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        init();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int viewWidth = getWidth();
        int viewHeight = getHeight();
        canvas.translate(viewWidth / 2, viewHeight / 2);
        for (int i = 0; i < 10; i++) {
            String message = "Котик";
            canvas.drawText(message, 30, 0, mPaint);
            canvas.rotate(36);
        }
    }

    private void init(){
        mPaint.setColor(Color.BLUE);
        mPaint.setTextSize(50);
        mPaint.setAntiAlias(true);
    }
}

Размещаем:


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <ru.alexanderklimov.custom.RotateTextView
        android:id="@+id/rotateTextView1"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

Реклама