自学Jetpack Compose 系列Compose控件Text与TextStyle的学习与使用

Posted bug樱樱

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了自学Jetpack Compose 系列Compose控件Text与TextStyle的学习与使用相关的知识,希望对你有一定的参考价值。

android 的TextView在Compose中是使用的Text控件

文本显示

说到文本显示,我们打开之前创建的Compose项目,看到一下代码:

@Composable
fun Greeting(name: String) 
    Text(text = "Hello $name!")
 

看到的就是使用Text()进行文字显示。但是在Google官方建议我们使用字符串资源,方便我们以后进行国际化适配。那么我们要如何使用字符串资源呢?

@Composable
fun TestText()
    Text(text = stringResource(id = R.string.app_name))
 

在Compose中使用stringResource就可以直接读取字符串资源了。接下来我们就需要去预览效果了,之前我们有提到Preview注解,下面我们就使用它查看预览了:

@Preview(showBackground = true, heightDp = 100, widthDp = 200)
@Composable
fun TestTextPreview() 
    TestText()
 

我看一下效果:

如果我们不需要进行其他设置的话,直接像上面那样使用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// 文本的样式配置,例如颜色字体行高等等
) 

我们看到只有text是必传的,其他参数都有默认值。

设置文字样式

1. 文字颜色

@Composable
fun TestText() 
    Text(
        text = stringResource(id = R.string.app_name),
        color = Color.Blue,
    )
 

代码很简单, 我们只是把文字字体颜色设置为蓝色, 下面是预览效果:

2.字号大小

@Composable
fun TestText() 
    Text(
        text = stringResource(id = R.string.app_name),
        color = Color.Blue,
        fontSize = 25.sp
    )
 

字号大小参数fontSize的类型是TextUnit。我们设置字号大小的时候使用了Int.sp的形式,其实这是Compose为我们写的扩展函数。Int、Float、Double都可以这样使用

@Stable
val Float.sp: TextUnit get() = pack(UNIT_TYPE_SP, this)

@Stable
val Double.sp: TextUnit get() = pack(UNIT_TYPE_SP, this.toFloat())

@Stable
val Int.sp: TextUnit get() = pack(UNIT_TYPE_SP, this.toFloat()) 

3. 设置斜体

@Composable
fun TestText() 
    Text(
        text = stringResource(id = R.string.app_name),
        color = Color.Blue,
        fontSize = 25.sp,
        fontStyle = FontStyle.Italic,
    )
 

我们看一下FontStyle的源码:

inline class FontStyle(val value: Int) 

    override fun toString(): String 
        return when (this) 
            Normal -> "Normal"
            Italic -> "Italic"
            else -> "Invalid"
        
    

    companion object 
        /** Use the upright glyphs */
        val Normal = FontStyle(0)

        /** Use glyphs designed for slanting */
        val Italic = FontStyle(1)

        /** Returns a list of possible values of [FontStyle]. */
        fun values(): List<FontStyle> = listOf(Normal, Italic)
    
 

代码很简单,就是一个枚举类,只用两个参数:NormalItalic

4. 设置字体粗细

设置字体粗细用的是FontWeight,我们先看一下FontWeight的源码

@Immutable
class FontWeight(val weight: Int) : Comparable<FontWeight> 

    companion object 
        @Stable
        val W100 = FontWeight(100)
        @Stable
        val W200 = FontWeight(200)
        @Stable
        val W300 = FontWeight(300)
        @Stable
        val W400 = FontWeight(400)
        @Stable
        val W500 = FontWeight(500)
        @Stable
        val W600 = FontWeight(600)
        @Stable
        val W700 = FontWeight(700)
        @Stable
        val W800 = FontWeight(800)
        @Stable
        val W900 = FontWeight(900)
        @Stable
        val Thin = W100
        @Stable
        val ExtraLight = W200
        @Stable
        val Light = W300
        @Stable
        val Normal = W400
        @Stable
        val Medium = W500
        @Stable
        val SemiBold = W600
        @Stable
        val Bold = W700
        @Stable
        val ExtraBold = W800
        @Stable
        val Black = W900
        internal val values: List<FontWeight> = listOf(
            W100,
            W200,
            W300,
            W400,
            W500,
            W600,
            W700,
            W800,
            W900
        )
    

    init 
        require(weight in 1..1000) 
            "Font weight can be in range [1, 1000]. Current value: $weight"
        
    
 

代码内置了从W100 到 W900的粗细效果,根据实际情况使用哪种加粗。FontWeight有一个有参构造函数,方便我们自定义粗细程度。里面内置好的也有我们比较熟悉的BoldNormal

