【Android】文字の一部を装飾する

■ 文字の一部を小さくする

※R.id.testにはHello world!が設定されています。

SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder();
TextView testTextView = (TextView) findViewById(R.id.test);
String testText = (String) testTextView.getText();
spannableStringBuilder.append(testText);
RelativeSizeSpan relativeSizeSpan = new RelativeSizeSpan(0.5f);
spannableStringBuilder.setSpan(
       relativeSizeSpan,
       testText.indexOf("world") - 1,
       testText.indexOf("world") - 1 + "world".length(),
       Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
   );
testTextView.setText(spannableStringBuilder);

■ 文字の一部を大きくする

SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder();
TextView testTextView = (TextView) findViewById(R.id.test);
String testText = (String) testTextView.getText();
spannableStringBuilder.append(testText);
RelativeSizeSpan relativeSizeSpan = new RelativeSizeSpan(1.5f);
spannableStringBuilder.setSpan(
        relativeSizeSpan,
        testText.indexOf("world") - 1,
        testText.indexOf("world") - 1 + "world".length(),
        Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
    );
testTextView.setText(spannableStringBuilder);

■ 文字の一部にstyleを適用する

SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder();
TextView testTextView = (TextView) findViewById(R.id.test);
String testText = (String) testTextView.getText();
spannableStringBuilder.append(testText);
TextAppearanceSpan boldTextAppearanceSpan = new TextAppearanceSpan(this, R.style.BoldTextAppearance);
spannableStringBuilder.setSpan(
        boldTextAppearanceSpan,
        testText.indexOf("world") - 1,
        testText.indexOf("world") + "world".length(),
        Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
   );
testTextView.setText(spannableStringBuilder);

■ リンクっぽくする

※この場合だけsetMovementMethodが必要。

TextView testTextView = (TextView) findViewById(R.id.test);
String testText = (String) testTextView.getText();
spannableStringBuilder.append(testText);
spannableStringBuilder.setSpan(
        new ClickableSpan() {
        @Override
        public void onClick(View widget) {
                System.out.println("clicked!");
        }
        },
        testText.indexOf("world") - 1,
        testText.indexOf("world") + "world".length(),
        Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
   );
testTextView.setText(spannableStringBuilder);
testTextView.setMovementMethod(LinkMovementMethod.getInstance());


クリックした感じにしたい場合

    <TextView
        android:id="@+id/testTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/hello_world"
        android:textColorHighlight="@drawable/selector_clickable_text_color_highlight"
        android:textColorLink="@drawable/selector_clickable_text_color_link" />

のようにandroid:textColorHighlightとandroid:textColorLinkで調整できる。

・selector_clickable_text_color_link.xml

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_focused="true" android:state_pressed="false" android:color="#1111cc" />
    <item android:state_focused="true" android:state_pressed="true" android:color="#FF8C00" />
    <item android:state_focused="false" android:state_pressed="true" android:color="#FF8C00" />
    <item android:color="#1111cc" />
</selector>

・selector_clickable_text_color_highlight.xml

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_focused="true" android:state_pressed="false" android:color="@android:color/transparent" />
    <item android:state_focused="true" android:state_pressed="true" android:color="@android:color/transparent" />
    <item android:state_focused="false" android:state_pressed="true" android:color="@android:color/transparent" />
    <item android:color="@android:color/transparent" />
</selector>


※複数のSpanを一つのテキストに設定する場合、setSpanを重ねていけばオッケー。