Compose - Text 详解

3,816 阅读5分钟

前言

学习记录一波。方便后续查阅。也方便其他小伙伴能够快速上手。 官网可查看

显示文本

📌 下面为了篇幅就省略预览以及注解。只显示关键信息代码。

@Preview(showBackground = true)
@Composable
fun SimpleText() {
    Text(text = "hello world")
}

如果需要显示资源中的文字则可以使用stringResource

Text(stringResource(id = R.string.hello_world))

字体颜色 ☆

Text(
    text = stringResource(id = R.string.hello_world),
    color = Color.Blue
)

或者使用 style 使用定义color

📌 下面可以在 TextStyle中找到相同属性的。会在标题中加入 ☆

Text(
    text = value,
    style = TextStyle(
        color = Color.Blue
    )
)

如果是资源中的颜色 可以使用colorResource

color = colorResource(id = R.color.black)

还可以是

Color(0xffff0000)
Color(red = 0f, green = 0f, blue = 1f)

当然我们最习惯用的还是String的颜色值,不过Compose 好像没有提供这样的方法,不过可以自己定义一下。例如

//拓展函数
fun Color.Companion.parse(colorString: String): Color =
    Color(color = android.graphics.Color.parseColor(colorString))

使用就很简单了

color = Color.parse("#FF0000"),

文字大小 ☆

Text(
    text = stringResource(id = R.string.hello_world),
    fontSize = 40.sp
)

字体样式 ☆

  • Normal 默认
  • Italic 斜体
Column {
    Text(
        text = value,
        fontStyle = FontStyle.Normal
    )
    Text(
        text = value,
        fontStyle = FontStyle.Italic
    )
}

image.png

字体加粗 ☆

Text(
    text = value,
    fontWeight = FontWeight.W800
)

下图中 左右两边等价

image.png

image.png

字体 ☆

Text(
    text = value,
    fontFamily = FontFamily.Default
)

image.png

可以使用 fontFamily 属性来处理 res/font 文件夹中定义的自定义字体和字型

image.png

  • 需要注意 引入的字体库名称 必须仅包含小写字母az,0-9或下划线
  • 引入完成就以后需要rebuild一下,否则无法找到 font
  • 字体下载
val fontFamily = FontFamily(
    Font(resId = R.font.myfont, weight = FontWeight.Normal)
)
Text(
    text = "Demo Text",
    style = TextStyle(
        fontFamily = fontFamily,
    )
)

字间隔空 ☆

Text(
    text = value,
    letterSpacing = 2.sp
)

image.png

文字装饰 ☆

Text(
    text = value,
    textDecoration = TextDecoration.None
)

image.png

对齐方式 ☆

相当于传统的 android:gravity='left'

Text(
    text = value,
    textAlign = TextAlign.Left
)

image.png

其中Justify表示两端贴边

image.png

TextAlign.StartTextAlign.Left的区别

有些国家的文字是从右往左。例如阿拉伯语。

  • TextAlign.Left表示 不管你是什么语言,都是靠左
  • TextAlign.Start会根据首选项语言去选择从左还是从右

image.png

行高 ☆

Text(
    text = value,
    lineHeight = 30.sp
)

image.png

最大行数

Text("hello ".repeat(50), maxLines = 2)

image.png

文字溢出

Text(
    text = value,
    overflow = TextOverflow.Ellipsis,
    maxLines = 1
)
  • Clip 将溢出的部分裁剪
  • Ellipsis 使用省略号表示溢出部分
  • Visible 指定范围内没有足够的空间。也要显示所有文本

image.png

关于最后一个Visible官网中可以找到示例去演示器效果。笔者这边简化了一下。示例如下。

Box(modifier = Modifier
    .size(300.dp, 150.dp)
    .background(Color.Red)) {
    Text(
        text = "Hello World".repeat(2),
        modifier = Modifier
            .size(200.dp, 70.dp)
            .background(Color.Yellow),
        fontSize = 35.sp,
        overflow = TextOverflow.Visible,
    )
}
未设置Visible设置了Visible
image.pngimage.png

换行处理

Text(
    text = value2,
    softWrap = false
)
  • false 被定位为有无限的水平空间
  • true 默认会有边界

image.png

onTextLayout

计算新的文本布局时执行的回调.预览是不打印的。只有运行才会打印

@Preview(showBackground = true)
@Composable
fun SimpleText7() {
    val value = "hello world"
    Column(Modifier.width(200.dp)) {
        Text(
            text = value,
            onTextLayout = {
                Log.i("TAGText",it.toString())
            }
        )
    }
}

运行以后的结果,可以看到所有的属性都被打印出来了

