android – 如何使用支持库字体功能作为TextView内容的一部分(使用spannable)?

前端之家收集整理的这篇文章主要介绍了android – 如何使用支持库字体功能作为TextView内容的一部分(使用spannable)?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
背景

支持库(docs here)允许您在XML中使用“res / font”文件夹中的TTF字体文件

app:fontFamily="@font/lato_black"

或通过代码

val typeface = ResourcesCompat.getFont(context,R.font.lato_black)

问题

虽然我知道可以使用spannable技术在TextView内容的部分内容中设置不同的样式(例如粗体,斜体,颜色等等),但我发现设置不同字体的唯一方法就是使用操作系统的内置字体,如here所示,但我无法看到一种方法来为新的方式加载字体.

我试过的

我试图找到一种方法来转换两者,但没有运气.当然,我也试图在可能的功能的文档中找到,我试图通过互联网找到它.

这个问题

如何为TextView的不同部分设置不同的字体?

例如,在文本“Hello world”中,将“Hello”设置为“lato_black”的字体,其余为默认值.

编辑:由于我得到了来自两个不同的人的相同答案,我不能接受另一个.给他们两个努力,我已经改变了一点问题:

我如何轻松地将字体样式设置为文本的一部分,同时让strings.xml文件使用自定义字体标记定义它.

例如,这可以在strings.xml文件中进行设置,如上所述:

<string name="something" ><customFont fontResource="lato_black">Hello</customFont> world</string>

然后,在代码中,您要做的就是使用以下内容

textView.setText (Html.fromHtml(text,null,CustomFontTagHandler()))

我认为这非常重要,因为翻译后的字符串可能与英语中的字符串差别太大,因此您不能只解析字符串的文本,然后选择设置自定义字体的位置.它必须在字符串文件中.

解决方法

由于MJM和TheMatrix的答案几乎相同(但对我来说过于复杂)并且两者都在同一时间被回答,我不能只选择其中一个,所以我给每个人一个,要求他们做到更短但支持XML标记,以便更轻松地处理字符串文件.

现在,这是如何为TextView中的部分文本设置自定义字体的更短版本:

class CustomTypefaceSpan(private val typeface: Typeface?) : MetricAffectingSpan() {
    override fun updateDrawState(paint: TextPaint) {
        paint.typeface=typeface
    }

    override fun updateMeasureState(paint: TextPaint) {
        paint.typeface=typeface
    }
}

样品用法

val text = "Hello world"
    val index = text.indexOf(' ')
    val spannable = SpannableStringBuilder(text)
    spannable.setSpan(CustomTypefaceSpan(ResourcesCompat.getFont(this,R.font.lato_light)),index,Spanned.SPAN_EXCLUSIVE_INCLUSIVE)
    spannable.setSpan(CustomTypefaceSpan(ResourcesCompat.getFont(this,R.font.lato_bold)),text.length,Spanned.SPAN_EXCLUSIVE_INCLUSIVE)
    textView.text = spannable

编辑:似乎谷歌提供了一个关于此的视频,here

class CustomTypefaceSpan(val font: Typeface?) : MetricAffectingSpan() {
    override fun updateMeasureState(textPaint: TextPaint) = update(textPaint)
    override fun updateDrawState(textPaint: TextPaint?) = update(textPaint)

    private fun update(tp: TextPaint?) {
        tp.apply {
            val old = this!!.typeface
            val oldStyle = old?.style ?: 0
            val font = Typeface.create(font,oldStyle)
            typeface = font
        }
    }
}

并且在视频here中也讨论了在strings.xml中处理它的解决方案,但是使用注释而不是新的HTML标记.例:

strings.xml中

<string name="title"><annotation font="lato_light">Hello</annotation> <annotation font="lato_bold">world</annotation></string>

MainActivity.kt

val titleText = getText(R.string.title) as SpannedString
    val spannable = SpannableStringBuilder(titleText)
    val annotations = titleText.getSpans(0,titleText.length,android.text.Annotation::class.java)
    for (annotation in annotations) {
        if(annotation.key=="font"){
            val fontName=annotation.value
            val typeface= ResourcesCompat.getFont(this@MainActivity,resources.getIdentifier(fontName,"font",packageName))
            spannable.setSpan(CustomTypefaceSpan(typeface),spannable.getSpanStart(annotation),spannable.getSpanEnd(annotation),Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
        }
    }
    textView.text = spannable

结果如下:

我仍然很确定可以使用fromHtml,但它可能不值得.

如果我们想要使用基本HTML标签和我们为字体设置的cusomzied,如果我们确实在那里使用注释,我也想知道应该怎么做.

猜你在找的Android相关文章