0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Android】フォントサイズ自動調整TextViewの作り方

Posted at

はじめに

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)

動作例

元のテキスト 調整後
スクリーンショット 2025-05-30 20.33.44.png スクリーンショット 2025-05-30 20.33.54.png

テキストが長い場合、自動的にフォントサイズが縮小されて、指定した領域内に収まります。

カスタマイズのポイント

最大サイズの制限

現在の実装では縮小のみ対応していますが、拡大も対応したい場合は以下のような拡張が可能です:

fun adjustTextSizeToFit(minSizeDp: Int? = null, maxSizeDp: Int? = null) {
    // 最大サイズの処理を追加
    val maxTextSize = maxSizeDp?.let { dpToPx(it) } ?: currentTextSize * 2
    
    // 拡大処理のロジックを追加
}

まとめ

この実装により、以下のメリットが得られます:

  • シンプル: 必要最小限の機能に絞った軽量な実装
  • 柔軟性: 最小サイズを動的に指定可能
  • 効率性: 早期リターンと最適化されたアルゴリズム
  • 拡張性: 必要に応じてカスタマイズ可能

Androidでフォントサイズの自動調整が必要な場面で、ぜひ活用してみてください。

参考リンク

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?