对于用户界面而言,文本是最基础而又核心的内容,在传统的 Android Native 开发中,需要用一个TextView来显示一个文本。在Jetpack Compose 中,提供了Text可组合函数(即组件,后面的文章都会称其为“组件”),可更轻松的显示文本。在本文中,将带大家一起探索Text组件的各种用法。

Text 属性介绍
在Jetpack Compose 中,组件是一个特殊的Kotlin 函数,因此Text其实也是一个函数,而它提供了很多参数来配置文本的显示外观。这些参数就是组件的属性。看一下Text组件有哪些属性:
@Composable
fun Text(
// 显示的文本字符串
text: String,
// 修改器,可以配置文本的大小及显示外观
modifier: Modifier = Modifier,
// 文本的颜色
color: Color = Color.Unspecified,
// 文本的字号大小
fontSize: TextUnit = TextUnit.Unspecified,
// 文字样式
fontStyle: FontStyle? = null,
// 文字粗细
fontWeight: FontWeight? = null,
// 文本字体
fontFamily: FontFamily? = null,
// 文字间的间距
letterSpacing: TextUnit = TextUnit.Unspecified,
// 文字添加装饰,可以添加上划线、下划线、中划线
textDecoration: TextDecoration? = null,
// 文本的对齐方式
textAlign: TextAlign? = null,
// 每一行的行高
lineHeight: TextUnit = TextUnit.Unspecified,
// 文本溢出的显示效果
overflow: TextOverflow = TextOverflow.Clip,
// 是否自动换行
softWrap: Boolean = true,
// 最多显示几行
maxLines: Int = Int.MAX_VALUE,
// 计算布局时的回调
onTextLayout: (TextLayoutResult) -> Unit = {},
// 样式
style: TextStyle = LocalTextStyle.current
) {
...
}
复制代码
Jetpack Compose 中,很多地方都用到了Kotlin 的特性,比如这里,就用到Kotlin的默认参数,Text 组件除了第一个参数text,其他都有默认值,也就是使用的时候可以不传,但是如果传多个参数时,一定要加参数名。比如,设置大小:
@Composable
fun MyText(){
Text("Jetpack Compose,by 依然范特稀西",
fontSize = 20.sp
)
}
复制代码
第一个参数可以加参数名,也可以不加,但我个人还是推荐加上,因为他是一个组件,参数是它的属性,这样代码比较直观。像下面这样就比较好一点:
@Composable
fun MyText(){
Text(
text = "Jetpack Compose,by 依然范特稀西",
fontSize = 20.sp
)
}
复制代码
知道了,每个属性的意思,我们接下来一起看看,配置各属性后的效果展示。
Text各属性示例效果
text 显示文本
Jetpack Compose系列-Text组件花式使用!
对于用户界面而言,文本是最基础而又核心的内容,在传统的 Android Native 开发中,需要用一个TextView来显示一个文本。在Jetpack Compose 中,提供了Text可组合函数(即组件,后面的文章都会称其为“组件”),可更轻松的显示文本。在本文中,将带大家一起探索Text组件的各种用法。
Text 属性介绍
在Jetpack Compose 中,组件是一个特殊的Kotlin 函数,因此Text其实也是一个函数,而它提供了很多参数来配置文本的显示外观。这些参数就是组件的属性。看一下Text组件有哪些属性:
@Composable
fun Text(
// 显示的文本字符串
text: String,
// 修改器,可以配置文本的大小及显示外观
modifier: Modifier = Modifier,
// 文本的颜色
color: Color = Color.Unspecified,
// 文本的字号大小
fontSize: TextUnit = TextUnit.Unspecified,
// 文字样式
fontStyle: FontStyle? = null,
// 文字粗细
fontWeight: FontWeight? = null,
// 文本字体
fontFamily: FontFamily? = null,
// 文字间的间距
letterSpacing: TextUnit = TextUnit.Unspecified,
// 文字添加装饰,可以添加上划线、下划线、中划线
textDecoration: TextDecoration? = null,
// 文本的对齐方式
textAlign: TextAlign? = null,
// 每一行的行高
lineHeight: TextUnit = TextUnit.Unspecified,
// 文本溢出的显示效果
overflow: TextOverflow = TextOverflow.Clip,
// 是否自动换行
softWrap: Boolean = true,
// 最多显示几行
maxLines: Int = Int.MAX_VALUE,
// 计算布局时的回调
onTextLayout: (TextLayoutResult) -> Unit = {},
// 样式
style: TextStyle = LocalTextStyle.current
) {
...
}
复制代码
Jetpack Compose 中,很多地方都用到了Kotlin 的特性,比如这里,就用到Kotlin的默认参数,Text 组件除了第一个参数text,其他都有默认值,也就是使用的时候可以不传,但是如果传多个参数时,一定要加参数名。比如,设置大小:
@Composable
fun MyText(){
Text("Jetpack Compose,by 依然范特稀西",
fontSize = 20.sp
)
}
复制代码
第一个参数可以加参数名,也可以不加,但我个人还是推荐加上,因为他是一个组件,参数是它的属性,这样代码比较直观。像下面这样就比较好一点:
@Composable
fun MyText(){
Text(
text = "Jetpack Compose,by 依然范特稀西",
fontSize = 20.sp
)
}
复制代码
知道了,每个属性的意思,我们接下来一起看看,配置各属性后的效果展示。
Text各属性示例效果
text 显示文本
显示文字的最简单的方法是使用以 String 作为参数的 Text 组件:
@Composable
fun MyText(){
Text("Jetpack Compose,by 依然范特稀西")
}
复制代码
也可以显示字符串资源,这也是推荐的方式,而不是直接将字符串写死在代码中,这样有利于替换或者国际化。
<!-- xml资源文件-->
<resources>
<string name="my_text">Jetpack Compose,by 依然范特稀西</string>
</resources>
@Composable
fun MyText(){
Text(stringResource(R.string.my_text))
}
复制代码

