LoginSignup
1
0

More than 5 years have passed since last update.

テキストをTextViewに1行まるまる収める

Posted at

はじめに

Androidは端末の種類が豊富なので、アプリの見た目には気をつけたいところです。
TextViewもその1つで、どうしてもテキスト全文表示させたいのに「...」で省略されてしまうことがあります。

下の画像はTextViewにmaxLines = 1を指定した場合に省略される例です。

スクリーンショット 2018-07-25 20.53.37.png

対策

テキストの長さを変えないのであれば、テキストサイズを変えましょう!
「TextViewの横幅」と「中身のテキストの横幅」を比較して、横幅が 『TextView > テキスト』 になればいいのです。

スクリーンショット 2018-07-25 21.04.07.png

テキストサイズを変えるコード

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, formatTextSize(textView))
}

private fun changeTextSize(textView: TextView): Float {
    // TextViewの横幅
    val textViewWidth = textView.width

    // TextViewのサイズ
    var textSize = textView.textSize

    val paint = Paint()

    // Paintを使ってTextViewのサイズをセット
    paint.textSize = textSize

    // Paintを使ってテキストの横幅を測定
    var textWidth = paint.measureText(textView.text.toString())

    // テキストサイズの最小値
    val min = 1f   

    // 横幅が TextView > テキスト になるまで実行
    while (textViewWidth < textWidth) {
        // テキストのサイズが最小
        if (min >= textSize) {
            textSize = min
            break
        }
        // TextViewのサイズを小さくする
        textSize--
        paint.textSize = textSize

        // テキストの横幅を更新
        textWidth = paint.measureText(textView.text.toString())
    }
    return textSize
}

...これだけではできない!のでさらに対策

ログを見ると明らかになるが、textView.width (= getWidth())0で返ってくる。。
なのでずっとwhileを実行し、テキストサイズがminに達してbreak。テキストが最小化されてしまう。

これの対策として、viewTreeObserverを使います。
onGlobalLayout()の中であれば、textView.widthが正常に返ってくるはずです。

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    // textViewの横幅を取得するため
    val viewTreeObserver = textView.viewTreeObserver
    viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
        override fun onGlobalLayout() {
            textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, formatTextSize(textView))
            textView.viewTreeObserver.removeOnGlobalLayoutListener(this)
        }
    })
}

補足

基本的にtextView.widthpaint.textSize = textSizeなどは全て、dpではなくpxで値を返しています。
そのため単純にtextView.textSize = formatTextSize(textView)してしまうと、予期していたサイズよりも大きく表示されてしまいます。

textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, formatTextSize(textView))は、その解決策です。
第1引数にTypedValue.COMPLEX_UNIT_PXを指定すると、dpに変換してくれる優れものです。
TypedValue.COMPLEX_UNIT_PXの他にTypedValue.COMPLEX_UNIT_DIPTypedValue.COMPLEX_UNIT_SPなどもあります。

1
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
1
0