2021-04-14 11:40:50.016 16830-16830/com.starot.pencase_compose I/TAGText: TextLayoutResult(layoutInput=TextLayoutInput(
text=hello world,
style=TextStyle(color=Color(0.0, 0.0, 0.0, 1.0, sRGB IEC61966-2.1), 
fontSize=Unspecified, 
fontWeight=null, 
fontStyle=null, 
fontSynthesis=null, 
fontFamily=null, 
fontFeatureSettings=null, 
letterSpacing=Unspecified, 
baselineShift=null, 
textGeometricTransform=null, 
localeList=null, 
background=Color(0.0, 0.0, 0.0, 0.0, None), 
textDecoration=null, 
shadow=null, 
textAlign=null, 
textDirection=null, 
lineHeight=Unspecified, 
textIndent=null), 
placeholders=[], 
maxLines=2147483647, 
softWrap=true, 
overflow=Clip, 
density=DensityImpl(density=2.75, fontScale=1.0), 
layoutDirection=Ltr, 
resourceLoader=androidx.compose.ui.platform.AndroidFontResourceLoader@7058a4b, 
constraints=Constraints(minWidth = 0, maxWidth = 550, minHeight = 0, maxHeight = 1977)),
multiParagraph=androidx.compose.ui.text.MultiParagraph@e80ec28, 
size=184 x 52, 
firstBaseline=41.0, 
lastBaseline=41.0, placeholderRects=[])

文字样式 🔥

style属性的TextStyle类中。有很多就可以在Text的构造方法中去执行。但是依然有一些特殊的属性

背景颜色

style = TextStyle(
    background = Color.Red
)

image.png

基线偏移

Text(
    text = value,
    style = TextStyle(
        baselineShift = BaselineShift.Subscript
    )
)

说明这个属性之前,要明白什么是基线。用hencoder中描述

每只小鸟的最高点和最低点都不一样,但画面很平衡,而这个用来让所有文字互相对齐的基准线,就是基线( baseline )

Android Text 的基线baseline

image.png

实际运行效果呢?

笔者这边选择了 3个参数进行演示。

image.png

BaselineShift给我们提供了3个默认的选项

  • val Superscript = BaselineShift(0.5f)
  • val Subscript = BaselineShift(-0.5f)
  • val None = BaselineShift(0.0f)

合成字体

fontSynthesis = FontSynthesis.All

合成字体用于指定当使用的FontFamily不包含粗体或斜体时,系统是否应该伪造粗体或倾斜字形。

  • None 关闭字体合成。 如果FontFamily中不存在粗体和斜体,则不会合成它们
  • Weight 如果FontFamily中不提供,则仅合成粗体。 倾斜的字体将不会被合成。
  • Style 如果FontFamily中不可用,则仅合成倾斜的字体。 粗体字体将不被合成。
  • All 如果FontFamily中不提供粗体和倾斜字体,则系统会合成粗体和倾斜字体

文字缩进

Text(
    text = "hello world".repeat(2),
    style = TextStyle(
        textIndent = TextIndent(10.sp,10.sp)
    )
)
class TextIndent(
    //第一行的缩进
    val firstLine: TextUnit = 0.sp,
    //除了第一行其他行的缩进
    val restLine: TextUnit = 0.sp
) 

image.png

文字方向

style = TextStyle(
    textDirection = TextDirection.Ltr
)

一般情况下。我们用到的都是从左往右。也有一些国家的语言是从右往左,例如阿拉伯语

image.png

  • Ltr 从左往右
  • Rtl 从右往左

下面的几个类型都是根据Unicode双向算法,文本方向取决于文本中的第一个强方向字符。适用于文本中有两种不同的文字。

关于Unicode双向算法可以查看 Unicode控制字符

  • Content
  • ContentOrLtr
  • ContentOrRtl

字体阴影

 style = TextStyle(
    shadow = Shadow(
        color = Color.Red,
        offset = Offset.Zero,
        blurRadius = 20.0f
    )
)
  • color 背景颜色

image.png

  • blurRadius 模糊半径

image.png

  • offset 偏移

image.png

几何变换

  • scaleX 水平缩放 默认是1f 不缩放
style = TextStyle(
    textGeometricTransform = TextGeometricTransform(
        scaleX = 1f,
        skewX = 0f
    )
)

image.png

  • skewX 倾斜 默认是0f 不倾斜

image.png

语言环境

style = TextStyle(
    localeList = LocaleList(Locale.current)
)

首先放上hencoder 对于Locale的介绍

image.png

高级排版

Text(
    text = "Hello World",
    style = TextStyle(
        fontFeatureSettings = "smcp"
    )
)

用 CSS 的 font-feature-settings 的方式来设置文字

image.png