使用SpannableStringBuilder 代替SpannableString 并使用replace 方法。
试试这个代码,
String content = "Yeah, <em>This</em> is bold.";
SpannableStringBuilder s = new SpannableStringBuilder(content);
String startTag = "<em>";
int startTagLength = startTag.length();
String endTag = "</em>";
int endTagLength = endTag.length();
Matcher m = Pattern.compile(startTag + "(.*?)" + endTag).matcher(content);
while (m.find()) {
Log.e(TAG, "" + m.start(1));
Log.e(TAG, "" + m.end(1));
s.setSpan(new BackgroundColorSpan(R.color.red), m.start(1), m.end(1), 0);
s.replace(m.end(1), m.end(1) + endTagLength, "");
s.replace(m.start(1) - startTagLength, m.start(1), "");
}
TextView out = (TextView) findViewById(R.id.out);
out.setText(s);
编辑
Caique Monteiro Araujo 在 cmets 中提到它不适用于多个标签。原因是字符串长度在第二次迭代中被弄乱了,因为我在 while 循环本身中替换了字符串。
我很高兴 Caique Monteiro Araujo 找到了解决方法。以下是我的。我使用TreeMap 来存储(开始,结束)对并在另一个循环中替换标签。我不知道这是不是矫枉过正。
String content = "<em>This</em> is <em>bold</em>.";
SpannableStringBuilder s = new SpannableStringBuilder(content);
String startTag = "<em>";
int startTagLength = startTag.length();
String endTag = "</em>";
int endTagLength = endTag.length();
Matcher m = Pattern.compile(startTag + "(.*?)" + endTag).matcher(content);
// TreeMap to store the start and end pair
TreeMap<Integer, Integer> pair = new TreeMap<>();
while (m.find()) {
// Store the start and end
pair.put(m.start(1), m.end(1));
s.setSpan(new BackgroundColorSpan(R.color.red), m.start(1), m.end(1), 0);
}
// Use descendingMap to reverse the Map
NavigableMap<Integer, Integer> reversePair = pair.descendingMap();
// Replace the tags starting from the last occurrence to avoid messing the length
for (Integer key : reversePair.keySet()) {
Integer end = reversePair.get(key);
s.replace(end, end + endTagLength, "");
s.replace(key - startTagLength, key, "");
}
TextView out = (TextView) findViewById(R.id.out);
out.setText(s);