android 本地持久化_android样式化的文本可替换和可本地化

android 本地持久化

Styled Texts can effect your UI/UX dramatically if used wisely but makes developer’s life harder. While developing UI with styled texts, Localization is the most crucial factor to consider. When you want to translate one language to another, word positions will be different most of the time. So, if you want to make bold a specific word in the text, the word’s position must be calculated dynamically.

如果使用得当,样式文本可以极大地影响您的UI / UX,但会使开发人员的生活更加艰难。 在开发带有样式文本的UI时,本地化是要考虑的最关键因素。 当您想将一种语言翻译成另一种语言时,大多数时候单词位置会有所不同。 因此,如果要将文本中的特定单词加粗,则必须动态计算单词的位置。

Previously, In Android Development, HTML formatting (which is Deprecated now in my opinion) was used pretty heavily. These formatting looks like this below.

以前,在Android开发中,HTML格式(我认为现在已弃用)已被大量使用。 这些格式如下所示。

People blame <b><i>machines</i></b> very often for, for it\’s oh, the machine\’s fault, how can it be the machine\’s fault?

人们经常责怪<b> <i> 机器 </ i> </ b>,因为它是机器的故障,怎么可能是机器的故障?

But as we all know that, HTML formatting is not suitable for all text changes such as changing custom font or inserting icon.

但是众所周知,HTML格式并不适合所有文本更改,例如更改自定义字体或插入图标。

So, I’ve started to use Annotation for this complex scenario. It basically uses the tags inside of the string to get dynamically computed text block area.

因此,对于这种复杂的情况,我已经开始使用注释。 它基本上使用字符串内部的标签来获取动态计算的文本块区域。

<string name="thanks_message"><annotation font="publicsans_medium">Thanks</annotation> <annotation replacement="user_name">usernamePlaceholder</annotation>for reading my blog post.</string>

After creating string in xml, we need to find where the “Thanks” and “usernamePlaceholder” are. After that, change font of “Thanks” and replace “usernamePlaceholder” with real username. With annotations, we can find these blocks and use Android Spans to make changes that we need.

在xml中创建字符串后,我们需要找到“ Thank ”和“ usernamePlaceholder”的位置。 之后,更改“ 谢谢 ”的字体并将“ usernamePlaceholder”替换为真实的用户名。 通过注释,我们可以找到这些块,并使用Android Spans进行所需的更改。

You may want to use the library. There’re examples on the README.md of library.

您可能要使用该 。 库的README.md上有示例。

If you don’t want to add another dependency to your project, I’m sharing the basic method and examples here below.

如果您不想在您的项目中添加其他依赖项,我将在下面共享基本方法和示例。

fun Context.getXmlStyledString(
    @StringRes stringResId: Int,
    replacementList: List<Pair<String, CharSequence>> = emptyList(),
    customAnnotations: List<Pair<String, Any>> = emptyList()
): CharSequence {
    val xmlText = resources.getText(stringResId)
    if (xmlText !is SpannedString) {
        return xmlText
    }


    val spannableString = SpannableStringBuilder(xmlText)
    xmlText.getSpans(0, xmlText.length, Annotation::class.java).forEach { annotation ->
        when (annotation.key) {
            "type" -> {
                when (annotation.value) {
                    "bold" -> StyleSpan(BOLD)
                    "underline" -> UnderlineSpan()
                    "italic" -> StyleSpan(ITALIC)
                    "bolditalic" -> StyleSpan(BOLD_ITALIC)
                    else -> null
                }?.let { span ->
                    spannableString.applySpan(span, annotation)
                }
            }
            "font" -> {
                spannableString.applyFontAnnotation(this, annotation)
            }
            "replacement" -> {
                replacementList.find { (key, _) ->
                    key == annotation.value
                }?.let { (_, replacementValue) ->
                    spannableString.replaceAnnotation(annotation, replacementValue)
                }
            }
            "custom" -> {
                val customAnnotation = customAnnotations.find { it.first == annotation.value }
                if (customAnnotation != null) {
                    spannableString.applySpan(customAnnotation.second, annotation)
                }
            }
        }
    }
    return spannableString
}


private fun SpannableStringBuilder.replaceAnnotation(
    annotation: Annotation,
    replacementValue: CharSequence
) {
    replace(
        getSpanStart(annotation),
        getSpanEnd(annotation),
        replacementValue
    )
}


private fun SpannableStringBuilder.applySpan(span: Any, annotation: Annotation) {
    setSpan(span, getSpanStart(annotation), getSpanEnd(annotation), SPAN_EXCLUSIVE_EXCLUSIVE)
}


private fun SpannableStringBuilder.applyFontAnnotation(context: Context, annotation: Annotation) {
    val fontName = annotation.value
    val typeface =
        ResourcesCompat.getFont(context, context.resources.getIdentifier(fontName, "font", context.packageName))
    if (typeface != null) {
        applySpan(CustomTypefaceSpan(typeface), annotation)
    }
}

You can access CustomTypefaceSpan class here.

您可以在此处访问CustomTypefaceSpan类。

没有库的示例: (Examples without library:)

粗体/斜体/下划线/粗体: (bold/italic/underline/bolditalic:)

Image for post
-- .xml
<string name="thanks_message"><annotation type="bold">Thanks</annotation> for reading through the documentation.</string>-- .kt
thanksMessageTextView.text = context.getXmlStyledString(R.string.thanks_message)

字型: (font:)

Image for post
-- .xml
<string name="thanks_message"><annotation font="publicsans_medium">Thanks</annotation> for reading through the documentation.</string>-- .kt
thanksMessageTextView.text = context.getXmlStyledString(R.string.thanks_message)

颜色: (color:)

Image for post
-- .xml
<string name="thanks_message"><annotation custom="thanks_color">Thanks</annotation> for reading through the documentation.</string>-- .kt
val thanksColor = ContextCompat.getColor(context, R.color.purple)
thanksMessageTextView.text = context.getXmlStyledString(
stringResId = R.string.thanks_message,
customAnnotations = listOf("thanks_color, ForegroundColorSpan(
)

替代: (replacement:)

Image for post
-- .xml
<string name="thanks_message">Thanks <annotation replacement="username">usernamePlaceholder</annotation> for reading through the documentation.</string>-- .kt
val replacementList = listOf("username" to "Yumi")
thanksMessageTextView.text = context.getXmlStyledString(
stringResId = R.string.thanks_message,
replacementList =
)

自定义: (custom:)

Image for post
-- .xml
<string name="thanks_message"><annotation custom="-- .kt
val thanksBackgroundColor = ContextCompat.getColor(context, R.color.purple)val customAnnotations = listOf(
"background_color" to BackgroundColorSpan(thanksBackgroundColor),
"android_icon" to ImageSpan(context, R.drawable.ic_android)
)thanksMessageTextView.text = context.getXmlStyledString(
stringResId = R.string.thanks_message,
)

These spans can be used together. Nested tags are supported for both library and these methods above. If you want to make replacement value bold. It’s doable.

这些跨度可以一起使用。 上面的库和这些方法都支持嵌套标记。 如果要使替换值加粗。 这是可行的。

Thanks Florina for this awesome blog. I hope everything now looks easier and practical.

感谢Florina这个很棒的博客 。 我希望现在一切看起来都简单实用。

Thanks for reading. Follow me on Twitter/GitHub for upcoming blogs/libraries.

谢谢阅读。 在Twitter / GitHub上关注我,了解即将推出的博客/库。

翻译自: https://proandroiddev.com/styled-texts-for-android-replaceable-and-localizable-dc0b25d01fe9

android 本地持久化

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值