对于用户界面而言,文本是最基础而又核心的内容,在传统的 Android Native 开发中,须要用一个TextView来显示一个文本。在Jetpack Compose 中,提供了Text可组合函数(即组件,后面的文章都会称其为“组件”),可更轻松的显示文本。在本文中,将带你们一块儿探索Text组件的各类用法。app
在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 ) }
知道了,每一个属性的意思,咱们接下来一块儿看看,配置各属性后的效果展现。动画
对于用户界面而言,文本是最基础而又核心的内容,在传统的 Android Native 开发中,须要用一个TextView来显示一个文本。在Jetpack Compose 中,提供了Text可组合函数(即组件,后面的文章都会称其为“组件”),可更轻松的显示文本。在本文中,将带你们一块儿探索Text组件的各类用法。ui
在Jetpack Compose 中,组件是一个特殊的Kotlin 函数,所以Text其实也是一个函数,而它提供了不少参数来配置文本的显示外观。这些参数就是组件的属性。看一下Text组件有哪些属性:spa
@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
,其余都有默认值,也就是使用的时候能够不传,可是若是传多个参数时,必定要加参数名。好比,设置大小:code
@Composable fun MyText(){ Text("Jetpack Compose,by 依然范特稀西", fontSize = 20.sp ) }
第一个参数能够加参数名,也能够不加,但我我的仍是推荐加上,由于他是一个组件,参数是它的属性,这样代码比较直观。像下面这样就比较好一点:orm
@Composable fun MyText(){ Text( text = "Jetpack Compose,by 依然范特稀西", fontSize = 20.sp ) }
知道了,每一个属性的意思,咱们接下来一块儿看看,配置各属性后的效果展现。xml
显示文字的最简单的方法是使用以 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)) }
@Composable fun MyText() { Text( text = stringResource(R.string.my_text), color = Color.Blue ) }
@Composable fun MyText() { Text( text = stringResource(R.string.my_text), color = Color.Blue, fontSize = 30.sp, ) }
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
能够取 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为咱们默认内置了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
更改文字间距,更确切的说是更改字符间距,由于若是是英文的话,不会按单词来设置间距,而是按字母。
@Composable fun MyText() { Text( text = stringResource(R.string.my_text), letterSpacing = 10.sp, ) }
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
能够设置Text组件内容的对齐方式,有TextAlign.Start
、TextAlign. End
、TextAlign. Center
、TextAlign. Justify
等值。默认状况下,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
设置行高,值为一个具体数值,单位为sp
@Composable fun MyText() { Column { Text( text = "未设置lineHeight".repeat(10), ) Text( text = "已经设置lineHeight".repeat(10), lineHeight = 30.sp ) } }
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
配置最多显示几行,该属性通常须要配置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, ) } }
默认为true
,即会自动换行,若是设置为false
,将不会自动换行。通常使用场景为:文本单行显示,超出默认截断或显示省略号
,即配合overflow
使用:
@Composable fun MyText() { Text( text = stringResource(R.string.my_text).repeat(10), softWrap = false, overflow = TextOverflow.Ellipsis ) }
计算新的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
来统一配置,除此以外,还有一些属性,如: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,这个属性很重要,也不是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组件内容不可选择
,这意味着,在默认状况下用户没法从你的应用中选择和复制
文字。要启用文字选择,须要使用 SelectionContainer
容器包装Text元素。
从字面意思看:可选择的容器,确实,只要用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 组件自己是没有点击事件的,若是要让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属性是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) } } } ) }
点击蓝色字,打印以下:
在真实场景中,只须要将打印的地方,换跳转Webview展现便可。
以上就是Jetpack Compose中,Text组件使用的介绍,以及文字显示的各类使用探索。欢迎你们留言交流。
我是西哥,欢迎你们关注个人公众号:「技术最TOP」,干货内容第一时间送阅!