color 更改文字颜色
@Composable
fun MyText() {
Text(
text = stringResource(R.string.my_text),
color = Color.Blue
)
}
复制代码

fontSize 更改文字大小
@Composable
fun MyText() {
Text(
text = stringResource(R.string.my_text),
color = Color.Blue,
fontSize = 30.sp,
)
}
复制代码

fontStyle 设置文字样式
fontStyle有2个取值,FontStyle.Italic和FontStyle.Normal
@Composable
fun MyText() {
Column{
Text(
text = stringResource(R.string.my_text),
fontStyle = FontStyle.Normal,
)
Text(
text = stringResource(R.string.my_text),
fontStyle = FontStyle.Italic,
)
}
}
复制代码

fontWeight 更改文字的粗细程度
fontWeight 可以取 1- 1000之间的值,使用的时候,构造一个FontWeight即可:
FontWeight(50)
复制代码
FontWeight 默认为我们定义几个默认值,100-900的整百值,并根据他们的显示效果取名为Bold,Light,Thin等等。
companion object {
/** [Thin] */
@Stable
val W100 = FontWeight(100)
/** [ExtraLight] */
@Stable
val W200 = FontWeight(200)
/** [Light] */
@Stable
val W300 = FontWeight(300)
/** [Normal] / regular / plain */
@Stable
val W400 = FontWeight(400)
/** [Medium] */
@Stable
val W500 = FontWeight(500)
/** [SemiBold] */
@Stable
val W600 = FontWeight(600)
/** [Bold] */
@Stable
val W700 = FontWeight(700)
/** [ExtraBold] */
@Stable
val W800 = FontWeight(800)
/** [Black] */
@Stable
val W900 = FontWeight(900)
/** Alias for [W100] */
@Stable
val Thin = W100
/** Alias for [W200] */
@Stable
val ExtraLight = W200
/** Alias for [W300] */
@Stable
val Light = W300
/** The default font weight - alias for [W400] */
@Stable
val Normal = W400
/** Alias for [W500] */
@Stable
val Medium = W500
/** Alias for [W600] */
@Stable
val SemiBold = W600
/**
* A commonly used font weight that is heavier than normal - alias for [W700]
*/
@Stable
val Bold = W700
/** Alias for [W800] */
@Stable
val ExtraBold = W800
/** Alias for [W900] */
@Stable
val Black = W900
/** A list of all the font weights. */
internal val values: List<FontWeight> = listOf(
W100,
W200,
W300,
W400,
W500,
W600,
W700,
W800,
W900
)
复制代码
看一下他们的显示效果:
@Composable
fun MyText() {
Column {
Text(
text = stringResource(R.string.my_text),
fontWeight = FontWeight.Thin,
)
Text(
text = stringResource(R.string.my_text),
fontWeight = FontWeight.ExtraLight
)
Text(
text = stringResource(R.string.my_text),
fontWeight = FontWeight.Light
)
Text(
text = stringResource(R.string.my_text),
fontWeight = FontWeight.Normal
)
Text(
text = stringResource(R.string.my_text),
fontWeight = FontWeight.Medium
)
Text(
text = stringResource(R.string.my_text),
fontWeight = FontWeight.SemiBold
)
Text(
text = stringResource(R.string.my_text),
fontWeight = FontWeight.Bold
)
Text(
text = stringResource(R.string.my_text),
fontWeight = FontWeight.ExtraBold
)
Text(
text = stringResource(R.string.my_text),
fontWeight = FontWeight.Black
)
}
}
复制代码

fontFamily 更改字体
fontFamily可以更改字体,FontFamily为我们默认内置了5种字体,Default、SansSerif、Serif、Monospace、Cursive。
@Composable
fun MyText() {
Column {
Text(
text = stringResource(R.string.my_text),
fontFamily = FontFamily.Default,
)
Text(
text = stringResource(R.string.my_text),
fontFamily = FontFamily.SansSerif
)
Text(
text = stringResource(R.string.my_text),
fontFamily = FontFamily.Serif
)
Text(
text = stringResource(R.string.my_text),
fontFamily = FontFamily.Monospace
)
Text(
text = stringResource(R.string.my_text),
fontFamily = FontFamily.Cursive
)
}
}
复制代码

letterSpacing 更改文字间距
letterSpacing更改文字间距,更确切的说是更改字符间距,因为如果是英文的话,不会按单词来设置间距,而是按字母。
@Composable
fun MyText() {
Text(
text = stringResource(R.string.my_text),
letterSpacing = 10.sp,
)
}
复制代码

textDecoration 文字装饰器
textDecoration可以给文字装饰下划线和中划线。默认提供了三个值:
None: 无装饰效果LineThrough: 添加中划线Underline: 添加下划线
@Composable
fun MyText() {
Column {
Text(
text = stringResource(R.string.my_text),
textDecoration = TextDecoration.None,
)
Text(
text = stringResource(R.string.my_text),
textDecoration = TextDecoration.LineThrough,
)
Text(
text = stringResource(R.string.my_text),
textDecoration = TextDecoration.Underline,
)
}
}
复制代码

除此之外,TextDecoration还提供了一个combine函数,可以将下划线和中划线组合:
@Composable
fun MyText() {
val combineDecoration = listOf(TextDecoration.Underline, TextDecoration.LineThrough)
Text(
text = stringResource(R.string.my_text),
textDecoration = TextDecoration.combine(combineDecoration)
)
}
复制代码

textAlign 设置文字对齐方向
textAlign 可以设置Text组件内容的对齐方式,有TextAlign.Start、TextAlign. End 、TextAlign. Center 、TextAlign. Justify 等值。默认情况下,Text 会根据其内容值选择自然的文字对齐方式:
- 对于从左到右书写的文字,如拉丁语、西里尔文或朝鲜文,向 Text 容器的左边缘对齐
- 对于从右到左书写的文字,如阿拉伯语或希伯来语,向 Text 容器的右边缘对齐
如果您想手动设置 Text 组件的文字对齐方式,最好分别使用
TextAlign.Start和TextAlign.End(而不要使用TextAlign.Left和TextAlign.Right),这样系统就可以根据具体语言的首选文字方向,将您的设置解析为向 Text 的右边缘对齐。例如,TextAlign.End对于法语文字将向右侧对齐,而对于阿拉伯语文字则将向左侧对齐,但无论对于哪种文字,TextAlign.Right都将向右侧对齐。
@Composable
fun MyText() {
Column {
Text(
text = stringResource(R.string.my_text),
modifier = Modifier
.size(300.dp, 50.dp)
.background(Color.Gray),
textAlign = TextAlign.Start
)
Text(
text = stringResource(R.string.my_text),
modifier = Modifier
.size(300.dp, 50.dp)
.background(Color.Gray),
textAlign = TextAlign.End
)
Text(
text = stringResource(R.string.my_text),
modifier = Modifier
.size(300.dp, 50.dp)
.background(Color.Gray),
textAlign = TextAlign.Center
)
Text(
text = stringResource(R.string.my_text),
modifier = Modifier
.size(300.dp, 50.dp)
.background(Color.Gray),
textAlign = TextAlign.Justify
)
}
}
复制代码

注意:要对齐方式生效,需要给Text设置大小,因为Text组件默认的大小是包裹内容的,上面的代码我们用
modifier属性设置了Text组件的大小。
lineHeight 设置行高
lineHeight设置行高,值为一个具体数值,单位为sp
@Composable
fun MyText() {
Column {
Text(
text = "未设置lineHeight".repeat(10),
)
Text(
text = "已经设置lineHeight".repeat(10),
lineHeight = 30.sp
)
}
}
复制代码

overflow 设置文本溢出效果
overflow设置当文本超出控件时的显示样式,有两个取值:
TextOverflow.Clip: 超出部分直接截断TextOverflow.Ellipsis: 使用省略号表示文本已溢出
overflow一般配合maxLines使用
@Composable
fun MyText() {
Column {
Text(
text = stringResource(R.string.my_text).repeat(10),
overflow = TextOverflow.Clip,
maxLines = 2
)
Spacer(modifier = Modifier.height(20.dp))
Text(
text = stringResource(R.string.my_text).repeat(10),
overflow = TextOverflow.Ellipsis,
maxLines = 2
)
}
}
复制代码

maxLines 设置最多显示行数
maxLines配置最多显示几行,该属性一般需要配置overflow,表明超出部分该如何显示,默认直接截断(Clip效果)。
@Composable
fun MyText() {
Column {
Text(
text = stringResource(R.string.my_text).repeat(10),
)
Spacer(modifier = Modifier.height(20.dp))
Text(
text = stringResource(R.string.my_text).repeat(10),
maxLines = 2,
)
}
}
复制代码

softWrap 是否自动换行
默认为true,即会自动换行,如果设置为false,将不会自动换行。一般使用场景为:文本单行显示,超出默认截断或显示省略号,即配合overflow使用:
@Composable
fun MyText() {
Text(
text = stringResource(R.string.my_text).repeat(10),
softWrap = false,
overflow = TextOverflow.Ellipsis
)
}
复制代码

onTextLayout 计算新的布局时回调函数
计算新的Text布局时回调函数,回调中可以获取一些结果,比如控件的size等。
@Composable
fun MyText() {
Text(
text = stringResource(R.string.my_text),
onTextLayout = {
Log.e("xige","text width: ${it.size.width}, text height: ${it.size.height}")
}
)
}
复制代码
运行结果:

style 可以配置text 的颜色、字号、行高等等
颜色、字号、行高等那些属性效果,都可以用style来统一配置,除此之外,还有一些属性,如:shadow可以设置倒影效果,所有可配置属性如下:

@Composable
fun MyText() {
Text(
text = stringResource(R.string.my_text),
style = TextStyle(
color = Color.Blue,
fontSize = 20.sp,
lineHeight = 20.sp,
fontWeight = FontWeight.Bold,
fontFamily = FontFamily.Monospace,
fontStyle = FontStyle.Normal,
shadow = Shadow(
color = Color.Red,
offset = Offset(10.0f,10.0f),
blurRadius = 10.0f
)
)
)
}
复制代码

modifier 修改器
最后来说说modifier,这个属性很重要,也不是Text组件所独有,基本所有组件都有这个属性,它可以修改组件外观比如:pading、宽高、背景、形状等等。但绝不仅于此,还要很多强大的功能,可以定义动画,自定义点击事件等等。由于篇幅有限,后面会单独写一篇Modifier的文章介绍。
@Composable
fun MyText() {
Text(
text = stringResource(R.string.my_text),
modifier = Modifier
.border(
width = 3.dp,
color = Color.Red,
shape = RoundedCornerShape(
topStart = 30.dp,
topEnd = 30.dp,
bottomStart = 20.dp,
bottomEnd = 30.dp
)
)
.size(400.dp, 50.dp)
.padding(10.dp)
)
}
复制代码

可选择的Text
默认情况下,Text组件内容不可选择,这意味着,在默认情况下用户无法从你的应用中选择和复制文字。要启用文字选择,需要使用 SelectionContainer 容器包装Text元素。
SelectionContainer 组件
从字面意思看:可选择的容器,确实,只要用SelectionContainer包装Text,则可选择Text组件显示的文本。
@Composable
fun MyText() {
SelectionContainer {
Text(stringResource(R.string.my_text))
}
}
复制代码

DisableSelection组件
JetpackCompose 其实支持更精细化的选择,假设你想在一段可选择的文本中,嵌入一个不可被选择的文本。要实现这样一个功能非常简单,使用DisableSelection组件即可。
被 DisableSelection 包裹的Text组件,内容不可被选择:
@Composable
fun MyText() {
SelectionContainer {
Column {
Text("我是可被选中文本1")
Text("我是可被选中文本2")
Text("我是可被选中文本3")
DisableSelection {
Text("我是不可被选中文本1")
Text("我是不可被选中文本2")
}
Text("我是可被选中文本4")
Text("我是可被选中文本4")
}
}
}
复制代码

可点击的Text
添加clickable 修饰符
Text 组件本身是没有点击事件的,如果要让Text可点击,可以给它添加clickable 修饰符,也就是我们前面说的Modifier,如下,我们添加一个可点击Text,点击一次增加1:
@Composable
fun MyText() {
val txt = remember { mutableStateOf(0)}
Column(
modifier = Modifier
.fillMaxSize()
.background(Color(0xFFE5E4E2))
.padding(16.dp),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = "${txt.value}",
fontFamily = FontFamily.Serif,
fontSize = 75.sp,
color = Color(0xFFE63E62),
modifier = Modifier
.clip(RoundedCornerShape(12.dp))
.background(Color(0xFFC9C0BB))
.clickable(
enabled = true,
role = Role.Button
){
txt.value += 1
}
.padding(25.dp)
)
}
}
复制代码

