소스

Android SpannableStringBuilder BulletSpan Custom (ImageBulletSpan)

잘구운토스트 2016. 12. 6. 13:39



BulletSpan은 아래처럼 텍스트에 글머리 기호를 넣는 기능이다.

하지만 글머리 기호는 변경할 수가 없다.


그래서 필자는 글머리 기호를 이미지로 표현하는 BulletSpan을 만들어보았다.




먼저 LeadingMarginSpan을 implements한 클래스를 하나 생성하고

아래와 같이 getLeadingMargin(), drawLeadingMargin()을 오버라이드한다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class ImageBulletSpan implements LeadingMarginSpan {
 
    @Override
    public int getLeadingMargin(boolean first) {
        return 0;
    }
 
    @Override
    public void drawLeadingMargin(Canvas c, Paint p, int x, int dir, int top, int baseline, 
                            int bottom, CharSequence text, 
                            int start, int end, boolean first, Layout layout) {
 
    }
}
cs



우선 글머리 기호를 비트맵으로 받아와서 Text와 비트맵의 크기를 계산하여 센터에 맞춰

이미지를 넣는 작업을 drawLeadingMargin()에서 처리한다.

구현은 아래와 같이 하면 될듯 하다.


1
2
3
4
5
6
7
8
9
10
11
12
13
@Override
public void drawLeadingMargin(Canvas c, Paint p, int x, int dir, int top, int baseline, 
                        int bottom, CharSequence text, 
                        int start, int end, boolean first, Layout layout) {
if (((Spanned) text).getSpanStart(this== start) {   // 시작점인지 체크
        float textCenter = (top + bottom) / 2.0f;        // text의 가운데 사이즈
        float imgCenter = mBitmap.getHeight() / 2.0f;    // 이미지의 가운데 사이즈
        c.save();
        mOffset = textSize - imgCenter;                  // 이미지가 text의 가운데로 정렬되기위한 top margin
        c.drawBitmap(mBitmap, 0, mOffset, new Paint());  // 이미지 세팅
        c.restore();
    }
}
cs



다음은  글머리 기호의 영역을 체크하여 글머리 기호 영역 이후에 text를 노출하고

text의 길이가 라인을 넘길 경우 들여쓰기하는 작업을 getLeadingmargin()에서 처리한다.


1
2
3
4
@Override
public int getLeadingMargin(boolean first) {
    return mBitmap.getWidth() + mGapWidth;    // mGapWidth는 이미지와 Text간의 간격을 의미한다.
}
cs


사용법은 기존 SpannableStringBuilder의 setSpan()을 사용하는 방법과 동일하게 하면 OK.


1
2
3
4
5
6
7
SpannableStringBuilder sb = new SpannableStringBuilder(text);
 
ImageBulletSpan bulletSpan = new ImageBulletSpan(this, R.drawable.icon_tip);
sb.setSpan(bulletSpan, 0, text.length(), 0);
 
TextView tvBullet = getTextView();
tvBullet.setText(sb);
cs



실행결과는 아래와 같다.




파일 첨부..


ImageBulletSpan.java


(사용하다가 개선할게 있으면 언제든지 변경해서 사용해도 상관없으나 필자에게도 알려주면 좋겠다.ㅠㅠ)