TextView内に複数のスタイルを含めることは可能ですか?


547

TextView内の異なるテキストに複数のスタイルを設定することは可能ですか?

たとえば、次のようにテキストを設定しています。

tv.setText(line1 + "\n" + line2 + "\n" + word1 + "\t" + word2 + "\t" + word3);

各テキスト要素に異なるスタイルを設定することは可能ですか?たとえば、line1 bold、word1 italicなど。

開発者ガイドの一般的なタスクとAndroidでのそれらの実行方法には、テキストの一部の選択、強調表示、またはスタイル設定が含まれます。

// Get our EditText object.
EditText vw = (EditText)findViewById(R.id.text);

// Set the EditText's text.
vw.setText("Italic, highlighted, bold.");

// If this were just a TextView, we could do:
// vw.setText("Italic, highlighted, bold.", TextView.BufferType.SPANNABLE);
// to force it to use Spannable storage so styles can be attached.
// Or we could specify that in the XML.

// Get the EditText's internal text storage
Spannable str = vw.getText();

// Create our span sections, and assign a format to each.
str.setSpan(new StyleSpan(android.graphics.Typeface.ITALIC), 0, 7, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
str.setSpan(new BackgroundColorSpan(0xFFFFFF00), 8, 19, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
str.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), 21, str.length() - 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

しかし、それはテキスト内の明示的な位置番号を使用します。これを行うためのよりクリーンな方法はありますか?


6
TextView文字列が静的である場合、html <b>、<i>、および<u>タグを文字列リソースファイルに追加するだけで、それらが自動的に適用されます。例:<TextView android:text = "@ string / test" /> @ string / testは<string> <b> bold </ b>、<i> italic </ i> </ string>に設定
greg7gkb

2
+1 @ greg7gkb!キーワードは「静的」です。文字列の一部が<b>で機能し、一部で機能しない理由を考えて髪を引っ張っていました。変数を持たないもの。
スコットビッグス

回答:


694

誰かがこれを行う方法を疑問に思っている場合は、ここに1つの方法があります(Markに再度感謝します!)

mBox = new TextView(context);
mBox.setText(Html.fromHtml("<b>" + title + "</b>" +  "<br />" + 
            "<small>" + description + "</small>" + "<br />" + 
            "<small>" + DateAdded + "</small>"));

このメソッドでサポートされているタグの非公式リストについては、このリンクまたはこの質問を参照してくださいどのHTMLタグがAndroid TextViewでサポートされていますか?


1
@JānisGruzis:おそらくこれを行う1つの方法は、たとえば、formatTextWhite(string text)テキストを次のフォーマット文字列に挿入するだけのスタブメソッドを使用することです"<font size="..." color="..." face="...">%s</font>"
Legend

@Legend <font fgcolor = '#ffff5400'> <b> <big> "+" Title "+" </ big> </ b> </ font>を使用しましたが、fgcolor / color(両方試した)は使用していません作業しています... htmlを使用してカラーを実行する方法を知っていますか
Muhammad Babar

@MuhammadBabar:これを試すことができますHtml.fromHtml("<![CDATA[<font color='#ffff5400'>the html content you already have</font>]]>");か?これはいつか私にとってうまくいったことを覚えています。それでも動作するかどうかはわかりません。
レジェンド

1
@伝説の感謝ですが、回避策Html.fromHtml("<font color=\"#999999\">は私のためにエスケープシーケンスが機能しました:)...
Muhammad Babar

2
なぜこれがmBox..setText(Html.fromHtml("<b>" + name + "</b>") + doNotApplyHTML);
効果を発揮

216

を試してHtml.fromHtml()、太字および斜体のHTMLタグでテキストをマークアップしてください。

Spanned text = Html.fromHtml("This mixes <b>bold</b> and <i>italic</i> stuff");
textView.setText(text);

1
実際には、別の質問が出てきます:htmlテキストを含む1つのtextview、またはhtmlクラスを使用せずにマークアップ設定が異なる3つのテキストビューを使用する方が良いですか?私はそれが明らかに最初のものであることを想定していますが、それを確認したいだけです...
Legend

2
Html.fromHtml()がサポートするタグの完全な一覧が何なのか、私にはわかりません。ソースコードを確認する必要があります。インラインマークアップと複数のTextViewウィジェットは、直交する決定である必要があります。テキストの個別のビットを正確に配置する必要がある場合は、複数のウィジェットを使用します。ウィジェットでマークアップをインライン化する必要がある場合は、インラインマークアップを使用します。覚えておいてください:AndroidにはFlowLayoutがないため、複数のTextViewをつなぎ合わせて段落を作成することは、実際的なAFAIKではありません。
CommonsWare、2009年

1
そのおかげで...実際、<small>タグは機能しました...それで、私はそれをシンプルに保ち、それをそのまま使用します...
Legend

1
@TimBoland:を介してスパンを破棄しますmonthText + " " + month.getYearLabel()。を参照してくださいStringUtils.concat()
CommonsWare 2016年

2
@TimBoland:それをすべて1つにまとめることができます:monthYearLabel.setText(Html.fromHtml("<b>"+month.getMonthLabel().toUpperCase()+"</b>&nbsp;"+month.getYearLabel()))個別のピースが必要ない場合。
CommonsWare 2016年

191

少し話題から外れましたが、これはあまりにも有用であり、ここでは触れられません。

string.xmlリソースからHTMLテキストを読み取り、ローカライズを簡単にしたい場合はどうでしょうか。CDATAはこれを可能にします:

<string name="my_text">
  <![CDATA[
    <b>Autor:</b> Mr Nice Guy<br/>
    <b>Contact:</b> myemail@grail.com<br/>
    <i>Copyright © 2011-2012 Intergalactic Spacebar Confederation </i>
  ]]>
</string> 

Javaコードから、次のように使用できます。

TextView tv = (TextView) findViewById(R.id.myTextView);
tv.setText(Html.fromHtml(getString(R.string.my_text))); 

これがうまくいくとは思っていませんでした。しかし、そうでした。

それがあなたの一部に役立つことを願っています!


2
通常「false」は、ルックアップテーブルの奇妙な値にアクセスしたことを意味します。R.id.okとR.string.okがあったときにこれを取得し、正しいgetString(R.string.ok)の代わりに誤ってgetString(R.id.ok)を使用した
Joe Plante

これはレイアウトXMLでも機能しますか?そこで文字列リソースを参照すると"@string/someText"( "someText"はstrings.xmlで定義されたリソースです)、すべてのHTMLタグを含む文字列を 'text'として取得します。
Gee.E 2013年

3
私はこれが最良の答えだと思った。刺激を受けました。私の2セント相当の答えも入れざるを得ませんでした。ここでのソリューションgist.github.com/aegis1980/b138dcb2fd1b2e98aa30を使用すると、レイアウトファイルで割り当てることができるため、プログラムでテキストリソースを割り当てる必要がありません(Android Studioでプレビューできます)
Jon

127

htmlを使用したくない場合は、styles.xmlを作成して次のように使用できます。

TextView tv = (TextView) findViewById(R.id.textview);
SpannableString text = new SpannableString(myString);

text.setSpan(new TextAppearanceSpan(getContext(), R.style.myStyle), 0, 5, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
text.setSpan(new TextAppearanceSpan(getContext(), R.style.myNextStyle), 6, 10, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

tv.setText(text, TextView.BufferType.SPANNABLE);

作業中の可能性のある単純なAndroidアプリケーションにコピーして貼り付けます。1つのテキストビューに2つのスタイルが適用されることがわかります。
ケントアンデルセン

すみません、よくわかりませんでした。スタイルを適用する場所の部分文字列を(2つのインデックスを介して)指定する必要がある場合、ローカライズされた文字列では機能しません。これは、インデックスはもちろんロケールごとに異なるためです。
Jeffrey Blattman、2012年

あなたは正しいです。複数の言語をサポートしている場合、これは希望するルートではありません。文字列がサイズを変更しないことが確実でない限り(アプリケーション名など)。
ケントアンデルセン、

9
l10nがこのソリューションで機能しない理由がわかりません。1つだけではなく、個別の文字列を取得します。String firstPart = getString(R.string.line1); String secondPart = getString(R.string.line2); Spannable text = new SpannableString(firstPart + secondPart); text.setSpan(new ForegroundColorSpan(Color.parseColor(TEXT_COLOR_FOR_FIRST_PART))、0、firstPart.length()、Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); myTextView.setText(text、TextView.BufferType.SPANNABLE);
2013年

5
@Ruiは、l10nも定位置であるためです。フレーズ内の単語の位置をハードコーディングして、それでもl10nにすることはできません。そのため$1%s is a happy $2%s、文字列バンドルのようなものが表示されます。トークンの再配置を許可する必要があります。
ジェフリーブラットマン2013年

60

SpannableStringHTMLマークアップの代わりに使用する方が軽量です。視覚的な例を見るのに役立ちますので、ここで補足的な答えを示します。

ここに画像の説明を入力してください

これはシングルTextViewです。

// set the text
SpannableString s1 = new SpannableString("bold\n");
SpannableString s2 = new SpannableString("italic\n");
SpannableString s3 = new SpannableString("foreground color\n");
SpannableString s4 = new SpannableString("background color\n");
SpannableString s5 = new SpannableString("underline\n");
SpannableString s6 = new SpannableString("strikethrough\n");
SpannableString s7 = new SpannableString("bigger\n");
SpannableString s8 = new SpannableString("smaller\n");
SpannableString s9 = new SpannableString("font\n");
SpannableString s10 = new SpannableString("URL span\n");
SpannableString s11 = new SpannableString("clickable span\n");
SpannableString s12 = new SpannableString("overlapping spans\n");

// set the style
int flag = Spanned.SPAN_EXCLUSIVE_EXCLUSIVE;
s1.setSpan(new StyleSpan(Typeface.BOLD), 0, s1.length(), flag);
s2.setSpan(new StyleSpan(Typeface.ITALIC), 0, s2.length(), flag);
s3.setSpan(new ForegroundColorSpan(Color.RED), 0, s3.length(), flag);
s4.setSpan(new BackgroundColorSpan(Color.YELLOW), 0, s4.length(), flag);
s5.setSpan(new UnderlineSpan(), 0, s5.length(), flag);
s6.setSpan(new StrikethroughSpan(), 0, s6.length(), flag);
s7.setSpan(new RelativeSizeSpan(2), 0, s7.length(), flag);
s8.setSpan(new RelativeSizeSpan(0.5f), 0, s8.length(), flag);
s9.setSpan(new TypefaceSpan("monospace"), 0, s9.length(), flag);
s10.setSpan(new URLSpan("https://developer.android.com"), 0, s10.length(), flag);
s11.setSpan(new ClickableSpan() {
    @Override
    public void onClick(View widget) {
        Toast.makeText(getApplicationContext(), "Span clicked", Toast.LENGTH_SHORT).show();
    }
}, 0, s11.length(), flag);
s12.setSpan(new ForegroundColorSpan(Color.RED), 0, 11, flag);
s12.setSpan(new BackgroundColorSpan(Color.YELLOW), 4, s12.length(), flag);
s12.setSpan(new UnderlineSpan(), 4, 11, flag);

// build the string
SpannableStringBuilder builder = new SpannableStringBuilder();
builder.append(s1);
builder.append(s2);
builder.append(s3);
builder.append(s4);
builder.append(s5);
builder.append(s6);
builder.append(s7);
builder.append(s8);
builder.append(s9);
builder.append(s10);
builder.append(s11);
builder.append(s12);

// set the text view with the styled text
textView.setText(builder);
// enables clicking on spans for clickable span and url span
textView.setMovementMethod(LinkMovementMethod.getInstance());

さらなる研究

この例は、もともとここから発想を得たものです


5
SpannableStringについての投稿はGoogleドキュメントよりも優れています。ありがとう
MBH

これはWebサービスからの画像をサポートしましたか?そのような私の要件。
MohanRaj S

@MohanRajS SpannableStringsはUnicode絵文字をサポートしていますが、他の画像はサポートしていません。
Suragch

@Suragchは迅速な対応に感謝しますが、私のサイド要件はjpg、pngです。処理する唯一の選択肢はwebviewですか?:(
MohanRaj S

43

サポートされているタグのリストは次のとおりです。

文字列リソースを使用する場合は、HTML表記を使用して太字や斜体などの簡単なスタイルを追加できます。現在サポートされているタグは以下のとおりですB(太字)、 I(イタリック)、 U(下線)、 TT(モノスペース)、 、BIGSMALLSUP上付き文字)、 SUB(下付き)、およびSTRIKE(取り消し線)。したがって、たとえば、res/values/strings.xml次のように宣言できます。

<resource>
    <string id="@+id/styled_welcome_message">We are <b><i>so</i></b> glad to see you.</string>
</resources>

http://developer.android.com/guide/faq/commontasks.html#selectingtext — Web Archiveリンクから、<resource>タイプミスはオリジナルです!)

またHtml.fromHtml、単純なケースではそれが実際には必要ないことも示しています。


Html.fromHtmlは、多くの場合、テキストのスタイルを設定する簡単な方法です。また、このリンクは元の質問にすでに含まれています。
複雑化

17

私は同じ問題に遭遇していました。私はfromHtmlを使用することもできましたが、今はWebではなくAndroidなので、これを試すことにしました。これをローカライズする必要があるので、文字列置換の概念を使用して試してみました。TextViewのスタイルをメインスタイルに設定し、他の部分をフォーマットします。

これが同じことをしようとしている他の人に役立つことを願っています-これがフレームワークで簡単ではない理由がわかりません。

私の文字列は次のようになります:


<string name="my_text">{0} You will need a {1} to complete this assembly</string>
<string name="text_sub0">1:</string>
<string name="text_sub1">screwdriver, hammer, and measuring tape</string>

ここにスタイルがあります:


<style name="MainStyle">
    <item name="android:textSize">@dimen/regular_text</item>
    <item name="android:textColor">@color/regular_text</item>
</style>
<style name="style0">
    <item name="android:textSize">@dimen/paragraph_bullet</item>
    <item name="android:textColor">@color/standout_text</item>
    <item name="android:textStyle">bold</item>
</style>
<style name="style1">
    <item name="android:textColor">@color/standout_light_text</item>
    <item name="android:textStyle">italic</item>
</style>

これが私のformatStylesメソッドを呼び出す私のコードです:


SpannableString formattedSpan = formatStyles(getString(R.string.my_text), getString(R.string.text_sub0), R.style.style0, getString(R.string.main_text_sub1), R.style.style1);
textView.setText(formattedSpan, TextView.BufferType.SPANNABLE);

フォーマット方法:


private SpannableString formatStyles(String value, String sub0, int style0, String sub1, int style1)
{
    String tag0 = "{0}";
    int startLocation0 = value.indexOf(tag0);
    value = value.replace(tag0, sub0);

    String tag1 = "{1}";
    int startLocation1 = value.indexOf(tag1);
    if (sub1 != null && !sub1.equals(""))
    {
        value = value.replace(tag1, sub1);
    }

    SpannableString styledText = new SpannableString(value);
    styledText.setSpan(new TextAppearanceSpan(getActivity(), style0), startLocation0, startLocation0 + sub0.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    if (sub1 != null && !sub1.equals(""))
    {
        styledText.setSpan(new TextAppearanceSpan(getActivity(), style1), startLocation1, startLocation1 + sub1.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    }

    return styledText;
}

ローカライズされたバージョンの文字列が{0}と{1}を並べ替える場合、これは機能しないと思います。startLocation1が<startLocation0の場合は、startLocation0を変更する必要がある場合があります
JonathanC


8

HTMLBuilderを使用してこれを行う簡単な方法を次に示します

    myTextView.setText(new HtmlBuilder().
                    open(HtmlBuilder.Type.BOLD).
                    append("Some bold text ").
                    close(HtmlBuilder.Type.BOLD).
                    open(HtmlBuilder.Type.ITALIC).
                    append("Some italic text").
                    close(HtmlBuilder.Type.ITALIC).
                    build()
    );

結果:

いくつかの太字のテキスト いくつかの斜体のテキスト


7

スタイル付きテキストをxmlに追加したい場合は、TextViewを拡張するカスタムビューを作成し、setText()をオーバーライドできます。

public class HTMLStyledTextView extends TextView
{
    public HTMLStyledTextView(Context context) {
        super(context);
    }

    public HTMLStyledTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public HTMLStyledTextView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    public void setText(CharSequence text, BufferType type)
    {
       super.setText(Html.fromHtml(text.toString()), type);
    }
}

その後、次のように使用できます(PACKAGE_NAMEパッケージ名に置き換えます)。

<PACKAGE_NAME.HTMLStyledTextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="<![CDATA[
        <b>Bolded Text:</b> Non-Bolded Text
    ]]>"
/>

その後、Android Studioで正しくプレビューされますか?
JPM 2015年


3

私も

どのようにKotlinとしていくつかの美しいマークアップを使用する方法についてアンコ -

import org.jetbrains.anko.*
override fun onCreate(savedInstanceState: Bundle?) {
    title = "Created with Beautiful Markup"
    super.onCreate(savedInstanceState)

    verticalLayout {
        editText {
            hint = buildSpanned {
                append("Italic, ", Italic)
                append("highlighted", backgroundColor(0xFFFFFF00.toInt()))
                append(", Bold", Bold)
            }
        }
    }
}

美しいマークアップで作成


2

はい、それを使用して可能SpannedStringです。Kotlinを使用している場合、を使用することでさらに簡単にcore-ktxなります。これは、これを行うためのドメイン固有言語(DSL)を提供するためです。

    val string: SpannedString = buildSpannedString {
        bold {
            append("1111")
        }
        append("Devansh")     
    }

それによって提供されるその他のオプションは次のとおりです。

append("Hello There")
bold {
    append("bold")
    italic {
        append("bold and italic")
        underline {
            append("then some text with underline")
        }
    }
}

最後に、次のことができます。

textView.text = string

0

実際には、Htmlオブジェクトを除いて、Spannnable型クラス(TextAppearanceSpanまたはTypefaceSpanとSpannableString togatherなど)を使用することもできます。HTMLクラスもこれらのメカニズムを使用します。ただし、Spannable型クラスを使用すると、自由度が増します。


0

これは、Stringのlength()メソッドを利用するのと同じくらい簡単かもしれません。

  1. :それはようなことができるよう、多くのあなたは、異なるスタイルを必要な数のサブ文字列(ビューのAndroidの視点から別々の文字列)に文字列XMLファイル内のテキスト文字列を分割STR1、STR2、STR3、(あなたの場合のように)結合すると、使用する単一の文字列全体になります。

  2. 次に、コードで提示したのと同じように、「Span」メソッドを実行します。ただし、単一の文字列ではなく、すべての部分文字列を結合して、それぞれを異なるカスタムスタイルを持つ1つの文字列に結合します。

あなたはまだ数値を使用していますが、直接ではありません-今は(コードのように)ハードコードされた形式ではなくなりましたが、それらは結合されたlength()メソッドで置き換えられています(前に2つの星があり、strに接尾辞が付いていることに注意してください)。絶対値の代わりにlength()を使用して、変更を元に戻します):

str.setSpan(new StyleSpan(android.graphics.Typeface.ITALIC), 0, **str.length()**, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

最初の文字列サイズの場合、次にstr.length()+ 1、str.length()+ str2.length()、2番目の文字列サイズのように、たとえば0、7、8、19の代わりにすべての部分文字列を使用等々...


0

ウェブページの下部にあるAndroid String Resources共有として補助的なSpannable Classを使用します。あなたはCharSquences彼らにスタイルを作成して与えることによってこれに取り組むことができます。

しかし、彼らが私たちに与える例では、単に太字、斜体、さらにはテキストに色を付けるためのものです。でスタイルCharSequenceを設定するには、いくつかのスタイルをでラップする必要がありましたTextView。そのクラス(私はそれに名前を付けましたCharSequenceStyles)に、この関数を追加しました。

public static CharSequence applyGroup(LinkedList<CharSequence> content){
    SpannableStringBuilder text = new SpannableStringBuilder();
    for (CharSequence item : content) {
        text.append(item);
    }
    return text;
}

そしてビューにこれを追加しました。

            message.push(postMessageText);
            message.push(limitDebtAmount);
            message.push(pretMessageText);
            TextView.setText(CharSequenceStyles.applyGroup(message));

これがお役に立てば幸いです。


0

SpannyはSpannableStringを使いやすくします。

Spanny spanny = new Spanny("Underline text", new UnderlineSpan())
                .append("\nRed text", new ForegroundColorSpan(Color.RED))
                .append("\nPlain text");
textView.setText(spanny)

0

ジョンが言ったように、私にとってこれが最良の解決策であり、実行時にテキストを設定する必要はなく、このカスタムクラスHtmlTextViewのみを使用します

public class HtmlTextView extends TextView {

  public HtmlTextView(Context context) {
      super(context);
  }

  public HtmlTextView(Context context, AttributeSet attrs) {
      super(context, attrs);
  }

  public HtmlTextView(Context context, AttributeSet attrs, int defStyleAttr) 
  {
      super(context, attrs, defStyleAttr);
  }

  @TargetApi(21)
  public HtmlTextView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
      super(context, attrs, defStyleAttr, defStyleRes);
  }

  @Override
  public void setText(CharSequence s,BufferType b){
      super.setText(Html.fromHtml(s.toString()),b);
  }

}

これで、XMLに入れるだけです。

<com.fitc.views.HtmlTextView
    android:id="@+id/html_TV"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/example_html" />

あなたのHTML文字列で

<string name="example_html">
<![CDATA[
<b>Author:</b> Mr Donuthead<br/>
<b>Contact:</b> me@donut.com<br/>
<i>Donuts for life </i>
]]>

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.