You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 10:48:03