【Android】Spannable String:使用 Span 的文本样式

前言

文本样式是增强 Android 应用程序 UI 的重要方面之一。在 Android 中,我们可以更改文本的大小、颜色、粗细、样式等,使文本更具吸引力和吸引力。

但是考虑一种情况,当您希望 TextView 的不同部分使用不同的颜色时。例如,如果文本是“Hello Android”,并且您希望“Hello”的颜色为绿色,“Android”的颜色为红色。你怎么能做到这一点?您可以制作两个 TextView 并将 textColor 分别设置为绿色和红色。但这不是这样做的好方法。因此,在 Spans 的帮助下,文本样式的作用就出现了。

在这篇文章中,我们将学习如何使用 Spans 来设置应用程序中使用的文本样式。我们将讨论以下主题:

  • 什么是跨度?
  • 为 TextView 中的不同单词更改不同的颜色
  • 可扩展标志
  • 更改 TextView 某些部分的背景颜色
  • 多个跨度到相同的文本
  • 同一个TextView中字符串的不同字体大小
  • 在 TextView 中为部分文本添加下划线
  • 设置 TextView Clickable 的某些部分
  • 在 Android 中添加项目符号列表

什么是跨度?

跨度是用于在字符级别(例如,更改不同单词的颜色)或段落级别(例如,制作项目符号列表)设置文本样式的标记对象。

为了在 Spans 的帮助下设置文本样式,可以使用以下三个类:

  • SpannedString:在创建后不需要修改文本或标记时使用。
  • SpannableString:当不需要修改文本但您需要修改标记时使用,即您需要在文本中添加一些跨度。
  • SpannableStringBuilder:当您需要修改文本和标记时使用它。

这是关于 Android 中 Spans 的快速介绍。现在,让我们看看它的一些用例。在我们所有的示例中,我们将使用以下具有 id 的 TextView tvMessage:

<TextView
    android:id="@+id/tvMessage"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_margin="8dp"
    android:gravity="center"
    android:textColor="@color/black"
    android:textSize="24sp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    tools:text="Hello World!" />

为 TextView 中的不同单词更改不同的颜色

在某些情况下,您希望为同一文本视图的不同部分使用不同的颜色。所以,在这里你可以使用ForegroundColorSpan.

val spannable = SpannableString("You can start learning Android from MindOrks")
spannable.setSpan(
    ForegroundColorSpan(Color.RED),
    36, // start
    44, // end
    Spannable.SPAN_EXCLUSIVE_INCLUSIVE
)
tvMessage.text = spannable

在这里,我们将“MindOrks”的颜色更改为红色。

如果您查看代码,那么您会发现我们正在使用SpannableString该类,因为我们有一个固定的文本。此外,我们正在使用该setSpan方法设置从字符串中第 36 位开始到第 44 位结束的文本的前景色。此外,我们正在传递一些标志,即Spannable.SPAN_EXCLUSIVE_INCLUSIVE.

让我们了解这些标志。

可扩展标志

Spans 可以使用许多标志,但最常用的标志是:

  • SPAN_EXCLUSIVE_EXCLUSIVE
  • SPAN_EXCLUSIVE_INCLUSIVE
  • SPAN_INCLUSIVE_EXCLUSIVE
  • SPAN_INCLUSIVE_INCLUSIVE

这些标志用于告诉 Span 是否应该包含在开始或结束位置插入的文本。Inclusive 表示将其添加到 Span 中,exclusive 表示将其从 Span 中删除。

如果您使用的是不可变字符串,即如果您没有在原始字符串中添加其他字符串,那么所有四个标志都将起作用。但是如果你使用的是可变字符串,那么这四个标志的作用就会发挥作用。让我们借助一个例子来理解这一点。

在这里,我们将在原始字符串中插入一些文本。因此,如前所述,对于可变字符串,我们需要使用SpannableStringBuilder.

val spannableStringBuilder = SpannableStringBuilder("Android")
spannableStringBuilder.setSpan(
    ForegroundColorSpan(Color.RED),
    1, // start
    4, // end
    Spannable.SPAN_INCLUSIVE_INCLUSIVE
)
spannableStringBuilder.insert(4, "1")
spannableStringBuilder.insert(1, "1")
tvMessage.text = spannableStringBuilder

多个跨度到相同的文本

