Android 는 SpannableString 을 이용 하여 웨 이 보 콘 텐 츠 포맷 을 실현 합 니 다.
10674 단어 androidSpannableString포맷
안 드 로 이 드 개발 에서 많은 정보 전 시 는 TextView 를 통 해 보 여 줘 야 합 니 다.일반적인 정보 만 보 여 준다 면 TextView setText(CharSequence str)설정 을 사용 하면 됩 니 다.그러나 TextView 의 이 내용 은 특정한 필드 를 캡 처 해 야 할 때 점 치기 와 응답 을 받 을 수 있 습 니 다.이 럴 때 SpannableString 을 사용 해 야 합 니 다.SpannableString 과 TextView 를 결합 하면 특정한 텍스트 에 대해 특정한 처 리 를 쉽게 할 수 있다.예 를 들 어 텍스트 색상,배경 색 을 수정 하고 문 자 를 그림 으로 바 꾸 어 실현 하 며 효 과 를 클릭 하 는 등 이다.
우선 최종 실현 효과 도 를 살 펴 보 자.
첫 번 째 카드 안의 웨 이 보 는 원본 텍스트 정보 이 고 두 번 째 카드 안의 웨 이 보 는 첫 번 째 포맷 된 텍스트 내용 으로 웨 이 보 안의'화제','표정','웹 링크',그리고'@사용자'를 모두 처리 하고 클릭 하여 공식 웨 이 보 에서 보 여 준 스타일 과 일치 하도록 한다.
구현 할 효과:
4.567917.화 제 를 변색 시 키 고 제시 에 대응 하 는 화제 의 텍스트 내용 을 클릭 할 수 있 습 니 다
정규 표현 식 정의
먼저'화제','표정','웹 링크','@사용자'에 대응 하 는 정규 표현 식 과 해당 하 는 Pattern 을 정의 합 니 다.SCHEME 는 다음 글 에서 구체 적 인 용 도 를 언급 할 것 이다.
public class WeiboPattern {
// # #
public static final String REGEX_TOPIC = "#[\\p{Print}\\p{InCJKUnifiedIdeographs}&&[^#]]+#";
// [ ]
public static final String REGEX_EMOTION = "\\[(\\S+?)\\]";
// url
public static final String REGEX_URL = "http://[a-zA-Z0-9+&@#/%?=~_\\\\-|!:,\\\\.;]*[a-zA-Z0-9+&@#/%=~_|]";
// @
public static final String REGEX_AT = "@[\\w\\p{InCJKUnifiedIdeographs}-]{1,26}";
public static final Pattern PATTERN_TOPIC = Pattern.compile(REGEX_TOPIC);
public static final Pattern PATTERN_EMOTION = Pattern.compile(REGEX_EMOTION);
public static final Pattern PATTERN_URL = Pattern.compile(REGEX_URL);
public static final Pattern PATTERN_AT = Pattern.compile(REGEX_AT);
public static final String SCHEME_TOPIC = "topic:";
public static final String SCHEME_URL = "url:";
public static final String SCHEME_AT = "at:";
}
일치 하 는 부분 을 추출 하고 SpannableString 포맷 사용 하기나 는 이 과정 을 하나의 방법 에 썼 다.아래 에 코드 를 직접 올 리 고 코드 에 상세 한 설명 이 있다.
/**
*
*
* @param context
* @param source
* @param textView TextView
* @return SpannableStringBuilder
*/
public static SpannableStringBuilder formatWeiBoContent(Context context, String source, TextView textView) {
// TextView , ImageSpan
int textSize = (int) textView.getTextSize();
// SpannableString ,
textView.setMovementMethod(LinkMovementMethod.getInstance());
// String SpannableStringBuilder
SpannableStringBuilder value = new SpannableStringBuilder(source);
//
Linkify.addLinks(value, WeiboPattern.PATTERN_TOPIC, WeiboPattern.SCHEME_TOPIC);
//
Linkify.addLinks(value, WeiboPattern.PATTERN_URL, WeiboPattern.SCHEME_URL);
// @
Linkify.addLinks(value, WeiboPattern.PATTERN_AT, WeiboPattern.SCHEME_AT);
//
MyClickableSpan clickSpan;
// addLinks ( URLSpan )
URLSpan[] urlSpans = value.getSpans(0, value.length(), URLSpan.class);
// URLSpan
for (final URLSpan urlSpan : urlSpans) {
//
clickSpan = new MyClickableSpan() {
@Override
public void onClick(View view) {
ToastUtils.makeShort(urlSpan.getURL());
}
};
//
if (urlSpan.getURL().startsWith(WeiboPattern.SCHEME_TOPIC)) {
int start = value.getSpanStart(urlSpan);
int end = value.getSpanEnd(urlSpan);
value.removeSpan(urlSpan);
//
value.setSpan(clickSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
// @
if (urlSpan.getURL().startsWith(WeiboPattern.SCHEME_AT)) {
int start = value.getSpanStart(urlSpan);
int end = value.getSpanEnd(urlSpan);
value.removeSpan(urlSpan);
// @
value.setSpan(clickSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
//
if (urlSpan.getURL().startsWith(WeiboPattern.SCHEME_URL)) {
int start = value.getSpanStart(urlSpan);
int end = value.getSpanEnd(urlSpan);
value.removeSpan(urlSpan);
SpannableStringBuilder urlSpannableString = getUrlTextSpannableString(context, urlSpan.getURL(), textSize);
value.replace(start, end, urlSpannableString);
//
value.setSpan(clickSpan, start, start + urlSpannableString.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
//
Matcher emotionMatcher = WeiboPattern.PATTERN_EMOTION.matcher(value);
while (emotionMatcher.find()) {
String emotion = emotionMatcher.group();
int start = emotionMatcher.start();
int end = emotionMatcher.end();
int resId = EmotionUtils.getImageByName(emotion);
if (resId != -1) { //
L.e("find emotion: " + emotion);
Drawable drawable = context.getResources().getDrawable(resId);
drawable.setBounds(0, 0, (int) (textSize * 1.3), (int) (textSize * 1.3));
// VerticalImageSpan , ImageSpan
VerticalImageSpan imageSpan = new VerticalImageSpan(drawable);
value.setSpan(imageSpan, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
return value;
}
private static SpannableStringBuilder getUrlTextSpannableString(Context context, String source, int size) {
SpannableStringBuilder builder = new SpannableStringBuilder(source);
String prefix = " ";
builder.replace(0, prefix.length(), prefix);
Drawable drawable = context.getResources().getDrawable(R.drawable.ic_status_link);
drawable.setBounds(0, 0, size, size);
builder.setSpan(new VerticalImageSpan(drawable), prefix.length(), source.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
builder.append(" ");
return builder;
}
getUrlTextSpannableString()
:방법 은 아이콘+"웹 링크"SpannableString 을 되 돌려 주 는 것 입 니 다.링크 텍스트 를 바 꾸 는 데 사 용 됩 니 다.위 에 서 는'화제','표정','웹 링크'를 모두 addLinks 방법 으로 표시 한 다음 에 통일 적 으로 처리 했다.표정 은 따로 처리 했다.
표정 은 다음 과 같은 방법 으로 미리 매 핑 을 한다.
public class EmotionUtils {
public static LinkedHashMap<String, Integer> sMap;
static {
sMap = new LinkedHashMap<>();
sMap.put("[doge]", R.drawable.d_doge);
sMap.put("[ ]", R.drawable.d_wu);
}
public static int getImageByName(String name) {
Integer integer = sMap.get(name);
return integer == null ? -1 : integer;
}
}
그리고 방금 말 한 사용자 정의 MyClickableSpan 은 기본 스타일 을 수정 합 니 다.
public class MyClickableSpan extends ClickableSpan {
@Override
public void onClick(View view) {
}
@Override
public void updateDrawState(TextPaint ds) {
super.updateDrawState(ds);
ds.setColor(0xff03A9F4);
ds.setUnderlineText(false);
}
}
또한,기본 ImageSpan 은 TextView 에서 android:lineSpacingExtra 속성 을 사용 할 때 수직 으로 가운데 에 있 지 않 기 때문에 ImageSpan 에서 계승 한 Vertical ImageSpan 을 사용 하면 TextView 에서 그림 을 수직 으로 유지 할 수 있 습 니 다.
public class VerticalImageSpan extends ImageSpan {
public VerticalImageSpan(Drawable drawable) {
super(drawable);
}
/**
* update the text line height
*/
@Override
public int getSize(Paint paint, CharSequence text, int start, int end,
Paint.FontMetricsInt fontMetricsInt) {
Drawable drawable = getDrawable();
Rect rect = drawable.getBounds();
if (fontMetricsInt != null) {
Paint.FontMetricsInt fmPaint = paint.getFontMetricsInt();
int fontHeight = fmPaint.descent - fmPaint.ascent;
int drHeight = rect.bottom - rect.top;
int centerY = fmPaint.ascent + fontHeight / 2;
fontMetricsInt.ascent = centerY - drHeight / 2;
fontMetricsInt.top = fontMetricsInt.ascent;
fontMetricsInt.bottom = centerY + drHeight / 2;
fontMetricsInt.descent = fontMetricsInt.bottom;
}
return rect.right;
}
/**
* see detail message in android.text.TextLine
*
* @param canvas the canvas, can be null if not rendering
* @param text the text to be draw
* @param start the text start position
* @param end the text end position
* @param x the edge of the replacement closest to the leading margin
* @param top the top of the line
* @param y the baseline
* @param bottom the bottom of the line
* @param paint the work paint
*/
@Override
public void draw(Canvas canvas, CharSequence text, int start, int end,
float x, int top, int y, int bottom, Paint paint) {
Drawable drawable = getDrawable();
canvas.save();
Paint.FontMetricsInt fmPaint = paint.getFontMetricsInt();
int fontHeight = fmPaint.descent - fmPaint.ascent;
int centerY = y + fmPaint.descent - fontHeight / 2;
int transY = centerY - (drawable.getBounds().bottom - drawable.getBounds().top) / 2;
canvas.translate(x, transY);
drawable.draw(canvas);
canvas.restore();
}
}
그리고 이 방법 을 직접 호출 하여 포맷 합 니 다:
mTextView.setText(formatWeiBoContent(this,mTextView.getText().toString(),mTextView))
최종 효과 그림 은 글 의 시작 효과 와 같 고 클릭 할 수 있 습 니 다.'웹 링크'를 클릭 할 때 나타 나 는 Toast 알림 을 보 여 줍 니 다.총결산
본 고 는 SpannableString 이 자주 사용 하 는 장면 만 소개 했다.예 를 들 어 특정한 텍스트 의 색 채 를 수정 하고 특정한 텍스트 를 교체 하 며 특정한 텍스트 의 클릭 이 벤트 를 소개 했다.그러나 SpannableString 의 강 함 은 이 뿐만 이 아니다.SpannableString 의 더 많은 용법 은 공식 문 서 를 읽 을 수 있 습 니 다.자,이상 이 이 글 의 전체 내용 입 니 다.본 논문 의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 도움 이 되 기 를 바 랍 니 다.궁금 한 점 이 있 으 시 면 댓 글 을 남 겨 주 셔 서 저희 에 대한 지지 에 감 사 드 립 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Kotlin의 기초 - 2부지난 글에서는 Kotlin이 무엇인지, Kotlin의 특징, Kotlin에서 변수 및 데이터 유형을 선언하는 방법과 같은 Kotlin의 기본 개념에 대해 배웠습니다. 유형 변환은 데이터 변수의 한 유형을 다른 데이터...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.