0
0

テキストを装飾する -SpannableString-

Posted at

SpannableStringとは?

概要

・文字列にさまざまな装飾やスタイル設定を行えるようにするためのもの
・一つの文字列に対して複数のスタイルを適用させることができる

注意点

・例として掲載しているコードはViewBindingを使用しています
 (変数bとして定義しています)

主な種類

クラス名 概要
ForgroundColorSpan テキストの色を変更する
BackgroundColorSpan テキストの背景色を変更する
StyleSpan テキストを太文字やイタリックにする
TypefaceSpan 指定フォントを適用する
RelativeSizeSpan テキストのサイズを相対的に変更する
AbsoluteSizeSpan テキストのサイズを絶対値で変更する
URLSpan テキストをリンクにする
UnderlineSpan テキストに下線を引く
StrikethroughSpan テキストに取り消し線を引く
ImageSpan テキストを指定した文字に置き換える

・他にもクリック可能にして、任意のアクションを実行するClickableSpanや、インデントを設定するLeadingMarginSpan、箇条書きの丸を追加するBulletSpanなどもあります

使い方

どのSpanクラスを使用するにしても、スタイルを適用する流れは共通です

  1. SpannnableStringに文字列を渡す
  2. SpannableString.setSpanを使用して文字列に装飾する
  3. TextViewなどに文字列を渡す

例: 文字列に下線を引きたい場合

fun underLineSpan(){
    val sampleText = "このテキストに下線を引きます"
    //textをSpannableStringにする
    val spannableString = SpannableString(sampleText)
    //setSpanメソッドを使用してスタイルを設定
    spannableString.setSpan(
        UnderlineSpan(),
        0,
        sampleText.length,
        Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
    )
    //TextViewに文字列を渡す
    b.underLineText.text = spannableString
}

setSpanについて

・setSpanメソッドには4つの引数があります

  1. 適用するSpanクラス
  2. 適用を開始する文字のindex
  3. 適用を終了する文字のindex
  4. Span範囲の扱い方を指定するフラグ

・3の終了のインデックスに関しては指定したインデックス-1までの箇所に適用されます

例: 文字列が HelloWorldの場合

spannableString.setSpan(
    UnderlineSpan(), //使用するSpanクラス
    0, //開始のインデックス
    5, //終了のインデックス
    Spannable.SPAN_EXCLUSIVE_INCLUSIVE //終了のインデックスを含まない
)

とすると、

Screenshot 2024-08-14 at 14.24.41.png

このように下線が引かれます

サンプル

UnderlineSpan

Screenshot 2024-08-14 at 14.30.35.png

 private fun setUnderSpan() {
        val sampleText = "ここが重要です"
        val spannableString = SpannableString(sampleText)
        spannableString.setSpan(
            UnderlineSpan(),
            0,
            sampleText.length,
            Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
        )
        b.underLineText.text = spannableString
    }

ForegroundColorSpan

Screenshot 2024-08-14 at 14.32.25.png

 private fun setForegroundColorSpan() {
        val sampleText = "Black and Red Text."
        val spannableString = SpannableString(sampleText)
        spannableString.setSpan(
            ForegroundColorSpan(Color.RED),
            sampleText.indexOf('R'),
            sampleText.length,
            Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
        )
        b.textColorText.text = spannableString
    }

BackgroundColorSpan

Screenshot 2024-08-14 at 14.35.44.png

private fun setBackgroundSpan() {
        val sampleText = "change Background Color."
        val spannableString = SpannableString(sampleText)
        spannableString.setSpan(
            BackgroundColorSpan(Color.RED),
            sampleText.indexOf('B'),
            sampleText.length,
            Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
        )
        b.backGroundColorText.text = spannableString
    }

StyleSpan

Screenshot 2024-08-14 at 14.36.19.png

fun setTextStyleSpan() {
        val sampleText = "通常の文字と太文字"
        val spannableString = SpannableString(sampleText)
        spannableString.setSpan(
            StyleSpan(Typeface.BOLD),
            sampleText.indexOf('太'),
            sampleText.length,
            Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
        )
        b.styleText.text = spannableString
    }

RelativeSizeSpan

Screenshot 2024-08-14 at 14.36.28.png

fun setRelativeSizeSpan() {
        val sampleText = "normal text size and big size text."
        val spannableString = SpannableString(sampleText)
        spannableString.setSpan(
            RelativeSizeSpan(2f), //元の文字サイズの2倍
            sampleText.indexOf('b'),
            sampleText.length,
            Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
        )
        b.relativeText.text = spannableString
    }

StrikethroughSpan

Screenshot 2024-08-14 at 14.36.34.png

fun setStrikethroughSpan() {
        val sampleText = "Original price $100"
        val spannableString = SpannableString(sampleText)
        spannableString.setSpan(
            StrikethroughSpan(),
            0,
            sampleText.length,
            Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
        )
        b.strikeThroughText.text = spannableString
    }

ImageSpan

Screenshot 2024-08-14 at 14.42.30.png

fun setImageSpan() {
        val sampleText = "Hello,Android."
        val spannableString = SpannableString(sampleText)
        spannableString.setSpan(
            ImageSpan(this@MainActivity, android.R.drawable.sym_def_app_icon),
            sampleText.indexOf('A'),
            sampleText.length,
            Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
        )
        b.imageSpanText.text = spannableString
    }

余談

・一部のものに関してはSpannableStringを使用しない方法でも再現できます

アンダーラインについて

・文字列があらかじめ決まっている場合、res/values/strings.xml内で

<resources>
    <string name="underline_text"><u>下線</u>を引きます</string>
</resources>

このように<u>タグで下線を引くことでできます

URLリンクについて

TextViewで、

   <TextView
        android:autoLink="web"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

このようにautoLinkwebを指定することで自動的にURLをリンクにできます
また、autoLinkは他にも電話番号やemailなどもリンクにできます

詳細・参照

・SpannableStringクラス
https://developer.android.com/reference/kotlin/android/text/SpannableString
・Spannableクラス
https://developer.android.com/reference/android/text/Spannable
・Android developers ガイド
https://developer.android.com/develop/ui/views/text-and-emoji/spans?hl=ja

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