0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Spannableを使ったTextViewでEllipsizeを実現する

Posted at

デフォルトのTextViewはSpannableを使うとEllipsizeがきかなくなるので、TextViewを継承して以下のような子クラスを作ってあげる。
(android:ellipsize="end"かつandroid:maxLinesを設定していないとき相当)

/**
 * SpannableStringを使用していてもEllipsize==Endの挙動をするTextView
 *
 * 参考 : https://www.programmersought.com/article/20037202696/
 */
class SpannableEllipsizeTextView : androidx.appcompat.widget.AppCompatTextView {


    constructor(context: Context) : super(context)
    constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)

    /**
     * Note: when spannableString sets the Spannable object to spannableString, use the flag value of Spannable.SPAN_EXCLUSIVE_EXCLUSIVE, otherwise the subsequent concatenated string may not be displayed
     */
    override fun onDraw(canvas: Canvas?) {
        var lineIndex = 0

        while (lineIndex < lineCount) {
            val charSequence = text
            val bottom = layout.getLineBottom(lineIndex)
            if (bottom > measuredHeight) {
                // もし、途中で見切れるor完全に隠れる行があったら、その直前の行に…を追加して以降は切る。
                val lastCharDown = layout.getLineStart(lineIndex) - 1 // 前の行の最後の文字の文全体でのindex。0始まり。
                val spannableStringBuilder = SpannableStringBuilder()
                spannableStringBuilder.append(charSequence.subSequence(0, lastCharDown + 1)).append("...")
                if (charSequence is Spannable) {
                    // ...の部分も色などを整える
                    // 直前の文字に揃える
                    // XXX この部分は、使用されている可能性があるものに合わせてください。
                    // 今回はForegroundColorSpanとRelativeSizeSpanが使用されている可能性があると想定しています。
                    val spanColor = charSequence.getSpans<ForegroundColorSpan>(lastCharDown, lastCharDown + 1)
                    val spanSize = charSequence.getSpans<RelativeSizeSpan>(lastCharDown, lastCharDown + 1)
                    if (spanColor.size > 0) {
                        spannableStringBuilder.setSpan(ForegroundColorSpan(spanColor[0].foregroundColor), // XXX 新しいインスタンスにしないと、元々かかっていた部分がspanがかからなくなってしまうので注意。
                                lastCharDown,
                                lastCharDown + 3,
                                Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
                    }
                    if (spanSize.size > 0) {
                        spannableStringBuilder.setSpan(RelativeSizeSpan(spanSize[0].sizeChange),
                                lastCharDown,
                                lastCharDown + 3,
                                Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
                    }
                }
                text = spannableStringBuilder
                break
            }
            lineIndex++
        }

        super.onDraw(canvas)
    }
}

参考

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?