Android Compose Text 文本控件属性详解

TextCompose 提供的文本显示控件,也是基于 BasicText 而来,下面引用官方文档对 Text 的描述,帮助大家更好理解。

Compose 提供了基础的 BasicText 和 BasicTextField,它们是用于显示文字以及处理用户输入的主要函数。Compose 还提供了更高级的 Text 和 TextField,它们是遵循 Material Design 准则的可组合项。建议在 Android 平台上使用这些构建块,因为它们的外观和样式非常适合 Android 用户,而且还包括可用以简化用户自定义设置的其他选项,无需编写大量代码。

属性介绍

由于 Text 是基于 BasicText 基础上增加了新特性和 Material Design 样式设计,本篇文章着重介绍 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:显示的内容信息

  • modifier:常用属性设定、宽高、背景等。

  • color:字体颜色

  • fontSize:字体大小

  • fontStyle:字体斜体

  • fontWeight:字体权重,设置 boldmedium 居多。(某些需求设计会要求设置权重,看效果是字体的粗细改变)

  • fontFamily:字体样式,提供了草书、字体等宽等样式,也可引用字体文件来改变字体样式,将字体文件放在 res/font 文件夹下,如果没有在 res 下创建个。

  • letterSpacing:字体间距,不要被 TextUnit 类型误导,直接设置间距值比如 10.sp

  • textDecoration:字体中划线、下划线

    • TextDecoration.None:默认不设置

    • TextDecoration.Underline:字体下划线

    • TextDecoration.LineThrough:字体中划线

  • textAlign:字体对齐方向

    • TextAlign.Left:左对齐

    • TextAlign.Right:右对齐

    • TextAlign.Center:水平居中

    • TextAlign.Start:字体语言开始方向对齐,通常我们使用的文本语言是中文、英文等,这类语言开始的方向是从左向右,而某些特殊语言,比如阿拉伯语言绘制方向是从右向左,方向是反的。
      建议设置文字 开始 \ 结尾 对齐或 \ 对齐时,使用 .Start \ .End,如果使用 .Left \ .Right 文字会永远 \ 对齐,不会根据语言来切换方向。

    • TextAlign.End:字体语言结束方向对齐,和 .Start 属性同理,语言不同显示的方向不同,通常情况下是文字居右。

    • TextAlign.Justify:文字多行对齐,强行对齐会增加文字间距。

  • lineHeight:行间距,不要被 TextUnit 类型误导,直接设置间距值 20.sp

  • maxLines:内容可显示最大行数

  • softWrap:内容是否自动换行,默认为 true

  • overflow:字体超出 Text 最大宽高范围,结尾显示处理,通常设置显示 ...,配合 maxLines \ softWrap 使用。

    • TextOverflow.Clip:默认属性,超出 Text 范围的内容截取掉不显示。

    • TextOverflow.Ellipsis:超出 Text 范围的内容用 ... 代替

    • TextOverflow.Visible:这个参数很奇怪,Api 解释是显示全部内容,即使限制了宽高范围,内容也会超出范围边界全部显示出来。但是在 Compose 1.0.5 源码中并没有任何控件调用此属性,测试后没有任何效果,可能需要其他参数配合,目前没有查询到相关信息,知道的小伙伴欢迎留言,后续 Api 有更新我会同步过来。

  • onTextLayout:当 Text 内容变化时回调

    • layoutInput:返回 Text 内容、stylemaxLinessoftWrap 等信息。

    • multiParagraph:经过计算返回多段对象

    • size:返回 Text 宽高大小

    • didOverflowWidth / didOverflowHeight:文本内容是否超出 Text 宽高,返回 true

    • hasVisualOverflow:文本内容是否超出 Text 水平方向或垂直方向,返回 true

    • lineCount:返回 Text 的文本行数

    • firstBaseline:返回 Text 顶部到第一行内容基线的距离

    • lastBaseline:返回 Text 顶部到最后一行内容基线的距离

  • style:这里使用的是 TextStyle,是对 Text 进行样式设定,其中部分属性和上面列举的功能重复,所以下面介绍其余属性。

    • fontSynthesis:在设置自定义字体 fontFamily 时,当使用的 fontFamily 不包含粗体或斜体字体,系统是否应该伪造粗体或倾斜的字形。fontSynthesis 提供了四种解决方法,比如给加粗斜体。

    • fontFeatureSettings:设置 CSS 中高级排版功能,设置属性和developer.mozilla.org/zh-CN/docs/… 内属性一样,可以设置 smcptnum

    • baselineShift:设置文本内容基于基线向上或向下偏移,偏移量结果为输入的参数 *(baseline - ascent),也提供了默认的三种偏移量参数,分别为基于基线向上偏移 0.5f、向下偏移 0.5f、不偏移(默认)三种固定参数。

    • textGeometricTransform:对 Text 内容进行几何变换,挺有意思的,根据参数设定水平方向文字内容缩放比例、水平方向剪裁倾斜角度。

    • localeList:设定 LocaleList 对象列表

    • backgroundText 背景颜色

    • shadowText 内容阴影,类似于两个同样文本重叠在一起,可以根据参数设置偏移量,设置完观感上很乱,目前没想到实际用处。

    • textIndent:设置 Text 段落的缩进量,有两个参数 firstLinerestLine 分别是设置第一行缩进量和除了第一行其余行的缩进量。

