下面列出了android.text.SpannableStringBuilder#insert ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
@Override
public boolean em(Line line) {
line = line.get();
SpannableStringBuilder builder = (SpannableStringBuilder) line.getStyle();
Matcher matcher = obtain(Tag.EM, builder);
while (matcher.find()) {
int start = matcher.start(1);
int end = matcher.end(1);
if (checkInCode(builder, start, end)) {
continue;
}
SpannableStringBuilder sb = (SpannableStringBuilder) builder.subSequence(matcher.start(3), matcher.end(3));
builder.delete(matcher.start(1), matcher.end(1));
builder.insert(matcher.start(1), styleBuilder.em(sb));
em(line);
return true;
}
return false;
}
private void applyQuoteSpan(SpannableStringBuilder body, int start, int end, boolean darkBackground) {
if (start > 1 && !"\n\n".equals(body.subSequence(start - 2, start).toString())) {
body.insert(start++, "\n");
body.setSpan(new DividerSpan(false), start - 2, start, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
end++;
}
if (end < body.length() - 1 && !"\n\n".equals(body.subSequence(end, end + 2).toString())) {
body.insert(end, "\n");
body.setSpan(new DividerSpan(false), end, end + 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
int color;
if (activity.isOrangeTheme()) {
color = darkBackground ? this.getMessageTextColor(darkBackground, false) : ContextCompat.getColor(activity, R.color.darkorange);
} else {
color = darkBackground ? this.getMessageTextColor(darkBackground, false) : ContextCompat.getColor(activity, R.color.darkblue);
}
final DisplayMetrics metrics = getContext().getResources().getDisplayMetrics();
body.setSpan(new QuoteSpan(color, metrics), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
@Override
public boolean emItalic(Line line) {
line = line.get();
SpannableStringBuilder builder = (SpannableStringBuilder) line.getStyle();
Matcher matcher = obtain(Tag.EM_ITALIC, builder);
while (matcher.find()) {
int start = matcher.start(1);
int end = matcher.end(1);
if (checkInCode(builder, start, end)) {
continue;
}
SpannableStringBuilder sb = (SpannableStringBuilder) builder.subSequence(matcher.start(3), matcher.end(3));
builder.delete(matcher.start(1), matcher.end(1));
builder.insert(matcher.start(1), styleBuilder.emItalic(sb));
emItalic(line);
return true;
}
return false;
}
private static SpannableStringBuilder addNumbers(Spanned htmlSpanned, int numberFrom, int sp) {
int listItemCount = numberFrom-1;
SpannableStringBuilder spannableBuilder = new SpannableStringBuilder(htmlSpanned);
BulletSpan[] spans = spannableBuilder.getSpans(0, spannableBuilder.length(), BulletSpan.class);
if (spans != null) {
for (BulletSpan span : spans) {
int start = spannableBuilder.getSpanStart(span);
int end = spannableBuilder.getSpanEnd(span);
spannableBuilder.removeSpan(span);
++listItemCount;
spannableBuilder.insert(start, listItemCount + ". ");
spannableBuilder.setSpan(new LeadingMarginSpan.Standard(0, sip(sp)), start, end, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
}
}
return spannableBuilder;
}
@Override
public boolean link2(Line line) {
line = line.get();
SpannableStringBuilder builder = (SpannableStringBuilder) line.getStyle();
Matcher matcher = obtain(Tag.LINK2, builder);
if (matcher.find()) {
String title = matcher.group(2);
String id = matcher.group(3);
Pair<String, String> link = idLinkLinks.get(id);
if (link != null) {
builder.delete(matcher.start(1), matcher.end(1));
builder.insert(matcher.start(1), styleBuilder.link(title, link.first, link.second));
} else {
return false;
}
link2(line);
return true;
}
return false;
}
@Override
public boolean image(Line line) {
line = line.get();
SpannableStringBuilder builder = (SpannableStringBuilder) line.getStyle();
Matcher matcher = obtain(Tag.IMAGE, builder);
if (matcher.find()) {
String title = matcher.group(2);
String link = matcher.group(3);
String hint = matcher.group(6);
builder.delete(matcher.start(1), matcher.end(1));
builder.insert(matcher.start(1), styleBuilder.image(title, link, hint));
image(line);
return true;
}
return false;
}
@Override
public boolean image2(Line line) {
line = line.get();
SpannableStringBuilder builder = (SpannableStringBuilder) line.getStyle();
Matcher matcher = obtain(Tag.IMAGE2, builder);
if (matcher.find()) {
String title = matcher.group(2);
String id = matcher.group(3);
Pair<String, String> image = idImageUrl.get(id);
if (image != null) {
builder.delete(matcher.start(1), matcher.end(1));
builder.insert(matcher.start(1), styleBuilder.image(title, image.first, image.second));
} else {
return false;
}
image2(line);
return true;
}
return false;
}
@Override
public void closeOrderedListItem(SpannableStringBuilder out) {
OrderedList orderedList = getLast(out, OrderedList.class);
if (orderedList != null) {
int number = orderedList.getAndIncrement();
int where = out.getSpanStart(getLast(out, OrderedListItem.class));
out.insert(where, Integer.toString(number) + ". ");
}
//check BulletSpan2
end(out, OrderedListItem.class, new LeadingMarginSpan.LeadingMarginSpan2.Standard(leading));
}
@Override
public boolean code(Line line) {
line = line.get();
SpannableStringBuilder builder = (SpannableStringBuilder) line.getStyle();
Matcher matcher = obtain(Tag.CODE, builder);
if (matcher.find()) {
String content = matcher.group(3);
builder.delete(matcher.start(1), matcher.end(1));
builder.insert(matcher.start(1), styleBuilder.code(content));
code(line);
return true;
}
return false;
}
private void applyQuoteSpan(SpannableStringBuilder body, int start, int end, boolean darkBackground) {
if (start > 1 && !"\n\n".equals(body.subSequence(start - 2, start).toString())) {
body.insert(start++, "\n");
body.setSpan(new DividerSpan(false), start - 2, start, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
end++;
}
if (end < body.length() - 1 && !"\n\n".equals(body.subSequence(end, end + 2).toString())) {
body.insert(end, "\n");
body.setSpan(new DividerSpan(false), end, end + 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
int color = darkBackground ? this.getMessageTextColor(darkBackground, false)
: ContextCompat.getColor(activity, R.color.green700_desaturated);
DisplayMetrics metrics = getContext().getResources().getDisplayMetrics();
body.setSpan(new QuoteSpan(color, metrics), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
@Override
public boolean autoLink(Line line) {
line = line.get();
SpannableStringBuilder builder = (SpannableStringBuilder) line.getStyle();
Matcher matcher = obtain(Tag.AUTO_LINK, builder);
boolean m = false;
while (matcher.find()) {
String content = matcher.group();
builder.delete(matcher.start(), matcher.end());
builder.insert(matcher.start(), styleBuilder.link(content, content, ""));
m = true;
}
return m;
}
/**
* 文本转化表情处理
*
* @param editText 要显示的EditText
* @param maxLength 最长高度
* @param size 显示大小
* @param name 需要转化的文本
*/
public static void insertIcon(EditText editText, int maxLength, int size, String name) {
String curString = editText.toString();
if ((curString.length() + name.length()) > maxLength) {
return;
}
int resId = SmileUtils.getRedId(name);
Drawable drawable = editText.getResources().getDrawable(resId);
if (drawable == null)
return;
drawable.setBounds(0, 0, size, size);//这里设置图片的大小
CenteredImageSpan CenteredImageSpan = new CenteredImageSpan(drawable);
SpannableString spannableString = new SpannableString(name);
spannableString.setSpan(CenteredImageSpan, 0, spannableString.length(), SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE);
int index = Math.max(editText.getSelectionStart(), 0);
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(editText.getText());
spannableStringBuilder.insert(index, spannableString);
editText.setText(spannableStringBuilder);
editText.setSelection(index + spannableString.length());
}
private FixingResult addSpacesAroundSpansUntilFixed(SpannableStringBuilder builder,
int widthMeasureSpec, int heightMeasureSpec) {
Object[] spans = builder.getSpans(0, builder.length(), Object.class);
List<Object> spansWithSpacesBefore = new ArrayList<>(spans.length);
List<Object> spansWithSpacesAfter = new ArrayList<>(spans.length);
for (Object span : spans) {
int spanStart = builder.getSpanStart(span);
if (isNotSpace(builder, spanStart - 1)) {
builder.insert(spanStart, " ");
spansWithSpacesBefore.add(span);
}
int spanEnd = builder.getSpanEnd(span);
if (isNotSpace(builder, spanEnd)) {
builder.insert(spanEnd, " ");
spansWithSpacesAfter.add(span);
}
try {
setTextAndMeasure(builder, widthMeasureSpec, heightMeasureSpec);
return FixingResult.fixed(spansWithSpacesBefore, spansWithSpacesAfter);
} catch (IndexOutOfBoundsException ignored) {
}
}
if (HtmlTextView.DEBUG) {
Log.d(HtmlTextView.TAG, "Could not fix the Spanned by adding spaces around spans");
}
return FixingResult.notFixed();
}
private void addMarkdown(SpannableStringBuilder ssb, int start, int end, String markdown, int typeface) {
ssb.insert(end, markdown);
ssb.insert(start, markdown);
editText.getText().charAt(start);
editText.getText().charAt(start + 1);
ssb.setSpan(new StyleSpan(typeface), start, end + markdown.length() * 2, 1);
}
/**
* 插入表情
*
* @param name
*/
public void insertIcon(String name) {
String curString = getText().toString();
if ((curString.length() + name.length()) > richMaxLength) {
return;
}
int resId = SmileUtils.getRedId(name);
Drawable drawable = this.getResources().getDrawable(resId);
if (drawable == null)
return;
drawable.setBounds(0, 0, richIconSize, richIconSize);//这里设置图片的大小
ImageSpan imageSpan = new ImageSpan(drawable);
SpannableString spannableString = new SpannableString(name);
spannableString.setSpan(imageSpan, 0, spannableString.length(), SpannableString.SPAN_EXCLUSIVE_EXCLUSIVE);
int index = Math.max(getSelectionStart(), 0);
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder(getText());
spannableStringBuilder.insert(index, spannableString);
setText(spannableStringBuilder);
setSelection(index + spannableString.length());
}
private void bindText(TextView textView, SearchResult searchResult, String searchText) {
String text = searchResult.text;
if (TextUtils.isEmpty(text)) return;
text = text.replace("\n", " ");
if (TextUtils.isEmpty(searchText)) {
textView.setText(text);
} else {
int idx = text.toLowerCase().indexOf(searchText.toLowerCase());
if (idx >= 0) {
SpannableStringBuilder builder = new SpannableStringBuilder();
builder.append(text);
builder.setSpan(
textAppearanceSpan,
idx,
idx + searchText.length(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
);
if (idx > ELLIPSIZE_LIMIT_COUNT && searchResult.isDescriptionType()) {
builder.delete(0, idx - ELLIPSIZE_LIMIT_COUNT);
builder.insert(0, ELLIPSIZE_TEXT);
}
textView.setText(builder);
} else {
textView.setText(text);
}
}
}
/**
* Applies QuoteSpan to group of lines which starts with > or » characters.
* Appends likebreaks and applies DividerSpan to them to show a padding between quote and text.
*/
private boolean handleTextQuotes(SpannableStringBuilder body, boolean darkBackground) {
boolean startsWithQuote = false;
char previous = '\n';
int lineStart = -1;
int lineTextStart = -1;
int quoteStart = -1;
for (int i = 0; i <= body.length(); i++) {
char current = body.length() > i ? body.charAt(i) : '\n';
if (lineStart == -1) {
if (previous == '\n') {
if ((current == '>' && UIHelper.isPositionFollowedByQuoteableCharacter(body, i))
|| current == '\u00bb' && !UIHelper.isPositionFollowedByQuote(body, i)) {
// Line start with quote
lineStart = i;
if (quoteStart == -1) quoteStart = i;
if (i == 0) startsWithQuote = true;
} else if (quoteStart >= 0) {
// Line start without quote, apply spans there
applyQuoteSpan(body, quoteStart, i - 1, darkBackground);
quoteStart = -1;
}
}
} else {
// Remove extra spaces between > and first character in the line
// > character will be removed too
if (current != ' ' && lineTextStart == -1) {
lineTextStart = i;
}
if (current == '\n') {
body.delete(lineStart, lineTextStart);
i -= lineTextStart - lineStart;
if (i == lineStart) {
// Avoid empty lines because span over empty line can be hidden
body.insert(i++, " ");
}
lineStart = -1;
lineTextStart = -1;
}
}
previous = current;
}
if (quoteStart >= 0) {
// Apply spans to finishing open quote
applyQuoteSpan(body, quoteStart, body.length(), darkBackground);
}
return startsWithQuote;
}
/**
* 封topic的TextView
*
* @param str
* @return
*/
public void insertTopics(List<Topic> topics) {
if (topics == null || topics.size() == 0) {
return;
}
// 光标的位置
int editSection = getSelectionStart();
Log.d("", "### insertTopicText, start = " + editSection);
SpannableStringBuilder ssb = new SpannableStringBuilder(getText());
int count = topics.size();
for (int i = 0; i < count; i++) {
final Topic topicItem = topics.get(i);
final String name = topicItem.name + " ";
// 如果已经有了该好友,则直接返回
if (mTopicMap.containsValue(topicItem)) {
continue;
}
isDecorating = true;
int ssbLength = ssb.length();
if (editSection > ssbLength) {
editSection = ssbLength;
}
ssb.insert(editSection, name);
setText(ssb);
// 更新map索引
updateMapIndex(editSection, name.length());
Log.d("#####", "#####put start : " + editSection);
// 将所有at的位置存储在map中
mTopicMap.put(editSection, topicItem);
// 更新起始点
editSection += name.length();
}
// 包装文本
decorateText();
isDecorating = false;
setSelection(editSection);
mCursorIndex = editSection;
}
private void setContent(TextView tv, UserLog ul) {
if (!init) initDrawables(tv);
SpannableStringBuilder ssb = new SpannableStringBuilder();
UserLogMessage.TYPE type = UserLogMessage.TYPE.convert(ul.getType());
String clock = FormatKit.getInstance().formatAsDayClockSeconds(ul.getTimestamp());
String text = ul.getMessageParsed();
if (largeText) clock += "\n";
switch (type) {
case WARN:
ssb.append(" * ").append(text);
ssb.setSpan(new ImageSpan(iWARN, DynamicDrawableSpan.ALIGN_BASELINE), 1, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
ssb.setSpan(new ForegroundColorSpan(iWARN.getColor()), 3, text.length() + 3, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
break;
case HELP:
ssb.append(" * ").append(text);
ssb.setSpan(new ImageSpan(iHELP, DynamicDrawableSpan.ALIGN_BASELINE), 1, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
ssb.setSpan(new ForegroundColorSpan(iHELP.getColor()), 3, text.length() + 3, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
break;
case INFO:
ssb.append(" * ").append(text);
ssb.setSpan(new ImageSpan(iINFO, DynamicDrawableSpan.ALIGN_BASELINE), 1, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
ssb.setSpan(new ForegroundColorSpan(iINFO.getColor()), 3, text.length() + 3, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
break;
case NOTE:
ssb.append(" * ").append(text);
ssb.setSpan(new ImageSpan(iNOTE, DynamicDrawableSpan.ALIGN_BASELINE), 1, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
ssb.setSpan(new ForegroundColorSpan(iNOTE.getColor()), 3, text.length() + 3, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
break;
case HISTORY:
ssb.append(" * ").append(text);
ssb.setSpan(new ImageSpan(iREFRESH, DynamicDrawableSpan.ALIGN_BASELINE), 1, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
ssb.setSpan(new ForegroundColorSpan(iREFRESH.getColor()), 3, text.length() + 3, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
break;
case CGM:
ssb.append(" * ").append(text);
ssb.setSpan(new ImageSpan(iCGM, DynamicDrawableSpan.ALIGN_BASELINE), 1, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
ssb.setSpan(new ForegroundColorSpan(iCGM.getColor()), 3, text.length() + 3, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
break;
case OPTION:
ssb.append(" * ").append(text);
ssb.setSpan(new ImageSpan(iSETTING, DynamicDrawableSpan.ALIGN_BASELINE), 1, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
ssb.setSpan(new ForegroundColorSpan(iSETTING.getColor()), 3, text.length() + 3, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
break;
case STARTUP:
case SHUTDOWN:
case HEART:
ssb.append(" * ").append(text);
ssb.setSpan(new ImageSpan(iHEART, DynamicDrawableSpan.ALIGN_BASELINE), 1, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
ssb.setSpan(new ForegroundColorSpan(cHigh), 3, text.length() + 3, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
ssb.setSpan(new StyleSpan(Typeface.BOLD_ITALIC), 3, text.length() + 3, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
break;
case SGV:
ssb.append(" ").append(text);
ssb.setSpan(new ForegroundColorSpan(cHigh), 1, text.length() + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
break;
case ESTIMATE:
ssb.append(" ").append(text);
ssb.setSpan(new ForegroundColorSpan(cEestimate), 1, text.length() + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
break;
case ISIG:
ssb.append(" ").append(text);
ssb.setSpan(new ForegroundColorSpan(cIsig), 1, text.length() + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
break;
case REQUESTED:
case RECEIVED:
ssb.append(" ").append(text);
ssb.setSpan(new ForegroundColorSpan(cHistory), 1, text.length() + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
break;
case SHARE:
ssb.append(" * ").append(text);
ssb.setSpan(new ImageSpan(iSHARE, DynamicDrawableSpan.ALIGN_BASELINE), 1, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
ssb.setSpan(new ForegroundColorSpan(iSHARE.getColor()), 3, text.length() + 3, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
break;
case PUSHOVER:
ssb.append(" ").append(text);
ssb.setSpan(new ForegroundColorSpan(cPushover), 1, text.length() + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
break;
default:
ssb.append(" ").append(text);
ssb.setSpan(new ForegroundColorSpan(cNormal), 1, text.length() + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
ssb.insert(0, clock);
ssb.setSpan(new ForegroundColorSpan(cLow), 0, clock.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
ssb.setSpan(new RelativeSizeSpan(0.78f), 0, clock.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
tv.setText(ssb);
}
/**
* 处理at某人
*
* @param text 输入文本
* @param spannable 处理过的文本
* @param color 颜色
* @param listUser 用户列表
* @return Spannable
*/
private Spannable resolveAtInsert(String text, Spannable spannable, String color, List<UserModel> listUser) {
if (listUser == null || listUser.size() <= 0) {
return spannable;
}
//此处保存名字的键值
Map<String, String> names = new HashMap<>();
if (listUser.size() > 0) {
for (UserModel userModel : listUser) {
names.put(userModel.getUser_name(), userModel.getUser_name());
}
}
int length = spannable.length();
Pattern pattern = Pattern.compile("@[^\\s]+\\s?");
Matcher matcher = pattern.matcher(spannable);
SpannableStringBuilder spannableStringBuilder =
new SpannableStringBuilder(spannable);
for (int i = 0; i < length; i++) {
if (matcher.find()) {
String name = text.substring(matcher.start(), matcher.end());
if (names.containsKey(name.replace("\b", "").replace(" ", ""))) {
//直接用span会导致后面没文字的时候新输入的一起变色
Spanned htmlText = Html.fromHtml(String.format("<font color='%s'>" + name + "</font>", color));
spannableStringBuilder.replace(matcher.start(), matcher.start() + name.length(), htmlText);
int index = matcher.start() + htmlText.length();
if (index < text.length()) {
if (" ".equals(text.subSequence(index - 1, index))) {
spannableStringBuilder.replace(index - 1, index, "\b");
}
} else {
if (text.substring(index - 1).equals(" ")) {
spannableStringBuilder.replace(index - 1, index, "\b");
} else {
//如果是最后面的没有空格,补上\b
spannableStringBuilder.insert(index, "\b");
}
}
}
}
}
return spannableStringBuilder;
}