はじめに
Androidアプリ開発において、様々な画面サイズやテキストの長さに対応するため、TextViewのフォントサイズを自動調整したい場面は多々あります。
Android 8.0(API 26)以降ではautoSizeTextType
属性が利用できます。
こちらは以前記事にしました。
画面の表示サイズ(dpi)変更に耐えられるLayoutを定義する
この方法だと対応できないケースがあり微調整できません。より細かい制御が必要な場合やカスタマイズが必要な場合は、独自のTextViewを実装する必要があります。
本記事では、AppCompatTextViewを継承してフォントサイズを自動調整するカスタムTextViewをKotlinで実装する方法を紹介します。
要件
- AppCompatTextViewを継承
- onMeasure()内でフォントサイズを調整
- 最小フォントサイズをdp単位で指定可能
- シンプルで軽量な実装
実装
import android.content.Context
import android.graphics.Paint
import android.util.AttributeSet
import android.util.TypedValue
import androidx.appcompat.widget.AppCompatTextView
class AutoResizeTextView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : AppCompatTextView(context, attrs, defStyleAttr) {
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
adjustTextSizeToFit()
}
/**
* テキストサイズを利用可能なスペースに合わせて自動調整する
* @param minSizeDp 縮小時の最小サイズ(dp)。nullの場合は現在のサイズを基準とする
*/
fun adjustTextSizeToFit(minSizeDp: Int? = null) {
val text = text?.toString() ?: return
if (text.isEmpty()) return
val availableWidth = measuredWidth - paddingLeft - paddingRight
if (availableWidth <= 0) return
val currentTextSize = textSize
val minTextSize = minSizeDp?.let { dpToPx(it) } ?: currentTextSize
val paint = Paint().apply { textSize = currentTextSize }
var adjustedSize = currentTextSize
while (paint.measureText(text) > availableWidth && adjustedSize > minTextSize) {
adjustedSize--
paint.textSize = adjustedSize
}
if (adjustedSize != currentTextSize) {
setTextSize(TypedValue.COMPLEX_UNIT_PX, adjustedSize)
}
}
private fun dpToPx(dp: Int): Float = dp * resources.displayMetrics.density
}
使用方法
XMLレイアウトでの使用
<com.yourpackage.AutoResizeTextView
android:layout_width="200dp"
android:layout_height="50dp"
android:text="自動調整されるテキスト"
android:textSize="16sp"
android:gravity="center" />
コードでの使用
val autoTextView = findViewById<AutoResizeTextView>(R.id.autoTextView)
// デフォルトサイズで自動調整
autoTextView.text = "長いテキストが入ります"
// 最小10dpまで縮小を許可
autoTextView.adjustTextSizeToFit(10)
// テキスト変更後に再調整
autoTextView.text = "新しいテキスト"
autoTextView.adjustTextSizeToFit(8)
動作例
元のテキスト | 調整後 |
---|---|
![]() |
![]() |
テキストが長い場合、自動的にフォントサイズが縮小されて、指定した領域内に収まります。
カスタマイズのポイント
最大サイズの制限
現在の実装では縮小のみ対応していますが、拡大も対応したい場合は以下のような拡張が可能です:
fun adjustTextSizeToFit(minSizeDp: Int? = null, maxSizeDp: Int? = null) {
// 最大サイズの処理を追加
val maxTextSize = maxSizeDp?.let { dpToPx(it) } ?: currentTextSize * 2
// 拡大処理のロジックを追加
}
まとめ
この実装により、以下のメリットが得られます:
- シンプル: 必要最小限の機能に絞った軽量な実装
- 柔軟性: 最小サイズを動的に指定可能
- 効率性: 早期リターンと最適化されたアルゴリズム
- 拡張性: 必要に応じてカスタマイズ可能
Androidでフォントサイズの自動調整が必要な場面で、ぜひ活用してみてください。