样式详解

显示 strings.xml 资源内容

Text 显示 strings.xml 资源文件内容使用 stringResource(id = R.string.app_name)

@Composable
fun TextTestView() {
    Column(Modifier.fillMaxSize()) {
        Text(text = stringResource(id = R.string.app_name))
    }
}

字体大小、颜色、粗细、斜体样式

@Composable
fun TextTestView() {
    val content =
        "Hello Compose!"
    Column(Modifier.fillMaxSize()) {
        Text(
            text = content,
            fontSize = 20.sp, // 字体大小
            color = colorResource(id = R.color.purple_200), // 字体颜色
            fontWeight = FontWeight.Bold, // 字体加粗
            fontStyle = FontStyle.Italic // 字体斜体
        )
    }
}

单行 / 多行,超出显示 ...

在属性介绍中讲解了设置单行不允许换行 softWrap、设置最多显示几行 maxLines、内容超出截取显示 overflow,下面使用代码演示。

  • 设置单行不允许换行,文字超出显示 ...
@Composable
fun TextTestView() {
    val content =
        "文字对任何界面都属于核心内容,而利用 Jetpack Compose 可以更轻松地显示或写入文字。Compose 可以充分利用其构建块的组合,这意味着您无需覆盖各种属性和方法,也无需扩展大型类,即可拥有特定的可组合项设计以及按您期望的方式运行的逻辑。"
        
    Column(Modifier.fillMaxSize()) {
        Text(text = content, softWrap = false, overflow = TextOverflow.Ellipsis)
    }
}

  • 设置多行,超出显示 ...
@Composable
fun TextTestView() {
    val content =
        "文字对任何界面都属于核心内容,而利用 Jetpack Compose 可以更轻松地显示或写入文字。Compose 可以充分利用其构建块的组合,这意味着您无需覆盖各种属性和方法,也无需扩展大型类,即可拥有特定的可组合项设计以及按您期望的方式运行的逻辑。"
        
    Column(Modifier.fillMaxSize()) {
        Text(text = content, maxLines = 3, overflow = TextOverflow.Ellipsis)
    }
}

字体 / 引用字体文件

Compose 内置了几种字体格式,使用 FontFamily. 设置。

@Composable
fun TextTestView() {
    val content = "Hello Compose!"
    Column(Modifier.fillMaxSize()) {
        Text(
            text = content,
            fontSize = 30.sp,
            fontFamily = FontFamily.Cursive
        )
    }
}

Compose 只提供了四种字体格式是远远不够的,开发者可以引用其他的字体格式文件。 在 res 文件夹下创建 font 文件夹,将 .ttf 的字体格式文件放入该文件夹下,通过代码设置给 Text

@Composable
fun TextTestView() {
    val content = "Hello Compose!"
    Column(Modifier.fillMaxSize()) {
        Text(
            text = content,
            fontSize = 30.sp,
            fontFamily = FontFamily(Font(R.font.panda_font))
        )
    }
}

字间距 / 行间距

设置间距和行距使用的是 sp,因为可能机型系统不同,设置老年人模式或设置统一的字体大小,使用 sp 会根据设置改变。dp 是不会的,Compose 也是强制使用 sp

@Composable
fun TextTestView() {
    val content = "Hello Compose!\nHello Compose!"
    Column(Modifier.fillMaxSize()) {
        Text(
            text = content,
            lineHeight = 30.sp,
            letterSpacing = 20.sp
        )
    }
}

中划线 / 下划线

@Composable
fun TextTestView() {
    val content = "Hello Compose!"
    Column(Modifier.fillMaxSize()) {
        Text(
            text = content,
            textDecoration = TextDecoration.Underline
        )

        Text(
            text = content,
            textDecoration = TextDecoration.LineThrough
        )
    }
}

文字对齐方向

下面以水平居中为列子:

@Composable
fun TextTestView() {
    val content = "Hello Compose!\nHello Compose!"
    Column(Modifier.fillMaxSize()) {
        Text(
            text = content,
            modifier = Modifier
                .size(300.dp, 50.dp)
                .background(Color.Gray),
            textAlign = TextAlign.Center
        )

    }
}

获取 Text 内容、行数、宽高等信息

获取内容等信息需要给 Text 添加 onTextLayout 监听,在此列举几个常用的,属性介绍中罗列了可获取的所有参数,感兴趣的小伙伴翻到上面看看。

@Composable
fun TextTestView() {
    val content = "Hello Compose!"
    Column(Modifier.fillMaxSize()) {
        Text(
            text = content,
            onTextLayout = {
                Log.i("Compose Text", "Content:${it.layoutInput.text}")
                Log.i("Compose Text", "Size:${it.size}")
                Log.i("Compose Text", "LineCount:${it.lineCount}")
            }
        )
    }
}

设置 CSS 一样的高级印刷排版样式

