如何修改EditText输入内容中双星号包裹文本在TextView的展示字体?
Android EditText 实现双星号包裹文本自定义字体显示
实现思路
核心是不修改用户原始输入内容,仅通过Span修改显示效果:监听输入变化,正则匹配所有成对**包裹的内容,将首尾的**设为透明隐藏,中间的文本区域设置你需要的字体样式,既满足显示要求,也能保留原始输入里的星号字符。
具体实现步骤
- 首先给EditText添加文本变化监听,加标记位避免处理文本时触发循环回调
// 标记位:避免修改文本时重复触发监听 private boolean isFormatting = false; private TextWatcher formatWatcher = new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {} @Override public void onTextChanged(CharSequence s, int start, int before, int count) {} @Override public void afterTextChanged(Editable s) { if (isFormatting) return; isFormatting = true; // 处理富文本格式 formatAsteriskText(s); isFormatting = false; } }; // 初始化时给EditText设置监听 editText.addTextChangedListener(formatWatcher);
- 编写匹配处理函数,用正则匹配所有成对双星号包裹的内容,设置对应Span
private void formatAsteriskText(Editable editable) { // 先清除之前设置的所有Span,避免重复叠加 Object[] oldSpans = editable.getSpans(0, editable.length(), Object.class); for (Object span : oldSpans) { if (span instanceof ForegroundColorSpan || span instanceof TypefaceSpan || span instanceof StyleSpan) { editable.removeSpan(span); } } // 正则匹配成对的**包裹内容,非贪婪匹配+支持跨行 Pattern pattern = Pattern.compile("\\*\\*(.*?)\\*\\*", Pattern.DOTALL); Matcher matcher = pattern.matcher(editable); // 你需要的自定义字体,提前加载好,如果只需要加粗可跳过这行 Typeface customTypeface = Typeface.createFromAsset(getAssets(), "你的自定义字体文件名.ttf"); while (matcher.find()) { int start = matcher.start(); int end = matcher.end(); // 1. 把前后的**设为透明,隐藏显示 ForegroundColorSpan transparentSpan = new ForegroundColorSpan(Color.TRANSPARENT); editable.setSpan(transparentSpan, start, start + 2, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); ForegroundColorSpan transparentSpan2 = new ForegroundColorSpan(Color.TRANSPARENT); editable.setSpan(transparentSpan2, end - 2, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); // 2. 给中间的文本设置样式 int contentStart = start + 2; int contentEnd = end - 2; if (contentStart < contentEnd) { // 如果只是要加粗,直接用下面这行即可 // editable.setSpan(new StyleSpan(Typeface.BOLD), contentStart, contentEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); // 自定义字体用下面这行 editable.setSpan(new TypefaceSpan(customTypeface), contentStart, contentEnd, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); } } }
如果需要兼容Android 9以下版本的自定义字体设置,可自定义CustomTypefaceSpan继承MetricAffectingSpan,重写updateDrawState和updateMeasureState方法设置Typeface即可。
注意事项
- 上述方案不会修改用户输入的原始内容,调用
editText.getText().toString()获取到的文本还是包含原始**的,符合需求 - 对于不成对的
**不会被匹配,不会影响正常文本显示
内容的提问来源于stack exchange,提问作者Cynthia
相关产品推荐
相关产品推荐