setSpan您也可以在单个文本上多次使用该方法。例如,如果要更改文本的颜色,同时使其变为粗体和斜体,则可以通过以下方式执行此操作:

val spannable = SpannableString("You can start learning Android from MindOrks")
spannable.setSpan(
    ForegroundColorSpan(Color.RED),
    36, // start
    44, // end
    Spannable.SPAN_EXCLUSIVE_INCLUSIVE
)
spannable.setSpan(
    StyleSpan(Typeface.BOLD_ITALIC),
    36, // start
    44, // end
    Spannable.SPAN_EXCLUSIVE_INCLUSIVE
)
tvMessage.text = spannable

这里,文本的颜色是红色,同时是粗体和斜体。

您可以根据setSpan需要多次使用该方法。

更改 TextView 某些部分的背景颜色

您可以使用 更改 TextView 中部分文本的背景颜色BackgroundColorSpan。

val spannable = SpannableString("You can start learning Android from MindOrks")
spannable.setSpan(
    BackgroundColorSpan(Color.RED),
    36, // start
    44, // end
    Spannable.SPAN_EXCLUSIVE_INCLUSIVE
)
tvMessage.text = spannable

在这里,我们将背景更改为红色。

同一个TextView中字符串的不同字体大小

您可以使用RelativeSizeSpan来更改 TextView 某些部分的大小。文本大小的变化将是相对的,即相对于字符串中的其他文本。

val spannable = SpannableString("You can start learning Android from MindOrks")
spannable.setSpan(
    RelativeSizeSpan(2f),
    36, // start
    44, // end
    Spannable.SPAN_EXCLUSIVE_INCLUSIVE
)
tvMessage.text = spannable

在这里,“MindOrks”的大小2f比其他文本大。

在 TextView 中为部分文本添加下划线

您可以使用以下方式为文本的一部分添加下划线UnderlineSpan:

val spannable = SpannableString("You can start learning Android from MindOrks")
spannable.setSpan(
    UnderlineSpan(),
    36, // start
    44, // end
    Spannable.SPAN_EXCLUSIVE_INCLUSIVE
)
tvMessage.text = spannable

设置 TextView Clickable 的某些部分

您可以使用ClickableSpan. 例如:

val spanText = SpannableStringBuilder("MindOrks")

val clickableMindOrks = object : ClickableSpan() {
    override fun onClick(view: View) {
        Toast.makeText(view.context, "MindOrks Clicked!", Toast.LENGTH_SHORT).show()
    }
}
spanText.setSpan(
    clickableMindOrks,
    0,
    spanText.length,
    0
)
spanText.setSpan(
    ForegroundColorSpan(Color.RED),
    0, // start
    8, // end
    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
)
tvMessage.setText(spanText, TextView.BufferType.SPANNABLE)

在这里,点击“MindOrks”会显示一个 toast。

在 Android 中添加项目符号列表

在 的帮助下BulletSpan,您可以在应用程序中创建一个项目符号列表,以便以简短的方式显示一些信息。

// function to covert a list into bullet list
fun convertToBulletList(stringList: List<String>): CharSequence {
    val spannableStringBuilder = SpannableStringBuilder("Learn Android from\n")
    stringList.forEachIndexed { index, text ->
        val line: CharSequence = text + if (index < stringList.size - 1) "\n" else ""
        val spannable: Spannable = SpannableString(line)
        spannable.setSpan(
            BulletSpan(15, Color.RED),
            0,
            spannable.length,
            Spanned.SPAN_INCLUSIVE_EXCLUSIVE
        )
        spannableStringBuilder.append(spannable)
    }
    return spannableStringBuilder
}
val androidResourceList = listOf("MindOrks Course", "MindOrks Blog", "MindOrks OpenSource", "MindOrks YouTube")
tvMessage.text = convertToBulletList(androidResourceList)

因此,通过这种方式,我们可以使用 Spans 来设置应用程序中的文本样式。

希望你今天学到了一些新东西,我相信你很快就会在你的应用程序中使用这些很棒的功能。

作者:Sumit Mishra
链接:https://blog.mindorks.com/spannable-string-text-styling-with-spans

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,377评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,390评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,967评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,344评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,441评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,492评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,497评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,274评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,732评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,008评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,184评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,837评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,520评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,156评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,407评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,056评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,074评论 2 352

推荐阅读更多精彩内容