文章

Text

Text

Text

Text 基础

官方文档:https://developer.android.google.cn/reference/kotlin/androidx/compose/material/package-summary#text

构造函数方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
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
)
fun Text(
    text: AnnotatedString,
    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,
    inlineContent: Map<String, InlineTextContent> = mapOf(),
    onTextLayout: (TextLayoutResult) -> Unit = {},
    style: TextStyle = LocalTextStyle.current
)

这两种方式的区别就在 于text 参数,一个是 String 类型,一个是 AnnotatedString 类型;第 2 个方法多了个 inlineContent 参数
参数介绍:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
text: String 普通的字符串;
text: AnnotatedString 带有不同属性的字符串,例如可以在一串字符中设置某些字符的颜色、字体、大小等属性;
modifier: Modifier = Modifier 属性Modifier(修饰符)
color: Color = Color.Unspecified 字体的颜色
fontSize: TextUnit = TextUnit.Inherit 绘制文本时使用的字形大小。请参见TextStyle.fontSize
fontStyle: FontStyle? = null 绘制字母时使用的字体变体(例如,斜体)。请参见TextStyle.fontStyle
fontWeight: FontWeight? = null 绘制文本时要使用的字体粗细(例如FontWeight.Bold)。
fontFamily: FontFamily? = null 呈现文本时要使用的字体系列。请参见TextStyle.fontFamily
letterSpacing: TextUnit = TextUnit.Inherit 每个字母之间添加的空间量。请参见TextStyle.letterSpacing
textDecoration: TextDecoration? = null 要在文字上绘制的装饰(例如下划线)。请参见TextStyle.textDecoration
textAlign: TextAlign? = null 文本在段落中的对齐方式。请参见TextStyle.textAlign
lineHeight: TextUnit = TextUnit.Inherit TextUnit为单位的段落的行高,例如SPEM。请参见TextStyle.lineHeight
overflow: TextOverflow = TextOverflow.Clip 视觉溢出应的处理方式,例如尾部显示…或者中间显示…。
softWrap: Boolean = true 文本是否应在换行符处中断。如果为false,则文本的宽度会在水平方向上无限延伸,且textAlign属性失效,可能会出现异常情况。
maxLines: Int = Int.MAX_VALUE 文本可跨越的可选最大行数,必要时可以换行。如果文本超过给定的行数,则会根据textAlignsoftWrap属性截断文本。它的值必须大于零。
onTextLayout: (TextLayoutResult) -> Unit = {} 计算新的文本布局时执行的回调。
style: TextStyle = AmbientTextStyle.current 文本的样式配置,例如颜色,字体,行高等。也就是说上面属性中的color,fontSize等一些属性也可以在这里进行声明。具体包含的属性可以参考TextStyle类。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
@Composable
private fun TextDemo(startString: String, endString: String) {
    val annotatedStringBuilder = AnnotatedString.Builder(startString)
    annotatedStringBuilder.pushStyle(
        SpanStyle(
            color = Color.Red,
            fontSize = 24.sp,
            fontStyle = FontStyle.Italic,
        )
    )
    annotatedStringBuilder.append("【可以】")
    annotatedStringBuilder.pop()
    annotatedStringBuilder.append(endString)
    val annotatedString = annotatedStringBuilder.toAnnotatedString()

    Text(
        text = annotatedString,
//            color = Color.Blue,
        fontSize = 16.sp,
        fontWeight = FontWeight.Bold,
        fontStyle = FontStyle.Normal,
        overflow = TextOverflow.Ellipsis,
        textAlign = TextAlign.Center,
        style = TextStyle(
            color = Color.White,
            background = Color.DarkGray
        ),
        modifier = Modifier
            .width(200.dp)
            .height(100.dp)
            .wrapContentSize(align = Alignment.CenterEnd)
//            .drawOpacity(1f)
            .clickable(onClick = {
                Toast
                    .makeText(this, "点击了全文本", Toast.LENGTH_SHORT)
                    .show()
            })
            .background(color = Color.Yellow)
    )
}

@Preview
@Composable
private fun previewTextDemo() {
    TextDemo(startString = "你", endString = "的")
}