@Composable
fun TestText() 
    Text(
        text = stringResource(id = R.string.app_name),
        color = Color.Blue,
        fontSize = 25.sp,
        fontStyle = FontStyle.Italic,
        fontWeight = FontWeight.Bold
    )
 

上面说了我们也可以自定义粗细的值:

@Composable
fun TestText() 
    Text(
        text = stringResource(id = R.string.app_name),
        color = Color.Blue,
        fontSize = 25.sp,
        fontStyle = FontStyle.Italic,
        fontWeight = FontWeight(10)
    )
 

上面是我们把粗细值改成10的效果

5.设置字体

修改字体使用的是fontFamily参数,用于设置使用的字体。按照惯例,先看源码:

 sealed class FontFamily(val canLoadSynchronously: Boolean) 
    companion object 
        // 默认字体
        val Default: SystemFontFamily = DefaultFontFamily()
        // 具有低对比度和平淡笔画结尾的字体
        val SansSerif = GenericFontFamily("sans-serif")
        // Scripts 的正式文本
        val Serif = GenericFontFamily("serif")
        // 字形具有相同固定宽度的字体
        val Monospace = GenericFontFamily("monospace")
        // 草书、手写字体
        val Cursive = GenericFontFamily("cursive")
    
 

系统默认提供了5种字体,我们把这5种字体都使用一下看看效果:

@Composable
fun TestText() 
    Column 
        Text(text = stringResource(id = R.string.app_name), fontFamily = FontFamily.Default)
        Text(text = stringResource(id = R.string.app_name), fontFamily = FontFamily.SansSerif)
        Text(text = stringResource(id = R.string.app_name), fontFamily = FontFamily.Serif)
        Text(text = stringResource(id = R.string.app_name), fontFamily = FontFamily.Monospace)
        Text(text = stringResource(id = R.string.app_name), fontFamily = FontFamily.Cursive)
    
 

除了系统给的字体,我们还可以添加自定义字体和字型,首先我们要讲字体文件放到res/font文件夹中。

放置完字体后,需要根据字体文件来定义fontFamily:

val customFamily = FontFamily(
    Font(R.font.family_normal, FontWeight.Normal),
    Font(R.font.family_bold, FontWeight.Bold),
) 

然后,就可以将此fontFamily传递给Text来使用了:

Text(text = stringResource(id = R.string.app_name), fontFamily = customFamily, fontWeight = FontWeight.Bold) 

6. 设置字符间距

设置字符间距使用的是Text的letterSpacing参数。参数类型和设置字号大小是一样的:

@Composable
fun TestText() 
    Text(
        text = stringResource(id = R.string.app_name),
        letterSpacing = 5.sp
    )
 

不是只有英文可是设置字符间距,中文也可以

7. 设置文字装饰

设置文字装饰用的是textDecoration参数,textDecoration我先去看一下这个源码:

@Immutable
class TextDecoration internal constructor(val mask: Int) 
    companion object 
        @Stable
        val None: TextDecoration = TextDecoration(0x0)
        // 下划线
        @Stable
        val Underline: TextDecoration = TextDecoration(0x1)
        // 删除线
        @Stable
        val LineThrough: TextDecoration = TextDecoration(0x2)
    
 

我们看看文字装饰怎么用?

@Composable
fun TestText() 
    Column 
        Text(
            text = "小码农沐枫",
            textDecoration = TextDecoration.None
        )
        Text(
            text = "小码农沐枫",
            textDecoration = TextDecoration.Underline
        )
        Text(
            text = "小码农沐枫",
            textDecoration = TextDecoration.LineThrough
        )
    
 

8. 文字对齐方式

设置文字的对齐方式使用的是textAlign参数。参数对应的类型是TextAlign, 先看一下源码:

inline class TextAlign internal constructor(internal val value: Int) 
    companion object 
        val Left = TextAlign(1)
        val Right = TextAlign(2)
        val Center = TextAlign(3)
        val Justify = TextAlign(4)
        val Start = TextAlign(5)
        val End = TextAlign(6)
    
 

我们以居中对齐为例:

Text(
    text = "小码农沐枫",
    textAlign = TextAlign.Center,
    modifier = Modifier.width(200.dp)
) 

9. 设置行高

设置行高使用的参数是lineHeight,参数类型也是TextUnit。

Text(
    text = "小码农沐枫小码农沐枫小码农沐枫",
    lineHeight = 35.sp
) 

10. 文字溢出

处理文字溢出的情况,使用的参数为overflow,参数类型为TextOverflow。直接看源码:

