본문 바로가기
안드로이드

TextView - 문자열 다루는 방법 (spannable)

by 호군 2011. 10. 4.
반응형
원문 : http://babtingdev.tistory.com/251


TextView의 기본적인 기능은 문자열을 보여주고 입력(EditText)받는 것이다.

코드로 Text를 읽거나 변경하는 메소드를 알아보겠다.
CharSequence getText()
void setText(int resid [, TextView.BufferType type])
void setText(CharSequence text [, TextView.BufferType type])

getText메소드는 리턴타입이 CharSequence 타입이다. CharSequence는 아래 메소드를 제공하는 interface이다.
쉽게 말하자면 문자의 배열인 셈이다.

 메서드  설명 
 charAt(int index)  index번째의 문자를 구한다 
 length()  길이를 구한다
 subSequence(int start, int end)  부분 문자열을 추출한다
 toString()  String 타입으로 변환한다

public final class java.lang.String implements java.io.Serializable, java.lang.Comparable, java.lang.CharSequence {

위 java.lang.String 클래스 정의를 보면 CharSequence를 구현하고 있는 걸 볼 수 있다.
즉, myText.setText(CharSequence객체)로 호출을 해야하지만 myText.setText("바부팅이") 와 같이 String을 파라미터로 바로  호출도 가능하다.

bufferType
이제 setText메소드의 두번째 파라미터 BufferType에 대해 알아보겠다.

 BufferType  bufferType 속성 (xml)  설명 
 NORMAL  normal   단순한 문자열이며 읽기 전용이다
 SPANNABLE  spannable  문자열에 부가 정보를 같이 기록한다
 EDITABLE  editable  편집 가능한 문자열이다

spannable 속성은 편집은 안되지만 문자열의 중간중간에 표식을 더 삽입할 수 있다는 뜻이다.
(스팬 : 문자서식, 문단서식, 이미지 정보등 문자열 표현과 동작에 사용되는 추가 정보를 의미)

CharSequence의 서브 인터페이스인 Spannable은 다음 두개의 메소드를 제공한다.

void setSpan(Object what, int start, int end, int flags)
void removeSpan(Object whar)


setSpan은 문자열의 start와 end 오프셋 사이에 스팬 정보를 설정한다. 설정 대상 정류가 워낙 많고 사용자가 직접 정의할 수도 있기 떄문에 Object타입으로 파라미터를 받는다.

아래는 Span설정에 관련된 WrapperClass들이다.
 상위 interface  Sub Class 
 CharacterStyle  ForegroundColorSpan, BackgroundColorSpan, UnderlineSpan, ClickableSpan, AbsoluteSizeSpan, ImageSpan, RelativeSizeSpan, RelativeSizeSpan, StyleSpan, URLSpan
 ParagraphStyle  AlignmentSpan, BulletSpan, LeadingMarginSpan, LineHeightSpan, QuoteSpan, TabStopSpan, WrapTogetherSpan
 TextWatcher  SpanWatcher

아래는 span을 사용하는 소스이다.

 main.xml
 <?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="fill_parent"
 android:layout_height="fill_parent"
 >
 <LinearLayout
     android:orientation="vertical"
     android:layout_width="fill_parent"
     android:layout_height="fill_parent"
     >
   <EditText 
     android:id="@+id/edit"
     android:layout_width="fill_parent"
     android:layout_height="wrap_content"
     android:text="-Italic-Red-Under-"
     />
   <TextView 
    android:id="@+id/text"
     android:layout_width="fill_parent"
     android:layout_height="wrap_content"
     android:text="SmallBlueBig"
     android:bufferType="spannable"
     />
 <TextView 
    android:id="@+id/textlink"
     android:layout_width="fill_parent"
     android:layout_height="wrap_content"
     android:text="이름 : 이창욱. 프로필 보기. 연락처 수소문하기"
     android:bufferType="spannable"
     android:linksClickable="true"
     />
 </LinearLayout>
</ScrollView>

위 xml 을 보면 이상한 점이 있다. EditText는 bufferType을 지정하지 않은 것을 볼 수 있을 것이다. 그 이유는 TextView의 디폴트 bufferType은 normal이고 EditText의 디폴트 bufferType은 editable이다. 이 때문에 TextView를 상속받은 EditText는 실행중에 편집이 가능한 것이다.
여기까지 구현을 하면 아래와 같이 일반적인 TextView와 EditText 를 볼 수 있다.


아래는 Activity Class에서 각 TextView와 EditText에 span 정보를 추가하는 코드를 보겠다.

 TextView2Activity.java
 public class TextView2Activity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
       
        EditText edit = (EditText)findViewById(R.id.edit);
        Spannable espan = edit.getText();
        espan.setSpan(new StyleSpan(Typeface.ITALIC), 1, 7, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        // 1~7까지 Italic체로 Span적용

        espan.setSpan(new BackgroundColorSpan(0xffff0000), 8, 11, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
        // 8~11까지 0xffff0000 컬러로 백그라운드 지정
        

        
        TextView text = (TextView)findViewById(R.id.text);
        Spannable tspan = (Spannable) text.getText();
        tspan.setSpan(new RelativeSizeSpan(0.5f), 0, 5, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        // 폰트 사이즈 변경


        TextView link = (TextView) findViewById(R.id.textlink);
        Spannable lspan = (Spannable) link.getText();
       
        URLSpan profile = new URLSpan("") {
            public void onClick(View v) {
               Toast.makeText(v.getContext(), "검색한다.", 0).show();
            }
        };
        lspan.setSpan(profile, 10, 13, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        // 10~13 클릭시 profile객체의 onClick메소드 실행. (검색한다라는 Toast bar 가 보이게 된다.)
        
        link.setMovementMethod(LinkMovementMethod.getInstance());
    }
}

아래 실행화면을 보면 Italic, background색 변화, font size변경, 클릭시 Toast 메시지가 보이는 걸 볼 수 있다.


이런 식으로 실행중에 해당 TextView에 다양한 span을 적용할 수 있다.


입력받는 문자갯수 정하기Filter 사용
다음은 filter를 사용하여 입력받는 문자열의 갯수를 정하는 방법이다. HTML input의 maxlength 속성과 같은 역할이다.

EditText mLimitEdit = (EditText) findViewById(R.id.edit);
mLimitEdit.setFilter(new InputFilter[] {
   new InputFilter.LengthFilter(3)
});


커서 및 선택관리
TextView에는 아래와 같은 wrapper 메소드들이 제공된다.

int getSelectionStart()
int getSelectionEnd()
void setSelection(int start, int stop)
void setSelection(int index) // 커서 위치를 옮김
void selectAll()
void extendSelection(int index) // 현재 위치부터 지정된 index까지 선택

대부분의 메소드는 이름만 보아도 알만하니 추가 설명은 하지 않겠다.


반응형