显示文本

  • 需要显示资源中的文字则可以使用 stringResource
1
2
3
Text(text = "hello world")
// 需要显示资源中的文字则可以使用stringResource
Text(stringResource(id = R.string.app_name))

字体

字体颜色 color

  • Color
  • TextStyle color
1
2
3
4
5
6
7
8
9
10
11
Text(
    text = stringResource(id = R.string.app_name),
    color = Color.Blue
)
// 使用 style 使用定义color
Text(
    text = stringResource(id = R.string.app_name),
    style = TextStyle(
        color = Color.Blue
    )
)
  • 如果是资源中的颜色 可以使用 colorResource
  • RGB
1
2
3
4
color = colorResource(id = R.color.black)
// 还可以是
Color(0xffff0000)
Color(red = 0f, green = 0f, blue = 1f)
  • String
1
2
3
4
5
6
7
fun Color.Companion.parse(colorString: String): Color =
    Color(color = android.graphics.Color.parseColor(colorString))
// 使用
Text(
    text = stringResource(id = R.string.app_name),
    color = Color.parse("#FF0000")
)

文字大小 fontSize

1
2
3
4
Text(
    text = stringResource(id = R.string.hello_world),
    fontSize = 40.sp
)

字体样式 fontStyle

  • FontStyle.Normal 默认
  • FontStyle.Italic 斜体
1
2
3
4
5
6
7
8
9
10
Column {
    Text(
        text = value,
        fontStyle = FontStyle.Normal
    )
    Text(
        text = value,
        fontStyle = FontStyle.Italic
    )
}

d4uyv
具体见下面的 文字样式

字体加粗 fontWeight

1
2
3
4
Text(
    text = value,
    fontWeight = FontWeight.W800
)

下图中 左右两边等价:
yz5af
效果:
pknmm

字体 fontFamily

1
2
3
4
Text(
    text = value,
    fontFamily = FontFamily.Default
)

104ne

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

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

字间隔空 letterSpacing

1
2
3
4
Text(
    text = value,
    letterSpacing = 2.sp
)

ix1wc

文字装饰 textDecoration

1
2
3
4
Text(
    text = value,
    textDecoration = TextDecoration.None
)

347wy

对齐方式

相当于 TextView 的 android:gravity='left'
sm84z
Justify 表示两端贴边

TextAlign.Center 不生效

1
2
3
4
5
6
7
Text(
    text = "How many cars are in the garage",
    modifier = Modifier
        .size(350.dp, 100.dp)
        .background(Color.Red),
    textAlign = TextAlign.Center
)

mx416
解决 1:用 .wrapContentHeight()wrapContentSize()

1
2
3
4
5
6
7
8
9
10
Text(
    text = "How many cars are in the garage",
//  textAlign = TextAlign.Center, // make text center horizontal
    modifier = Modifier
        .width(350.dp)
        .height(100.dp)
        .background(Color.Cyan)
        .wrapContentSize()
//      .wrapContentHeight() // make text center vertical
)

1n21y
解决 2:在 Text 外层加上 Box 后设置 Box 的属性来实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Box(
    modifier = Modifier
        .size(250.dp)
        .border(width = 4.dp, color = Gray, shape = RoundedCornerShape(16.dp)),
    contentAlignment = Alignment.Center
) {
    Text(
        text = "Question 1 : How many cars are in the garage?",
        modifier = Modifier
            .padding(16.dp)
            .width(350.dp)
            .height(80.dp)
            .background(Color.Gray),
        textAlign = TextAlign.Center,
    )
}

79esu
解决 3:Column wrapContentSize

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Column(
    modifier = Modifier
        .padding(30.dp)
        .fillMaxWidth()
        .wrapContentSize(Alignment.Center)
        .clickable(onClick = { }) /*question = "3 Bananas required"*/
        .clip(shape = RoundedCornerShape(16.dp)),
) {
    Box(
        modifier = Modifier
            .size(250.dp)
            .border(width = 4.dp, color = Gray, shape = RoundedCornerShape(16.dp)),
        contentAlignment = Alignment.Center
    ) {
        Text(
            text = "Question 1 : How many cars are in the garage?",
            modifier = Modifier.padding(16.dp),
            textAlign = TextAlign.Center,
        )
        //...
    }
}