inline class TextOverflow internal constructor(internal val value: Int) 

    override fun toString(): String 
        return when (this) 
            Clip -> "Clip"
            Ellipsis -> "Ellipsis"
            Visible -> "Visible"
            else -> "Invalid"
        
    

    companion object 
       
        val Clip = TextOverflow(1)

        val Ellipsis = TextOverflow(2)

        val Visible = TextOverflow(3)
    
 

Text(
    text = "小码农沐枫小码农沐枫小码农沐枫",
    overflow = TextOverflow.Ellipsis,
    maxLines = 2
) 

11. 文字中富文本显示

这种在登录或注册页面的底部同意隐私权限的位置经常用到。

如果要实现这种效果,我们就需要借助AnnotatedString类来实现。先看源码:

@Immutable
class AnnotatedString internal constructor(
    val text: String,
    val spanStyles: List<Range<SpanStyle>> = emptyList(),
    val paragraphStyles: List<Range<ParagraphStyle>> = emptyList(),
    internal val annotations: List<Range<out Any>> = emptyList()
) 

  • text: 用于表示文字内容
  • spanStyles:用于在文本的特定部分指定SpanStyle
  • paragraphStyles:用于指定文字对齐、文字方向、行高和文字缩进样式。

TextStyle用于Text可组合项,而SpanStyle和ParagraphStyle用于AnnotatedString。

SpanStyle和ParagraphStyle之间的区别在于:ParagraphStyle可应用于整个段落,而SpanStyle可以在字符级别应用。一旦用ParagraphStyle标记了一部分文字,该部分就会与其余部分隔开,就像开头和末尾有换行符一样。

下面看看具体使用:

@Composable
fun TestText() 
    Text(buildAnnotatedString 
        withStyle(style = SpanStyle(color = Color.Gray, fontSize = 14.sp))
            append("阅读并同意")
        
        withStyle(style = SpanStyle(color = Color.Green, fontSize = 14.sp))
            append("《用户协议》")
        
        withStyle(style = SpanStyle(color = Color.Gray, fontSize = 14.sp))
            append("和")
        
        withStyle(style = SpanStyle(color = Color.Green, fontSize = 14.sp))
            append("《隐私协议》")
        
        withStyle(style = SpanStyle(color = Color.Gray, fontSize = 14.sp))
            append("。")
        
    )
 

设置文字选择

在Compose中支持Text的精细互动,文字选择现在更加灵活,并且可以跨各种可组合项布局进行选择。
在默认情况下,可组合项不可选择,也就是说默认情况下用户无法选择和复制文字。要启用文字选择,需要使用SelectionContainer可组合项封装文字元素:

@Composable
fun TestText() 
    SelectionContainer(modifier = Modifier.fillMaxSize()) 
        Text(text = "我是可以选择的, 我是可以选择的, 我是可以选择的", fontSize = 35.sp)
    
 

这种需要长按的,我们预览就看不到效果了,我们只能去运行看效果:

比如说在一段文字中,我们有一部分是不想让用户去选中的,这个应该怎么做呢?在这里我们就可以借用DisableSelection可组合项来封装不可选择的部分:

@Composable
fun TestText() 
    SelectionContainer(modifier = Modifier.fillMaxSize()) 
        Column 
            Text(text = "鹅鹅鹅")
            Text(text = "曲项向天歌")
            DisableSelection 
                Text(text = "白毛浮绿水")
            
            Text(text = "红掌拨清波")
        
    
 


我们可以看到白毛浮绿水这句话就是不能选中的状态了

文末

我总结了一些Android核心知识点,以及一些最新的大厂面试题、知识脑图和视频资料解析。

需要的小伙伴直接点击文末小卡片免费领取哦,以后的路也希望我们能一起走下去。(谢谢大家一直以来的支持,需要的自己领取)

Android学习PDF+架构视频+面试文档+源码笔记

部分资料一览:

  • 330页PDF Android学习核心笔记(内含8大板块)

  • Android学习的系统对应视频

  • Android进阶的系统对应学习资料

  • Android BAT大厂面试题(有解析)

领取地址:

以上是关于自学Jetpack Compose 系列Compose控件Text与TextStyle的学习与使用的主要内容,如果未能解决你的问题,请参考以下文章

Jetpack Compose 深入探索系列一:Composable 函数

Jetpack Compose - Slider

Jetpack Compose Runtime 与 NodeTree 管理

Android JetPack Compose组件中Scaffold的应用

《Jetpack Compose系列学习》-2 Compose编程思想

Jetpack Compose 深入探索系列二:Compose 编译器