CSS 高级印刷排版样式参考链接:developer.mozilla.org/zh-CN/docs/…

Compose 设置的参数和 CSS 对比只是去掉了 -,使用 fontFeatureSettings

@Composable
fun TextTestView() {
    val content = "Hello Compose!"
    Column(Modifier.fillMaxSize()) {
        Text(
            text = content, style = TextStyle(fontFeatureSettings = "smcp")
        )
    }
}

字体缩放比例,倾斜角度

Text 设置水平方向缩放比例,倾斜角度使用 textGeometricTransform 设置,其中有两个参数 scaleX 设置文字内容水平方向缩放比例,skewX 设置文字水平方向剪裁倾斜角度。

@Composable
fun TextTestView() {
    val content = "Hello Compose!"
    Column(Modifier.fillMaxSize()) {
        Text(
            text = content,
            style = TextStyle(textGeometricTransform = TextGeometricTransform(2f, -0.5f))
        )
    }
}

文本内容段落缩进

Text 设置段落缩进使用 textIndent,两个参数 firstLine 和 restLine 分别是设置第一行缩进量和其余行的缩进量。

@Composable
fun TextTestView() {
    val content = "文字对任何界面都属于核心内容,而利用 Jetpack Compose 可以更轻松地显示或写入文字。Compose 可以充分利用其构建块的组合,这意味着您无需覆盖各种属性和方法,也无需扩展大型类,即可拥有特定的可组合项设计以及按您期望的方式运行的逻辑。"\n"
    Column(Modifier.fillMaxSize()) {
        Text(
            text = content,
            style = TextStyle(textIndent = TextIndent(20.sp, 10.sp))
        )
    }
}

文本内容多段不同样式

开发中经常会有这种需求,一串字符串中一部分显示不同颜色或加粗等样式的需求,Compose 提供了 buildAnnotatedString{} 文字构建器、withStyle() 设置该段文本的样式(在属性介绍中讲解了具体参数)、append() 文本链接。

下面以常见的隐私协议样式来展示,看代码更好理解。


在代码中可看出每个文本都在 withStyle 中,分别可以设置不同样式,灵活性高不仅可以设置样式,多段点击也是这样实现,下面 交互详解 中介绍。

交互详解

点击监听

Text 点击监听使用 Modifier 设置

@Composable
fun TextTestView() {
   val content =
       "Hello Compose!"

   var clickNum by remember {
       mutableStateOf(0)
   }

   Text(
       text = content + clickNum,
       modifier = Modifier.clickable(
           onClick = {
               clickNum += 1
           })
   )
}

代码中使用了 ComposeremembermutableStateOf 函数,mutableStateOf 是做数据绑定和变动通知的类似 JetpackliveData,后面写一篇文章详细介绍。

上面代码创建 int 类型变量 clickNum,填写 Text 中显示 UI,点击 Text clickNum + 1Text 收到变量更新后自动刷新显示新的值,下面看实现效果。

文本多段点击监听

不同位置点击监听使用 ClickableText,它也是继承于 BasicText,只是比 Text 多了 onClick 参数,返回点击内容位置的下标。

@Composable
fun TextTestView() {

    var clickIndex by remember {
        mutableStateOf(0)
    }

    ClickableText(
        text = buildAnnotatedString {
            append("您好,请同意《掘金隐私协议》才可以登陆。")
        },

        ) { contentIndex ->
        clickIndex = contentIndex
    }

    Text(
        text = "点击的文字下标:${clickIndex}",
        modifier = Modifier.padding(top = 20.dp)
    )
}

这样就可以根据文字下标来判断点击范围。
下面使用 List 将需要点击的文字下标存下,点击时判断范围。

@Composable
fun TextTestView() {

    var clickIndex by remember {
        mutableStateOf("")
    }

    val clickIndexList: MutableList<Pair<Int, Int>> = ArrayList()

    ClickableText(
        text = buildAnnotatedString {
            append("您好,请同意")

            withStyle(
                style = SpanStyle(
                    fontWeight = FontWeight.Bold,
                    textDecoration = TextDecoration.Underline
                )
            ) {
                val firstIndex = this.length + 1 // 下标开始
                append("《掘金隐私协议》")
                val endIndex = this.length // 下标结束
                clickIndexList.add(Pair(firstIndex, endIndex))
            }
            append("才可以登陆。")
        },

        ) { contentIndex ->
        clickIndex = when (contentIndex) {
            in clickIndexList[0].first..clickIndexList[0].second -> {
                "点击了隐私协议"
            }
            else -> {
                "点击了其他范围"
            }
        }
    }

    Text(
        text = clickIndex,
        modifier = Modifier.padding(top = 20.dp)
    )
}

选择文本内容、复制等操作

Text 默认是不支持选择复制的,需要给它包一层 SelectionContainer{}函数,可以在任意层,比如 TextView 的父 View ... 只要包着 Text 就有效。

@Composable
fun TextTestView() {
    SelectionContainer {
        Text("Hello Compose!")
    }
}

猜你喜欢

转载自blog.csdn.net/qq_39312146/article/details/129942403