获取点击文字的位置
clickable可以给Text添加点击事件,但是它却不能监听点击的是Text的那个位置,比如显示的是Jetpack Compose,by 依然范特稀西,我想确定点击的是哪个字符,该咋整呢?Compose 为我们提供了支持,使用ClickableText即可:
@Composable
fun MyText() {
ClickableText(
text = AnnotatedString(stringResource(R.string.my_text))
) { index ->
Log.d("ClickableText", "第 $index 个字符被点击")
}
}
复制代码

注意ClickableText接受的是一个 AnnotatedString类型,最后一个参数就是onClick,这里运用了kotlin的lamuda表达式特性,最后一个lamuda表达式可以提到括号外,跟下面是等价的。
@Composable
fun MyText() {
ClickableText(
text = AnnotatedString(stringResource(R.string.my_text)),
onClick = { index ->
Log.d("ClickableText", "第 $index 个字符被点击")
}
)
}
复制代码
Text样式嵌套
Text 支持为其中的字符、字符串单独设置不同的样式,因为Text组件的text属性是AnnotatedString类型,AnnotatedString是一个数据类:
class AnnotatedString internal constructor(
val text: String, // 字符串
val spanStyles: List<Range<SpanStyle>> = emptyList(), // 设置字符样式的List
val paragraphStyles: List<Range<ParagraphStyle>> = emptyList(), //设置段落样式的List
internal val annotations: List<Range<out Any>> = emptyList() // 注解list
)
复制代码
我们可以通过提供的buildAnnotatedString来构建AnnotatedString 类,其中,可以通过append函数拼接字符串,可以通过withStyle拼接字符串并设置样式:
@Composable
fun MyText() {
Text(
buildAnnotatedString {
withStyle(
style = SpanStyle(
color = Color.Blue,
fontWeight = FontWeight.Bold
)
) {
append("Jetpack ")
}
append("Compose ")
withStyle(
style = SpanStyle(
color = Color.Red,
fontWeight = FontWeight.Bold,
fontSize = 30.sp
)
) {
append("by ")
}
append("依然范特稀西")
}
)
}
复制代码