行高 lineHeight

1
2
3
4
Text(
    text = value,
    lineHeight = 30.sp
)

最大行数 maxLines

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

文字溢出 overflow

  • Clip 将溢出的部分裁剪,默认
  • Ellipsis 使用省略号表示溢出部分
  • Visible 指定范围内没有足够的空间。也要显示所有文本

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

1
2
3
4
5
6
7
8
9
10
11
12
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
23n1jj5ggb

换行处理 softWrap

  • false 被定位为有无限的水平空间
  • true 默认会有边界

b9h1p

文字样式 fontStyle

背景颜色 background

1
2
3
style = TextStyle(
    background = Color.Red
)

基线偏移 baselineShift

1
2
3
4
5
6
Text(
    text = value,
    style = TextStyle(
        baselineShift = BaselineShift.Subscript
    )
)

Android Text 的基线 baseline:ix0i3
BaselineShift 给我们提供了 3 个默认的选项

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

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
Text(
    text = "hello world 1f",
    style = TextStyle(
        background = Color.Yellow,
        baselineShift = BaselineShift(1f)
    )
)
Text(
    text = "hello world 0.5f",
    style = TextStyle(
        background = Color.Green,
        baselineShift = BaselineShift.Superscript
    )
)
Text(
    text = "hello world 0f",
    style = TextStyle(
        background = Color.Red,
        baselineShift = BaselineShift.None
    )
)
Text(
    text = "hello world -0.5f",
    style = TextStyle(
        background = Color.Yellow,
        baselineShift = BaselineShift.Subscript
    )
)
Text(
    text = "hello world -1f",
    style = TextStyle(
        background = Color.Cyan,
        baselineShift = BaselineShift(-1f)
    )
)

1966r

合成字体 fontSynthesis

1
fontSynthesis = FontSynthesis.All

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

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

文字缩进 textIndent

1
2
3
4
5
6
class TextIndent(
    //第一行的缩进
    val firstLine: TextUnit = 0.sp,
    //除了第一行其他行的缩进
    val restLine: TextUnit = 0.sp
) 

示例:

1
2
3
4
5
6
Text(
    text = "hello world".repeat(2),
    style = TextStyle(
        textIndent = TextIndent(10.sp, 10.sp)
    )
)

文字方向 textDirection

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

1
2
3
style = TextStyle(
    textDirection = TextDirection.Ltr
)

字体阴影

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
Text(
    text = "hello world".repeat(2),
    style = TextStyle(
        shadow = Shadow(
            color = Color.Red,
            offset = Offset.Zero,
            blurRadius = 20.0f
        )
    )
)
Text(
    text = "hello world".repeat(2),
    style = TextStyle(
        shadow = Shadow(
            color = Color.Red,
            offset = Offset.Zero,
            blurRadius = 2.0f
        )
    )
)
Text(
    text = "hello world".repeat(2),
    style = TextStyle(
        shadow = Shadow(
            color = Color.Red,
            offset = Offset(10F, 10F),
            blurRadius = 2.0f
        )
    )
)

oa4dl

几何变换

  • scaleX 水平缩放 默认是 1f 不缩放
  • skewX 倾斜 默认是 0f 不倾斜
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Text(
    text = "hello world".repeat(2),
    style = TextStyle(
        textGeometricTransform = TextGeometricTransform(
            scaleX = 1f,
            skewX = 0f
        )
    )
)
Text(
    text = "hello world".repeat(2),
    style = TextStyle(
        textGeometricTransform = TextGeometricTransform(
            scaleX = 1f,
            skewX = 0.5f
        )
    )
)

jqrjg

语言环境

1
2
3
style = TextStyle(
    localeList = LocaleList(Locale.current)
)

高级排版

1
2
3
4
5
6
Text(
    text = "Hello World",
    style = TextStyle(
        fontFeatureSettings = "smcp"
    )
)

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

1tbmk

本文由作者按照 CC BY 4.0 进行授权