web-dev-qa-db-ja.com

TextView BOLDで特定のテキストを作成する方法

TextView上の特定のテキストを太字にする方法がわかりません。

こんな感じです

txtResult.setText(id+" "+name);

出力をこのようにします。

1111ニール

idnameは、データベースから値を取得した変数であり、idを太字にしたいのですが、idのみが影響を受けないため、nameは影響を受けません。

185
Budi Darmawan

文字列をHTMLで構築して設定するだけです。

String sourceString = "<b>" + id + "</b> " + name; 
mytextview.setText(Html.fromHtml(sourceString));
319
Raghav Sood

Html.fromHtml() を使うことができますが、 SpannableStringBuilder というよりネイティブなアプローチを使うことができますが、これは post が役に立つかもしれません。

SpannableStringBuilder str = new SpannableStringBuilder("Your awesome text");
str.setSpan(new Android.text.style.StyleSpan(Android.graphics.Typeface.BOLD), INT_START, INT_END, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
TextView tv=new TextView(context);
tv.setText(str);
326
wtsang02

まず、 Raghav Sood's answer のスローパフォーマンスコードを使うことについて心配する必要はありません。

第二に:Kotlinを使うとき w3bshark's answer によって提供される拡張関数を書く必要はありません。

Finnaly:Kotlin Android-ktx library を使用するだけです。

// Suppose id = 1111 and name = neil (just what you want). 
val s = SpannableStringBuilder()
          .bold { append(id) } 
          .append(name)
txtResult.setText(s) 

生産:1111ニール


更新:

私はそれが他の誰かを助けることができるだけでなく、あなたがここにどれだけ遠くまで行くことができるかを示すことができると思うので、もっとユースケースです。

  • テキストを青とイタリックの部分で表示する必要がある場合

    val myCustomizedString = SpannableStringBuilder()
        .color(blueColor, { append("A blue text ") })
        .append("showing that ")
        .italic{ append("it is painless") }
    
  • テキストを太字と斜体の両方で表示する必要がある場合は、次のようにします。

        bold { italic { append("Bold and italic") } }
    

つまり、boldappendcolor、およびitalicは、SpannableStringBuilderの拡張関数です。 公式文書 に他の拡張機能があり、そこから他の可能性を考えることができます。

43

私は選ばれた答えが満足のいく結果を提供しないと思いました。私は2つの文字列を取る私自身の関数を書きました。本文全体と本文の一部を太字にします。

'text'の 'textToBold'を太字にしてSpannableStringBuilderを返します。

部分文字列をタグでラップせずに太字にする機能があると便利です。

    /**
     * Makes a substring of a string bold.
     * @param text          Full text
     * @param textToBold    Text you want to make bold
     * @return              String with bold substring
     */

    public static SpannableStringBuilder makeSectionOfTextBold(String text, String textToBold){

        SpannableStringBuilder builder=new SpannableStringBuilder();

        if(textToBold.length() > 0 && !textToBold.trim().equals("")){

            //for counting start/end indexes
            String testText = text.toLowerCase(Locale.US);
            String testTextToBold = textToBold.toLowerCase(Locale.US);
            int startingIndex = testText.indexOf(testTextToBold);
            int endingIndex = startingIndex + testTextToBold.length();
            //for counting start/end indexes

            if(startingIndex < 0 || endingIndex <0){
                return builder.append(text);
            }
            else if(startingIndex >= 0 && endingIndex >=0){

                builder.append(text);
                builder.setSpan(new StyleSpan(Typeface.BOLD), startingIndex, endingIndex, 0);
            }
        }else{
            return builder.append(text);
        }

        return builder;
  }
35
Eitan

Wtsang02が言ったように、HTMLを使用することは高価なオーバーヘッドです。ネイティブソリューションを使うだけです。文字列を変更する必要がない場合は、SpannableStringBuilderではなくSpannableStringを使用してください。

String boldText = "id";
String normalText = "name";
SpannableString str = new SpannableString(boldText + normalText);
str.setSpan(new StyleSpan(Typeface.BOLD), 0, boldText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(str);
17
Jadamec

XMLの文字列を使いたい場合は、次のようにします。

strings.xml

<string name="test">
     <![CDATA[
 <b>bold!</b> normal
    ]]>
</string>

コード:

textView.setText(Html.fromHtml(getString(R.string.test)));
13

複数のテキストを太字にする場合は、これがより良い解決策です。 Eitanのコードを改良しました。アイタンに感謝します。

public static SpannableStringBuilder makeSectionOfTextBold(String text, String... textToBold) {
    SpannableStringBuilder builder = new SpannableStringBuilder(text);

    for (String textItem :
            textToBold) {
        if (textItem.length() > 0 && !textItem.trim().equals("")) {
            //for counting start/end indexes
            String testText = text.toLowerCase(Locale.US);
            String testTextToBold = textItem.toLowerCase(Locale.US);
            int startingIndex = testText.indexOf(testTextToBold);
            int endingIndex = startingIndex + testTextToBold.length();

            if (startingIndex >= 0 && endingIndex >= 0) {
                builder.setSpan(new StyleSpan(Typeface.BOLD), startingIndex, endingIndex, 0);
            }
        }
    }

    return builder;
}
10
Krishna

その単純なものは、例えば<b>"your text here:"</b>のように指定されたテキストを閉じるだけです。

<string name="headquarters">"<b>"Headquarters:"</b>" Mooresville, North Carolina, U.S.</string>

結果:本社:米国ノースカロライナ州ムーアズビル.

9
Rida

@ mladj0niの回答に基づいて、以下のコードを機能させることができました。問題は、String.formatを使用すると、HTMLマークアップが削除されるため、strings.xmlの角括弧記号をエスケープする必要があることです。

strings.xml:

<string name="welcome_messages">Hello, %1$s! You have &lt;b>%2$d new messages&lt;/b>.</string>

code.Java:

String unspanned = String.format(Locale.US, "%s%s", getResources().getString(R.string. welcome_messages), 99);

Spanned spanned;
if (Android.os.Build.VERSION.SDK_INT >= Android.os.Build.VERSION_CODES.N) {
    spanned = Html.fromHtml(unspanned, Html.FROM_HTML_MODE_LEGACY);
} else {
    spanned = Html.fromHtml(unspanned);
}

textView.setText(spanned);

SpannableStringBuilderよりも簡単です。パフォーマンスに関しては、1つの文字列だけを表示している場合、ユーザーはそれを解析するための余分なミリ秒に気付くことはありません。

ドキュメント こちら を参照してください。

6
Yusuf X

wtsang02の回答が最も適切な方法です。Html.fromHtml( "")が推奨されなくなったためです。ここでは、文のサイズに関係なく、最初のWordを動的に太字にすることに問題がある場合は、少しだけ強化します。

まず最初のWordを取得するメソッドを作成しましょう。

 private String getFirstWord(String input){

    for(int i = 0; i < input.length(); i++){

        if(input.charAt(i) == ' '){

            return input.substring(0, i);
        }
    }

    return input;
}

今、あなたはこのような長い文字列があるとしましょう:

String sentence = "[email protected] want's to be your friend!"

そしてあなたはあなたの文章が[email protected]のようになりたいのです。 firstWordを大胆にするには、firstWordを取得してその長さを取得するだけです。

String myFirstWord = getFirstWord(sentence);
int start = 0; // bold will start at index 0
int end = myFirstWord.length(); // and will finish at whatever the length of your first Word

さて、wtsang02のの手順に従ってください。

SpannableStringBuilder fancySentence = new SpannableStringBuilder(sentence);
fancySentence.setSpan(new Android.text.style.StyleSpan(Typeface.BOLD), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(fancySentence);

以上です!今、あなたは長い/短い文章からどんなサイズでもWordを太字にすることができるはずです。誰かに役立つこと、幸せなコーディング:)

3
Junia Montana

私は既存の答えに満足できなかったので、私はもっと最新の解決策を提供するためにここに来ました。私は翻訳されたテキストに対して機能するものが必要で、Html.fromHtml()を使用することによるパフォーマンスへの影響はありません。 Kotlinを使っているのであれば、テキストの複数の部分を簡単に太字に設定する拡張関数があります。これはMarkdownと同じように機能し、必要に応じて他のMarkdownタグをサポートするように拡張できます。

val yourString = "**This** is your **string**.".makePartialTextsBold()
val anotherString = getString(R.string.something).makePartialTextsBold()

/**
 * This function requires that the parts of the string that need
 * to be bolded are wrapped in ** and ** tags
 */
fun String.makePartialTextsBold(): SpannableStringBuilder {
    var copy = this
    return SpannableStringBuilder().apply {
        var setSpan = true
        var next: String
        do {
            setSpan = !setSpan
            next = if (length == 0) copy.substringBefore("**", "") else copy.substringBefore("**")
            val start = length
            append(next)
            if (setSpan) {
                setSpan(StyleSpan(Typeface.BOLD), start, length,
                        Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
            }
            copy = copy.removePrefix(next).removePrefix("**")
        } while (copy.isNotEmpty())
    }
}
3
w3bshark

Kotlinを使用している場合は、core-ktxを使用することでさらに簡単になります。これを行うために domain-specific-language(DSL) を提供します。

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

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

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

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

textView.text = string
3
Devansh Maurya

リスト/リサイクラーでcharを検索している間、文字列の最初のcharをスパン可能にします。

r a viとajay

以前はこのように強調表示されていましたが、私は以下のようになりたかったです

ravi a nd ajay OR ravi and a jay

このため、Wordの長さが1であれば検索し、メイン文字列を単語に分割してWordの開始位置を計算してから、charで始まるWordを検索しました。

 public static SpannableString colorString(int color, String text, String... wordsToColor) {
    SpannableString coloredString = new SpannableString(text);

    for (String Word : wordsToColor) {

        Log.e("tokentoken", "-wrd len-" + Word.length());
        if (Word.length() !=1) {
            int startColorIndex = text.toLowerCase().indexOf(Word.toLowerCase());
            int endColorIndex = startColorIndex + Word.length();
            try {
                coloredString.setSpan(new ForegroundColorSpan(color), startColorIndex, endColorIndex,
                        Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

            } catch (Exception e) {
                e.getMessage();
            }
        } else {
            int start = 0;

            for (String token : text.split("[\u00A0 \n]")) {
                if (token.length() > 0) {
                    start = text.indexOf(token, start);
                   // Log.e("tokentoken", "-token-" + token + "   --start--" + start);
                    char x = token.toLowerCase().charAt(0);
                    char w = Word.toLowerCase().charAt(0);
                   // Log.e("tokentoken", "-w-" + w + "   --x--" + x);

                    if (x == w) {
                        // int startColorIndex = text.toLowerCase().indexOf(Word.toLowerCase());
                        int endColorIndex = start + Word.length();
                        try {
                            coloredString.setSpan(new ForegroundColorSpan(color), start, endColorIndex,
                                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

                        } catch (Exception e) {
                            e.getMessage();
                        }
                    }
                }
            }

        }

    }

    return coloredString;
}
3
Sagar

2つの文字列を別々にビルダーに追加することができます。一方はspannedString、もう一方は通常のものです。このようにしてインデックスを計算する必要はありません。

val instructionPress = resources?.getString(R.string.settings_press)

val okText = resources?.getString(R.string.ok)
val spannableString = SpannableString(okText)

val spannableBuilder = SpannableStringBuilder()
spannableBuilder.append(instructionPress)
spannableBuilder.append(spannableString, StyleSpan(Typeface.BOLD), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)

instructionText.setText(spannableBuilder,TextView.BufferType.SPANNABLE)
public static Spanned getBoldString(String textNotBoldFirst, String textToBold, String textNotBoldLast) {
    String resultant = null;

    resultant = textNotBoldFirst + " " + "<b>" + textToBold + "</b>" + " " + textNotBoldLast;

    return Html.fromHtml(resultant);

}

これを試して。それは間違いなく助けることができます

2
Saad Bilal

TextViewとEditTextのテキストの一部を太字に設定の静的メソッドを作成しました

public static void boldPartOfText(View mView, String contentData, int startIndex, int endIndex){
        if(!contentData.isEmpty() && contentData.length() > endIndex) {
            final SpannableStringBuilder sb = new SpannableStringBuilder(contentData);

            final StyleSpan bss = new StyleSpan(Typeface.BOLD); // Span to make text bold
            final StyleSpan iss = new StyleSpan(Typeface.NORMAL); //Span to make text normal
            sb.setSpan(iss, 0, startIndex, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
            sb.setSpan(bss, startIndex, endIndex, Spannable.SPAN_INCLUSIVE_INCLUSIVE); // make first 4 characters Bold
            sb.setSpan(iss,endIndex, contentData.length()-1, Spanned.SPAN_INCLUSIVE_INCLUSIVE);

            if(mView instanceof TextView)
               ((TextView) mView).setText(sb);
            else if(mView instanceof EditText)
               ((EditText) mView).setText(sb);

        }
    }

もう1つのよりカスタマイズされたコード

  /*typeFaceStyle can be passed as 

    Typeface.NORMAL = 0;
    Typeface.BOLD = 1;
    Typeface.ITALIC = 2;
    Typeface.BOLD_ITALIC = 3;*/

    public static void boldPartOfText(View mView, String contentData, int startIndex, int endIndex,int typeFaceStyle){
        if(!contentData.isEmpty() && contentData.length() > endIndex) {
            final SpannableStringBuilder sb = new SpannableStringBuilder(contentData);

            final StyleSpan bss = new StyleSpan(typeFaceStyle); // Span to make text bold
            final StyleSpan iss = new StyleSpan(Typeface.NORMAL); //Span to make text italic
            sb.setSpan(iss, 0, startIndex, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
            sb.setSpan(bss, startIndex, endIndex, Spannable.SPAN_INCLUSIVE_INCLUSIVE); // make first 4 characters Bold
            sb.setSpan(iss,endIndex,contentData.length()-1,Spanned.SPAN_INCLUSIVE_INCLUSIVE);

            if(mView instanceof TextView)
                ((TextView) mView).setText(sb);
            else if(mView instanceof EditText)
                ((EditText) mView).setText(sb);
        }
    }
1
Xar E Ahmer

このコードを使用して、テキストの一部を太字に設定できます。太字のhtmlタグの間にあるものは何でも、それはそれを太字にします。

String myText = "make this <b>bold</b> and <b>this</b> too";
textView.setText(makeSpannable(myText, "<b>(.+?)</b>", "<b>", "</b>"));

public SpannableStringBuilder makeSpannable(String text, String regex, String startTag, String endTag) {

            StringBuffer sb = new StringBuffer();
            SpannableStringBuilder spannable = new SpannableStringBuilder();

            Pattern pattern = Pattern.compile(regex);
            Matcher matcher = pattern.matcher(text);
            while (matcher.find()) {
                sb.setLength(0);
                String group = matcher.group();
                String spanText = group.substring(startTag.length(), group.length() - endTag.length());
                matcher.appendReplacement(sb, spanText);

                spannable.append(sb.toString());
                int start = spannable.length() - spanText.length();

                spannable.setSpan(new Android.text.style.StyleSpan(Android.graphics.Typeface.BOLD), start, spannable.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
            }
            sb.setLength(0);
            matcher.appendTail(sb);
            spannable.append(sb.toString());
            return spannable;
        }
1
live-love

太字のテキストの位置が固定されている場合(例:ifがtextViewの先頭にある場合)、同じ背景を持つ2つの異なるtextViewを使用します。それから、他のtextViewのtextStyleを太字にすることができます。

これは単一のtextViewと比較して2倍のメモリを必要としますが、スピードは上がります。

0
neens

これは私がこれに使用するKotlin拡張関数です

/**
 * Sets the specified Typeface Style on the first instance of the specified substring(s)
 * @param one or more [Pair] of [String] and [Typeface] style (e.g. BOLD, ITALIC, etc.)
 */
fun TextView.setSubstringTypeface(vararg textsToStyle: Pair<String, Int>) {
    val spannableString = SpannableString(this.text)
    for (textToStyle in textsToStyle) {
        val startIndex = this.text.toString().indexOf(textToStyle.first)
        val endIndex = startIndex + textToStyle.first.length

        if (startIndex >= 0) {
            spannableString.setSpan(
                StyleSpan(textToStyle.second),
                startIndex,
                endIndex,
                Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
            )
        }
    }
    this.setText(spannableString, TextView.BufferType.SPANNABLE)
}

使用法:

text_view.setSubstringTypeface(
    Pair(
        "something bold",
        Typeface.BOLD
    )
)

text_view.setSubstringTypeface(
    Pair(
        "something bold",
        Typeface.BOLD
    ),
    Pair(
        "something italic",
        Typeface.ITALIC
    )
)
0
aaronmarino

これは、大文字と小文字を区別した動的なString値に対する私の完全な解決策です。

/**
 * Makes a portion of String formatted in BOLD.
 *
 * @param completeString       String from which a portion needs to be extracted and formatted.<br> eg. I am BOLD.
 * @param targetStringToFormat Target String value to format. <br>eg. BOLD
 * @param matchCase Match by target character case or not. If true, BOLD != bold
 * @return A string with a portion formatted in BOLD. <br> I am <b>BOLD</b>.
 */
public static SpannableStringBuilder formatAStringPortionInBold(String completeString, String targetStringToFormat, boolean matchCase) {
    //Null complete string return empty
    if (TextUtils.isEmpty(completeString)) {
        return new SpannableStringBuilder("");
    }

    SpannableStringBuilder str = new SpannableStringBuilder(completeString);
    int start_index = 0;

    //if matchCase is true, match exact string
    if (matchCase) {
        if (TextUtils.isEmpty(targetStringToFormat) || !completeString.contains(targetStringToFormat)) {
            return str;
        }

        start_index = str.toString().indexOf(targetStringToFormat);
    } else {
        //else find in lower cases
        if (TextUtils.isEmpty(targetStringToFormat) || !completeString.toLowerCase().contains(targetStringToFormat.toLowerCase())) {
            return str;
        }

        start_index = str.toString().toLowerCase().indexOf(targetStringToFormat.toLowerCase());
    }

    int end_index = start_index + targetStringToFormat.length();
    str.setSpan(new StyleSpan(BOLD), start_index, end_index, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    return str;
}

例えば。 completeString= "私は太字です"

CASE I*targetStringToFormat* = "bold"*matchCase* = trueの場合

「私は太字です」(太字なので、=太字)

ケースII*targetStringToFormat* = "bold"*matchCase* = falseの場合

"私はBOLD"です

適用するには

myTextView.setText(formatAStringPortionInBold("I am BOLD", "bold", false))

それが役立つことを願っています!

0
sud007