Android中SpannableStringBuilder设置自定义字体不生效如何解决
问题根因
你调用SpannableStringBuilder.append(CharSequence text, Object what, int flags)方法时直接传入Typeface实例是无效的,Android富文本渲染体系只会识别MetricAffectingSpan子类的实例作为样式配置,原生不支持直接传入Typeface生效。同时你传入的flags参数为0,也不符合Span作用范围的标记要求。
解决方案
方案1:自定义TypefaceSpan(全版本兼容)
先实现自定义Span类绑定自定义字体:
import android.graphics.Paint import android.graphics.Typeface import android.text.TextPaint import android.text.style.TypefaceSpan class CustomTypefaceSpan(private val typeface: Typeface) : TypefaceSpan("") { override fun updateDrawState(ds: TextPaint) = applyTypeface(ds, typeface) override fun updateMeasureState(paint: TextPaint) = applyTypeface(paint, typeface) private fun applyTypeface(paint: Paint, tf: Typeface) { paint.typeface = tf } }
修改原有业务代码:
import android.text.Spannable import android.text.SpannableStringBuilder private fun createSpannedNameAndComment(name: String, comment: String): SpannableStringBuilder { // ResourcesCompat.getFont已直接返回Typeface实例,无需额外用Typeface.create包裹 val semiBoldFont = ResourcesCompat.getFont(this, R.font.josefin_san_semi_bold) ?: Typeface.DEFAULT_BOLD val regularFont = ResourcesCompat.getFont(this, R.font.josefin_san_regular) ?: Typeface.DEFAULT return SpannableStringBuilder().apply { // 设置名字段字体 append(name) setSpan( CustomTypefaceSpan(semiBoldFont), 0, name.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE ) append(" ") // 设置评论段字体 val commentStart = length append(comment) setSpan( CustomTypefaceSpan(regularFont), commentStart, length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE ) } }
方案2:使用AndroidX官方Span(无需自定义)
如果项目依赖AndroidX Core 1.1.0及以上版本,可以直接使用官方提供的androidx.core.text.style.TypefaceSpan,替换上述代码中的自定义CustomTypefaceSpan即可,无需额外写自定义类。
注意事项
- 把生成的Spannable设置给TextView时,不要调用
toString()转普通字符串,否则所有样式会丢失,直接赋值textView.text = 生成的Spannable实例即可。 - 确保字体文件存放于
res/font/目录下,命名仅包含小写字母、数字和下划线。
内容的提问来源于stack exchange,提问作者alfietap
相关产品推荐
相关产品推荐

