일모도원(日暮途遠) 개발자

[Android] 텍스트 꾸미기 (Span) 본문

안드로이드 개발/안드로이드

[Android] 텍스트 꾸미기 (Span)

달님개발자 2022. 12. 29. 15:02

기존에는 text에 색상등을 줄려면 HTML을 활용해서 했지만, 요즘은 Span을 사용하여 텍스트에 색상 표시, 텍스트를 클릭 가능하게등을 할수 있다.

 

스팬을 사용할려면 아래 3개 클래스중 하나를 사용하면 된다.

  • SpannedString
    텍스트 또는 마크업이 읽기 전용이면(변경하지 않는다면). 개발자는 이 클래스를 직접 사용하지는 않는거 같다. textview에 setText시 span이 적용된 클래스(SpannableString, SpannableStringBuilder)를 넘겨주면, 이걸 받을때 복사본을 SpannedString으로 만든다고 한다. 그래서 텍스트나 스팬을 업데이트해야 할 경우 SpannedString는 텍스트와 스팬은 변경할 수 없으므로 새로운 Spannable 객체를 만들고 setText()를 다시 호출해야 한다.
  • SpannableString
    텍스트는 읽기전용이지만, 마크업은 변경하능할때.그리고 적은수의 스팬을 단일 텍스트 객체에 연결해야 하고 
  • SpannableStringBuilder
    읽기전용이라도 많은 수의 스팬을 텍스트 객체에 연결해야 한다거나, 텍스트를 수정해야한다면

 

위 3개의 클래스는 전부 Spannable 인터페이스를 implement한거다. (Spannable은 Spanned인터페이스의 자식이다)

 

Span을 만들고 TextView에 Span을 연결하려면 그냥 setText메소드를 사용해서 span을 넘겨주면 된다.

textView.setText(spannableObject);

Span이란 말이 첨에는 낯설지만, 영어 뜻을 보면 "범위, 폭, 걸치다"등의 뜻 이 있다.

즉 텍스트에서 내가 원하는 부분(Span)에 원하는 효과(아래의 Object what)를 주는것(setSpan메소드)이다. 

 

public abstract void setSpan (Object what, 
    int start, 
    int end, 
    int flags)

 

실제 여러가지 예제들은 아래를 참고하자.


setSpan메소드를 사용해서 텍스트에서 원하는 부분에 효과(색상 변경, 폰트 변경, 클릭등)를 주면 된다.

예를 들어서 텍스트에서 8~12번째 글자는 빨간색으로 칠할려면 아래 코드를 쓰면 된다.

Spannable.SPAN_EXCLUSIVE_INCLUSIVE 플래그 설명은 다음을 참고

(아래는 텍스트를 변경하지 않으며로 SpannableStringBuilder가 아니로 SpannableString를 사용해도 된다)

SpannableStringBuilder spannable = new SpannableStringBuilder("Text is spantastic!");
spannable.setSpan(
    new ForegroundColorSpan(Color.RED),
    8, // start
    12, // end
    Spannable.SPAN_EXCLUSIVE_INCLUSIVE
);


원하는 부분(Span)에 빨간색으로 칠한후, 그 부분 다음 "(& fon)"이라는 글자를 추가 했다.

즉 텍스트가 변했다. 이때는 꼭 SpannableStringBuilder를 써야 한다.

그리고 추가된 글자의 색상도 같이 빨간색으로 변했다. 추가된 글자는 빨간색을 적용안할려면 Spannable.SPAN_EXCLUSIVE_INCLUSIVE

의 INCLUSIVE를 EXCLUSIVE로 바꾸면 된다. 자세한건 다음을 참조

SpannableStringBuilder spannable = new SpannableStringBuilder("Text is spantastic!");
spannable.setSpan(
    new ForegroundColorSpan(Color.RED),
    8, // start
    12, // end
    Spannable.SPAN_EXCLUSIVE_INCLUSIVE
);
spannable.insert(12, "(& fon)");

 

 


여러 스팬을 동일한 텍스트에 연결 (빨간색으로 칠하고, 폰트를 굵게)

SpannableString spannable = SpannableString(“Text is spantastic!”);
spannable.setSpan(
    new ForegroundColorSpan(Color.RED),
    8, 12,
    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
);
spannable.setSpan(
    new StyleSpan(Typeface.BOLD),
    8, spannable.length(),
    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
);


텍스트에 밑줄 긋기

SpannableString string = new SpannableString("Text with underline span");
string.setSpan(new UnderlineSpan(), 10, 19, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

배경 색상바꾸기

SpannableString string = new SpannableString("Text with a background color span");
string.setSpan(new BackgroundColorSpan(color), 12, 28, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

이런씩으로 텍스트나 배경 색상을 변경하고 밑줄이나 취소선을 추가하는 등 텍스트 모양에 영향 이러한 스팬은 모두 CharacterStyle 클래스를 확장하고, 그 종류들은 아래와 같다. 이름만으로도 대충 어떤건지 알수 있을거다.

 

BackgroundColorSpan, ClickableSpan, ForegroundColorSpan, MaskFilterSpan, MetricAffectingSpan, StrikethroughSpan, SuggestionRangeSpan, SuggestionSpan, UnderlineSpan


텍스트 크기를 50% 늘리는 RelativeSizeSpan

 

SpannableString string = new SpannableString("Text with relative size span");
string.setSpan(new RelativeSizeSpan(1.5f), 10, 24, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);

줄 높이 및 텍스트 크기등을 바꾸면 텍스트 측정항목에도 영향을 미칠 수 있습니다. 이러한 스팬은 모두 MetricAffectingSpan 클래스를 확장한다. 

 

스팬을 적용하면 다시 측정, 텍스트 레이아웃 다시 계산, 텍스트 다시 그리기가 트리거된다.

 

 

 


이미 textview에 스팬이 적용된것을 바꿀려면 아래처럼 한다.

textView.setText(spannable, BufferType.SPANNABLE);
Spannable spannableText = (Spannable) textView.getText();
spannableText.setSpan(
     new ForegroundColorSpan(color),
     8, spannableText.getLength(),
     SPAN_INCLUSIVE_INCLUSIVE);

 

 

 

블러를 줄려면 아래 소스 참조.

SpannableString strBlur = new SpannableString(str);
MaskFilter blurMask = new BlurMaskFilter(30f, BlurMaskFilter.Blur.NORMAL);
float percentNoBlur = 0.5f;
strBlur.setSpan(new MaskFilterSpan(blurMask),  (int)(strBlur.length() * percentNoBlur), strBlur.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
return strBlur;

 

 

자세한건 공식 매뉴얼을 참고하자.

https://developer.android.com/guide/topics/text/spans?hl=ko