はじめに
Androidは端末の種類が豊富なので、アプリの見た目には気をつけたいところです。
TextViewもその1つで、どうしてもテキスト全文表示させたいのに「...」で省略されてしまうことがあります。
下の画像はTextViewにmaxLines = 1
を指定した場合に省略される例です。
対策
テキストの長さを変えないのであれば、テキストサイズを変えましょう!
「TextViewの横幅」と「中身のテキストの横幅」を比較して、横幅が 『TextView > テキスト』 になればいいのです。
テキストサイズを変えるコード
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.width
やpaint.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_DIP
やTypedValue.COMPLEX_UNIT_SP
などもあります。