여러 글꼴 / 텍스트 크기 등으로 문자열을 만드는 SpannableStringBuilder 예?


81

다음과 같은 문자열을 표시 할 TextView에 배치 된 문자열을 만들어야합니다.

첫 번째 부분은 굵게하지 BOLD 나머지 대담하지

그래서 어떻게 이것을 할 수 있는지 알고 싶습니다 SpannableStringBuilder.

이 작업을 수행하기 위해 세 개의 텍스트 편집기를 사용할 수 있지만 최상의 솔루션을 사용하고 싶습니다.

답변:


88
First Part Not Bold   BOLD  rest not bold

@Rajesh가 제안한대로 또는 이것에 의해 이것을 할 수 있습니다.

String normalBefore= "First Part Not Bold ";
String normalBOLD=  "BOLD ";
String normalAfter= "rest not bold";
String finalString= normalBefore+normalBOLD+normalAfter;
Spannable sb = new SpannableString( finalString );
sb.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), finalString.indexOf(normalBOLD)+ normalBOLD.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); //bold
sb.setSpan(new AbsoluteSizeSpan(intSize), finalString.indexOf(normalBOLD)+ normalBOLD.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);//resize size

이것을 TextView에 표시하려면

textview.setText(sb,  TextView.BufferType.SPANNABLE);

1
또한 굵은 체의 글꼴 크기도 어떻게 설정할 수 있습니까? 그래서 나는 그것이 굵은 체이고 글꼴 20이라고 모두 지정하고 있습니까?
Code Droid

7
또한 색인을 (finalString.indexOf (normalBOLD), finalString.indexOf (normalBOLD) + normalBOLD.lenth ())로 업데이트하십시오
Code Droid

2
CodeDroid는 말 외에, 또 다른 문제는 같이 IndexOf 방법은 반복되는 단어를 잡을하고 떠날 수 있다는 것입니다 end당신 전에 start을 위해 IndexOutOfBoundsException. 따라서 부분 문자열의 형식을 지정한 다음 함께 조합하는 것이 좋습니다.
물 자체

@hotveryspicy 나는 "finalString.indexOf (normalBOLD)"이 부분이-외모와는 반대로-효율적이라고 생각한다. 왜냐하면 String interning 때문이지?
Paul Brewczynski

참고 : android:textAllCaps="true"SpannableString
Someone Somewhere

80

받아 들여지는 대답은 괜찮지 만 (그리고 나는 그것을 찬성했습니다) 제출자가 요청 한대로 SpannableStringBuilder를 사용하지 못했습니다. 빌더가 가장 이해하기 쉬운 경우가 있었기 때문에 여기에 코드가 있습니다 (다른 사람에게 도움이 될 경우 텍스트의 색상을 변경하는 보너스 사용 포함). SpannableStringBuilder 생성자에 초기 문자열을 제공 할 수도 있지만 여기에서 "append"를 사용하여 원하는 "굵은"텍스트 앞에 많은 것을 추가 한 다음 표시된대로 시작을 기록 할 수 있음을 명확히하기 위해 여기에서 설정했습니다. 나는 이것이 허용되는 답변보다 더 빠른 코드라고 의심합니다.

SpannableStringBuilder longDescription = new SpannableStringBuilder();
longDescription.append("First Part Not Bold ");
int start = longDescription.length();
longDescription.append("BOLD");
longDescription.setSpan(new ForegroundColorSpan(0xFFCC5500), start, longDescription.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
longDescription.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), start, longDescription.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
longDescription.append(" rest not bold");

2
또한 텍스트를 추가하기 전에 굵은 부분의 시작 위치를 검색하여 굵게 표시되어야하는 단어의 중복 발생에 대해 걱정할 필요가 없습니다.
Qw4z1 2015

57

Kotlin을 사용하는 경우 android-ktx 라이브러리를 사용하여 다음을 수행 할 수 있습니다.

val s = SpannableStringBuilder()
        .append("First Part Not Bold ")
        .bold { append("BOLD") } 
        .append("Rest not bold")

bold확장 기능입니다 SpannableStringBuilder. 사용할 수있는 작업 목록은 여기 에서 설명서를 참조하십시오 .

다른 예시:

