[Androidアプリ開発] フォントサイズ自動調整TextViewを作ってみた

2014.08.29

今回は、フォントサイズが自動調整されるTextViewを作ってみました。 iOSでいう「UILabel」の「Autoshrink」で「Minimum...」を設定したときのようなものです。 もしかしたらこれを実現できるプロパティは存在していて、見落としてしまっただけかもしれませんが。。。

AutoshrinkTextView.java

package jp.classmethod.sampletextview;

import android.content.Context;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.widget.TextView;

public class AutoshrinkTextView extends TextView {

	/** 最小のテキストサイズ。 */
	private static final float MIN_TEXT_SIZE = 6.0f;

	/** テキスト幅計測用のペイント。 */
	private Paint mPaint = new Paint();

	/**
	 * コンストラクタ。
	 * 
	 * @param context
	 * @param attrs
	 */
	public AutoshrinkTextView(Context context, AttributeSet attrs) {
		super(context, attrs);
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);

		float measuredWidth = getMeasuredWidth();
		if (measuredWidth > 0) {
			shrinkTextSize();
		}
	}

	/**
	 * テキストサイズを縮小します。
	 */
	private void shrinkTextSize() {
		// テキストサイズを取得します。
		float tempTextSize = getTextSize();

		// テキスト幅が入りきっていない場合は、入るまで繰り返します。
		while (getMeasuredWidth() < getTextWidth(tempTextSize)) {
			// テキストサイズを縮小します。
			tempTextSize--;

			if (tempTextSize <= MIN_TEXT_SIZE) {
				// 最小テキストサイズより小さくなった場合は、最小テキストサイズをセットして終了します。
				tempTextSize = MIN_TEXT_SIZE;
				break;
			}
		}

		// 調整した結果のテキストサイズをセットします。
		setTextSize(TypedValue.COMPLEX_UNIT_PX, tempTextSize);
	}

	/**
	 * テキスト幅を取得します。
	 * 
	 * @param text
	 * @param textSize
	 * @return
	 */
	float getTextWidth(float textSize) {
		mPaint.setTextSize(textSize);
		float textWidth = mPaint.measureText(getText().toString());
		return textWidth;
	}
}

 

では、試してみます。サンプルのレイアウトはこちら。

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="${relativePackage}.${activityClass}" >

    <jp.classmethod.sampletextview.AutoshrinkTextView
        android:id="@+id/autoshrinkTextView1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:text="classmethod"
        android:textSize="30sp" />

    <jp.classmethod.sampletextview.AutoshrinkTextView
        android:id="@+id/autoshrinkTextView2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_below="@+id/autoshrinkTextView1"
        android:layout_marginTop="10dp"
        android:text="classmethod_classmethod_classmethod"
        android:textSize="30sp" />

    <jp.classmethod.sampletextview.AutoshrinkTextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_below="@+id/autoshrinkTextView2"
        android:layout_marginTop="10dp"
        android:text="classmethod_classmethod_classmethod_classmethod_classmethod"
        android:textSize="30sp" />

</RelativeLayout>

実行結果がこちら。

android-font-fit-text-view

動きました。 ただし、これは1行のときにしか対応していません。複数行対応版はまた今度。

ではでは。