这里我们使用了SpanStyle 来设置单个样式,还有一个ParagraphStyle ,按字面理解,就是设置段落样式,也就是包裹在ParagraphStyle里面的段落都会应用它设置的样式,看一下示例:
@Composable
fun MyText() {
Text(
buildAnnotatedString {
withStyle(
// 设置段落样式
style = ParagraphStyle(
lineHeight = 60.sp,
textAlign = TextAlign.Center
)
) {
withStyle(
style = SpanStyle(
color = Color.Blue,
fontWeight = FontWeight.Bold
)
) {
append("Jetpack Compose\n")
}
withStyle(
style = SpanStyle(
color = Color.Red,
fontWeight = FontWeight.Bold,
fontSize = 30.sp
)
) {
append("by\n")
}
withStyle(
style = SpanStyle(
color = Color.Green,
fontWeight = FontWeight.Bold,
)
) {
append("依然范特稀西\n")
}
withStyle(
style = SpanStyle(
fontWeight = FontWeight.Bold,
fontSize = 30.sp,
color = Color.Red
)
) {
append("@公众号:技术最TOP
")
}
}
},
modifier = Modifier.width(400.dp)
)
}
复制代码

上面,设置的lineHeight和textAlin样式应用到了所包裹的所有段落上。
实用案列-点击超链接
我们的APP中,登录/注册页面都会有隐私政策协议,需要用户同意后才能继续,像下面这样:

点击蓝色字即可跳转到隐私政策/用户协议界面,一般是一个H5页面。我们来用Jetpack Compose实现这么一个功能。
思路: ClickText + 样式嵌套 + 点击注解 可实现
前两个已经介绍过了,现在简单说说点击注解:在使用buildAnnotatedString 时,可以使用pushStringAnnotation 携带一个tag数据, 在点击对应tag时, onClick 中,可以使用getStringAnnotations 获取携带的数据。
@Composable
fun MyText() {
val annotatedText = buildAnnotatedString {
append("登录即表明同意")
pushStringAnnotation(
tag = "tag1",
annotation = "隐私条款1:https://www.xxx1.com"
)
withStyle(
style = SpanStyle(
color = Color.Blue,
fontWeight = FontWeight.Bold,
textDecoration = TextDecoration.Underline
)
) {
append("中国移动认证服务条款")
}
pop()
append("以及")
pushStringAnnotation(
tag = "tag2",
annotation = "隐私条款2:https://www.xxx2.com"
)
withStyle(
style = SpanStyle(
color = Color.Blue,
fontWeight = FontWeight.Bold,
textDecoration = TextDecoration.Underline
)
) {
append("用户协议")
}
pop()
append("和")
pushStringAnnotation(
tag = "tag1",
annotation = "隐私条款3:https://www.xxx3.com"
)
withStyle(
style = SpanStyle(
color = Color.Blue,
fontWeight = FontWeight.Bold,
textDecoration = TextDecoration.Underline
)
) {
append("隐私政策")
}
pop()
}
val tags = listOf("tag1", "tag2", "tag3")
ClickableText(
text = annotatedText,
onClick = { offset ->
tags.forEach { tag ->
annotatedText.getStringAnnotations(
tag = tag, start = offset,
end = offset
)
.firstOrNull()?.let { annotation ->
Log.d("xige", annotation.item)
}
}
}
)
}
复制代码
![图片[1]-Jetpack Compose系列-Text组件花式使用!-一一网](https://www.proyy.com/skycj/data/images/2021-04-26/ce67471ff48e9a7ef29aa2a4b3fa4283.jpg)
点击蓝色字,打印如下:

在真实场景中,只需要将打印的地方,换跳转Webview展示即可。
总结
以上就是Jetpack Compose中,Text组件使用的介绍,以及文字显示的各种使用探索。欢迎大家留言交流。
我是西哥,欢迎大家关注我的公众号:「技术最TOP」,干货内容第一时间送阅!
















![[02/27][官改] Simplicity@MIX2 ROM更新-一一网](https://www.proyy.com/wp-content/uploads/2020/02/3168457341.jpg)


![[桜井宁宁]COS和泉纱雾超可爱写真福利集-一一网](https://www.proyy.com/skycj/data/images/2020-12-13/4d3cf227a85d7e79f5d6b4efb6bde3e8.jpg)

![[桜井宁宁] 爆乳奶牛少女cos写真-一一网](https://www.proyy.com/skycj/data/images/2020-12-13/d40483e126fcf567894e89c65eaca655.jpg)