val s = SpannableStringBuilder()
            .color(green, { append("Green text ") })
            .append("Normal text ")
            .scale(0.5, { append("Text at half size " })
            .backgroundColor(green, { append("Background green") })

green해결 된 RGB 색상은 어디에 있습니까 ?

스팬을 중첩하여 임베디드 DSL로 끝낼 수도 있습니다.

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

build.gradle작동하려면 앱 모듈 수준에서 다음이 필요합니다 .

repositories {
    google()
}

dependencies {
    implementation "androidx.core:core-ktx:1.2.0"
}

3
Kotlin을 사용할 수 있다면 확실히 최선의 선택입니다. DSL은 그것을 훨씬 더 좋은 API로 만듭니다.
Baptiste Candellier 2019

1
LiveData <String>에서 어떻게 작동합니까? 모든 것이 컴파일되고 괜찮아 보이지만 이러한 변경 사항을 적용 할 수없는 것 같습니다.
순종

42

API 21에서 SpannableStringBuilder에는이를 수행하는 간단한 방법이 포함되어 있습니다. 다음은 솔루션 예입니다.

SpannableStringBuilder builder= new SpannableStringBuilder();
StyleSpan boldSpan = new StyleSpan(android.graphics.Typeface.BOLD);
builder.append("First Part Not Bold ")
              .append("BOLD ", boldSpan, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
              .append("rest not bold");

API 21을 지원하지 않는 좋은 기회이므로 해당 메서드에서 코드를 복제 할 수 있습니다.

public SpannableStringBuilder append(CharSequence text, Object what, int flags) {
        int start = length();
        append(text);
        setSpan(what, start, length(), flags);
        return this;
}

7

Html클래스를 사용하여 TextView에서 HTML 코드를 사용하십시오 .

Spanned styledText = Html.fromHtml("First Part Not Bold <b>BOLD</b> rest not bold");
textView.setText(styledText);

20
이것은 매우 느리며 스크롤하는 동안 완료되면 프레임을 건너 뛸 수 있습니다.
Phil Kulak 2013

6

이 코드는 html bold 태그 안에있는 모든 것을 굵게 설정해야합니다. 또한 태그를 삭제하여 내부 내용 만 표시합니다.

        SpannableStringBuilder sb = new SpannableStringBuilder("this is <b>bold</b> and this is <b>bold too</b>  and this is <b>bold too, again</b>.");

        Pattern p = Pattern.compile("<b>.*?</b>", Pattern.CASE_INSENSITIVE);            
        boolean stop = false;
        while (!stop)
        {
            Matcher m = p.matcher(sb.toString());
            if (m.find()) {
                sb.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), m.start(), m.end(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
                sb.delete(m.end()-4, m.end());
                sb.delete(m.start(), m.start() + 3);
            }
            else
                stop = true;
        }

이 코드는 Superscript (sup 태그) 등과 같은 다른 html 스타일 태그에도 적용 할 수 있습니다.

        SpannableStringBuilder sb = new SpannableStringBuilder("text has <sup>superscript</sup> tag");

        Pattern p = Pattern.compile("<sup>.*?</sup>", Pattern.CASE_INSENSITIVE);            
        boolean stop = false;
        while (!stop)
        {
            Matcher m = p.matcher(sb.toString());
            if (m.find()) {
                sb.setSpan(new SuperscriptSpan(), m.start(), m.end(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
                sb.delete(m.end()-6, m.end());
                sb.delete(m.start(), m.start() + 5);
            }
            else
                stop = true;
        }

색상을 설정하려면 setSpan과 함께 ForegroundColorSpan을 사용하십시오.

sb.setSpan(new ForegroundColorSpan(Color.rgb(255, 0, 0)), m.start(), m.end(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);

도움이 되었기를 바랍니다.


완벽한 대답, 당신은 내 하루를 구했습니다! 시작 태그 만 있으면 패턴을 사용하기 때문에 패턴을 val p = Pattern.compile ( "<b> ([^ <] *) </ b>", Pattern.MULTILINE 또는 Pattern.DOTALL)로 대체했습니다. 텍스트는 굵게 표시됩니다. 감사합니다
AndroidRuntimeException

4

그래서 나는 이것이 해결되었다는 것을 알고 있으며 SpannableStringBuilder로 요청한 것처럼 문자열을 더 동적으로 만들고 싶을 때 나는 이것을 올릴 것이라고 생각했습니다.

// Stuff needed
TextView DataTextView = (TextView)rootView.findViewById(R.id.DataView);
String Fields[] = {...database column names as strings... "x","y"};

String DataString = new String();   

int start,stop;     // Start and Stop of formatting

// Final Result
SpannableStringBuilder coloredString = new SpannableStringBuilder(); 

SpannableString temp;       // Small segment of colored string
for (int i =0; i < Fields.length; i++)
{
    if (database_result.containsKey(Fields[i]))  // Be sure a field exists in the ContentValues
    {
            DataString = Fields[i]+": ";
        start = DataString.length();
        DataString = DataString+ +database_result.getAsInteger(Fields[i])+" ";
        stop= DataString.length();
        temp = new SpannableString(DataString);
        temp.setSpan(new ForegroundColorSpan(Color.WHITE),start, stop, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        coloredString.append(temp);
    }   
}
DataTextView.setText(coloredString);

database_result는 SQL 쿼리의 반환 된 Cursor 유형에서 생성 한 ContentValues ​​유형입니다. 내가 가진 유일한 문제는 처음에는 ColorSpaning이 첫 번째 세그먼트였습니다. 루프에서 하나 (또는 ​​다른 종류의 범위)를 사용할 때마다 새 ForegroundColorSpan을 선언해야한다는 점이 이음새가됩니다.


3

이를 위해 TextAppearanceSpan 과 함께 SpannableStringBuilder 를 사용할 수도 있습니다 . 그렇게 구현하려면 아래 단계를 따르십시오.

  1. 에서 스타일을 만듭니다 styles.xml.

<style name="BoldStyle">
   <!-- Can add other styling attributes -->
   <item name="android:textStyle">bold</item>
   ......
</style>

  1. 아래 코드를 사용하십시오.
SpannableStringBuilder builder = new SpannableStringBuilder ( "첫 부분은 굵게 표시되지 않음 BOLD 나머지 부분은 굵게 표시되지 않음");
builder.setSpan (new TextAppearanceSpan (this, R.style.BoldStyle), 20, 24, 0);
((TextView) findViewById (R.id.tv7)). setText (builder);

그게 다야. 누군가를 도울 수 있기를 바랍니다.


1

SpannableBuilder를 사용할 수 있는데 왜 SpannableStringBuilder를 사용합니까 ?? ( https://gist.github.com/qtyq/90f9b4894069a8b3676c )

SpannableString ss = SpannableBuilder.init("First Part Not Bold BOLD rest not bold")
                                     .makeBold("BOLD")
                                     .create()

4
spannablebuilder는 하나의 스팬을 빌드하는 반면, spannablestringbuilder는 여러 스팬으로 문자 시퀀스를 빌드하기위한 것이므로
dabluck
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.