欢迎访问移动开发之家(rcyd.net),关注移动开发教程。移动开发之家  移动开发问答|  每日更新
页面位置 : > > > 内容正文

Jetpack Compose基础组件之文字组件,

来源: 开发者 投稿于  被查看 36389 次 评论:25

Jetpack Compose基础组件之文字组件,


目录
  • 概述
  • 文字组件
    • 1.Text 文本
    • 2.Text的style文字样式
    • 3.maxLines参数
    • 4.fontFamily字体风格
    • 5.AnnotatedString多样式文字
    • 6.SelectionContainer可选中文字
    • 7.TextField输入框
    • 8.OutlinedTextField边框样式输入框
    • 9.BasicTextField
  • 总结

    概述

    文本是UI界面中最常见的元素之一,在Compose中,文字组件扮演着重要的角色,文字组件是遵循Material Design规范设计的上层组件,如果我们不想使用Material Design,我们也可以直接使用更底层的文本组件,如Text组件对应的更底层的文本组件是BasicText,文本组件不得不提输入框的使用,本文会主要介绍Text和输入框,并且实现一个现在App中都在用的好看的输入框

    文字组件

    1.Text 文本

    因为Composable组件都是函数,所有的配置都来自于参数的传递,所以我们通过参数列表就可以了解组件的所有功能,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,// 控制文本是否能够换行,如果为false,则会定位
        maxLines: Int = Int.MAX_VALUE,// 文本最多的展示行数
        onTextLayout: (TextLayoutResult) -> Unit = {},// 在文本发生变化之后,会回调一个TextLayoutResult,包含此文本的各种信息
        style: TextStyle = LocalTextStyle.current // 文本的风格配置,如颜色,字体,行高等
    )
    

    Text组件的参数会按照其使用的频度排序,比如text和modifier排在靠前的位置,并尽量添加默认实现。

    Text组件的基本功能是显示一段文字,可以为text参数传入要显示的文字内容,Compose也提供了stringResource方法,通过R 资源文件获取字符串,方便做多语言适配

            // 指定字符串
            Text(text = "Hello World")
            // 指定文字资源
            Text(text = stringResource(id = R.string.app_name))
    

    2.Text的style文字样式

    style参数接受一个TextStyle类型,TextStyle中包含了一系列设置文字样式的字段,例如行高,间距,字体大小,字体粗细等,演示代码如下所示:

    @Composable
    fun TextStyleDemo() {
        Column {
            Text(
                text = "Zhongxj",
                style = TextStyle(
                    fontSize = 25.sp,
                    fontWeight = FontWeight.Bold,
                    background = Color.Cyan,
                    lineHeight = 35.sp
                )
            )
            Text(
                text = stringResource(id = R.string.app_name), style = TextStyle(
                    color = Color.Cyan,
                    letterSpacing = 4.sp
                )
            )
            Text(
                text = "Hello world", style = TextStyle(
                    textDecoration = TextDecoration.LineThrough
                )
            )
            Text(
                text = "Walt-zhong",
                style = MaterialTheme.typography.h6.copy(fontStyle = FontStyle.Italic)
            )
        }
    }
    

    运行结果如下所示:

    代码中的TextDecoration可以为文字增加删除线或下划线,FontStyle可以用来设置文字是否是斜体

    3.maxLines参数

    maxLines参数可以帮助我们将文本限制在指定行数之间,当文本超过了参数设置的阈值时,文本会被截断,而overflow可以处理文字过多的场景,文字过多的时候会以“...”结尾,这个参数可以用来实现一个阅读文字时的展开和收起功能,当我们显示很多条数据时,每一条数据都有很多的文字,这时我们可以使用这个参数,默认只展示指定的行数,提供一个展开按钮,当用户点击展开的时候,就显示所有的文本。展示收起按钮,点击收起按钮又可以显示指定的行数。这个功能后面有时间我们会演示,这里我们先看下基本的演示代码:

    @Composable
    fun MaxLinesDemo() {
        Column {
            Text(
                text = "在Compose中,每一个组件都是带有@Compose注解的函数,被称为Composable。" +
                        "Compose已经预置了很多的Compose UI组件,这些组件都是基于Material Design规范设计的",
                style = MaterialTheme.typography.body1,
                color = Color.Red
            )
            Spacer(modifier = Modifier.size(10.dp))
            Text(
                text = "在Compose中,每一个组件都是带有@Compose注解的函数,被称为Composable。" +
                        "Compose已经预置了很多的Compose UI组件,这些组件都是基于Material Design规范设计的",
                style = MaterialTheme.typography.body1,
                maxLines = 1,
                color = Color.Green
            )
            Spacer(modifier = Modifier.size(10.dp))
            Text(
                text = "在Compose中,每一个组件都是带有@Compose注解的函数,被称为Composable。" +
                        "Compose已经预置了很多的Compose UI组件,这些组件都是基于Material Design规范设计的",
                style = MaterialTheme.typography.body1,
                maxLines = 1,
                color = Color.Blue,
                overflow = TextOverflow.Ellipsis
            )
        }
    }
    

    运行结果:

    4.fontFamily字体风格

    fontFamily参数用来设置文字字体,演示代码如下:

    @Composable
    fun FontFamilyDemo() {
        Column {
            Text(text = "Hello World", color = Color.Red)
            Spacer(modifier = Modifier.size(10.dp))
            Text(text = "Hello World", color = Color.Green, fontFamily = FontFamily.Monospace)
            Spacer(modifier = Modifier.size(10.dp))
            Text(text = "Hello World", color = Color.Blue, fontFamily = FontFamily.Cursive)
        }
    }
    

    运行结果

    当使用系统中没有的字体时,可以右击res文件夹,选择New->Android Resource Directory->Resource type ->font创建font文件夹,然后将自己的字体拖入文件夹即可

    5.AnnotatedString多样式文字

    AnnotatedString 其实很像传统View中的SpannableString,在很多的场景中,我们需要在一段文字中突出某些内容,比如超链接和电话号码,我们点击超链接和电话号码能跳到链接指向的页面和拨打电话。在Compose中就需要使用AnnotatedString多样式文字,AnnotatedString是一个数据类,除了文本值,它还包含了一个SpanStyle和ParagraphStyle的Range列表,SpanStyle用于描述在文本中字串的文字样式,ParagraphStyle则用于描述文本字串中的段落样式,Range确定字串的范围,示例代码如下:

    @Composable
    fun AnnotatedStringDemo() {
        Text(text = buildAnnotatedString {
            withStyle(style = SpanStyle(fontSize = 24.sp)) {
                append("I am Iron man,我是钢铁侠")
            }
            withStyle(style = SpanStyle(fontWeight = FontWeight.W900, fontSize = 24.sp)) {
                append("zhongxj")
            }
            append("\n")
            withStyle(style = ParagraphStyle(lineHeight = 25.sp)) {
                append(
                    "在Compose中,每一个组件都是带有@Compose注解的函数,被称为Composable。" +
                            "Compose已经预置了很多的Compose UI组件,这些组件都是基于Material Design规范设计的"
                )
            }
            append("\n")
            append("Now,We are working hard")
            append(annotatedText)
        })
    }
    

    运行结果如下:

    SpanStyle继承了TextStyle中关于文字样式相关的字段,而ParagraphyStyle继承了TextStyle中控制锻炼的样式,例如textAlign,lineHeight等。SpanStyle和ParagraphyStyle中的设置优先于整个TextStyle中同名属性的设置

    看到上图中的绿色文字,是不是有一种想点击的冲动,可惜现在是无法点击的,若要实现点击,我们需要借助于ClickedText.演示代码如下:

    @Composable
    fun ClickTextDemo() {
        ClickableText(text = annotatedText, onClick = { offset ->
            annotatedText.getStringAnnotations(
                tag = "URL",
                start = offset,
                end = offset
            ).firstOrNull()?.let {
                Log.d("zhongxj", "click me, content: $it")
            }
        })
    }
    val annotatedText = buildAnnotatedString {
        withStyle(style = ParagraphStyle(lineHeight = 25.sp)) {
            append(
                "在Compose中,每一个组件都是带有@Compose注解的函数,被称为Composable。" +
                        "Compose已经预置了很多的Compose UI组件,这些组件都是基于Material Design规范设计的"
            )
        }
        append("\n")
        pushStringAnnotation(tag = "URL", annotation = "http://xxxxx")
        withStyle(
            style = SpanStyle(
                fontWeight = FontWeight.W900,
                textDecoration = TextDecoration.Underline,
                color = Color(0xFF59A869)
            )
        ) {
            append("点击我,了解更多")
        }
    }
    

    运行结果如下:

    这样才可以点击,点击的时候我们打了一个Log,证明点击生效了

    6.SelectionContainer可选中文字

    Text自身默认是不能被长按选择的,否则在Button使用的时候,就会出现传统View的Button是可粘贴的Button的按钮,Compose提供了专门的SelectionContainer组件对包裹的Text进行选中,演示代码如下:

    @Composable
    fun SelectionContainerDemo() {
        SelectionContainer {
            Text(text = "我是可以被复制的文字")
        }
    }
    

    运行结果:

    7.TextField输入框

    TextField组件是我们最常用的文本输入框,遵循Material Design设计准则,它有一个低级别的底层组件,BasicTextField.TextField有两种风格,默认的(filled)和OutlinedTextField我们可以先看下输入框的参数

    @Composable
    fun TextField(
        value: String, // 输入框显示的文本
        onValueChange: (String) -> Unit, // 当输入框内的文字发生改变时的回调,其中带有最新的文本参数
        modifier: Modifier = Modifier,// 修饰符
        enabled: Boolean = true,// 是否启用
        readOnly: Boolean = false, // 控制输入框的可编辑状态
        textStyle: TextStyle = LocalTextStyle.current, // 输入框内文字样式
        label: @Composable (() -> Unit)? = null, // 可选的标签,将显示在输入框内
        placeholder: @Composable (() -> Unit)? = null, // 占位符,当输入框处于焦点位置且输入框文本为空时显示
        leadingIcon: @Composable (() -> Unit)? = null, // 输入框开头的前置图标
        trailingIcon: @Composable (() -> Unit)? = null,// 输入框末尾的后置图标
        isError: Boolean = false, // 指示输入框当前值是否有错,当值为true时,标签底部指示器和尾部图标将以错误的颜色显示
        visualTransformation: VisualTransformation = VisualTransformation.None,// 输入框内的文字视觉
        keyboardOptions: KeyboardOptions = KeyboardOptions.Default, // 软键盘选项,包含键盘类型和ImeAction等配置
        keyboardActions: KeyboardActions = KeyboardActions(), // 当输入服务发出一个IME动作时,相应的回调被调用
        singleLine: Boolean = false,// 输入框是否只能输入一行
        maxLines: Int = Int.MAX_VALUE, // 输入框能输入的最大行数
        interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, // 监听组件的状态便于自定义
        // 组件不同状态下的样式
        shape: Shape =
            MaterialTheme.shapes.small.copy(bottomEnd = ZeroCornerSize, bottomStart = ZeroCornerSize),// 输入框的外观形状
        colors: TextFieldColors = TextFieldDefaults.textFieldColors() // 输入框的颜色组
    ) 
    

    演示示例如下所示:

    @Composable
    fun TextFieldDemo() {
        var text by remember {
            mutableStateOf("")
        }
        TextField(value = text, onValueChange = {
            text = it
        },
            label = { Text(text = "用户名") })
    }
    

    运行结果

    输入框附带一个label,label会更具输入框获得焦点而呈现出不同的效果,底部会有一个高亮的图标,代码中有关于State的使用,此处不做讲解,这里用于展示使用

    我们还可以给输入框添加装饰,代码如下:

    @Composable
    fun TextFieldWithDec() {
        var username by remember {
            mutableStateOf("")
        }
        var password by remember {
            mutableStateOf("")
        }
        Column {
            TextField(value = username, onValueChange = {
                username = it
            }, label = { Text(text = "用户名") }, leadingIcon = {
                Icon(imageVector = Icons.Filled.AccountBox, contentDescription = "用户名")
            })
            TextField(value = password, onValueChange = {
                password = it
            }, label = { Text(text = "密码") }, trailingIcon = {
                IconButton(onClick = { /*TODO*/ }) {
                    Icon(
                        painter = painterResource(id = R.drawable.password),
                        modifier = Modifier.size(16.dp),
                        contentDescription = "password"
                    )
                }
            })
        }
    }
    

    运行结果

    8.OutlinedTextField边框样式输入框

    OutlinedTextField是按照Material Design规范设计的另一种风格的输入框,除了外观上带有一个边框,其他用法和TextField基本一致,演示代码如下:

    @Composable
    fun OutlineTextFieldDemo()
    {
        var text by remember {
            mutableStateOf("")
        }
        OutlinedTextField(value = text, onValueChange = {text = it},
            label = { Text(text = "用户名")})
    }
    

    运行结果:

    9.BasicTextField

    BasicTextField是一个更低级别的Compose组件,与TextField,OutlinedTextField不同的是,BasicTextField拥有更多的自定义效果,我们可以看下BasicTextField为我们提供的可选参数列表:

    @Composable
    fun BasicTextField(
        value: String,
        onValueChange: (String) -> Unit,
        modifier: Modifier = Modifier,
        enabled: Boolean = true,
        readOnly: Boolean = false,
        textStyle: TextStyle = TextStyle.Default,
        keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
        keyboardActions: KeyboardActions = KeyboardActions.Default,
        singleLine: Boolean = false,
        maxLines: Int = Int.MAX_VALUE,
        visualTransformation: VisualTransformation = VisualTransformation.None,
        onTextLayout: (TextLayoutResult) -> Unit = {}, // 当输入框文本更新时的回调包括当前文本的各种信息
        interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
        cursorBrush: Brush = SolidColor(Color.Black), // 输入框光标的颜色
        decorationBox: @Composable (innerTextField: @Composable () -> Unit) -> Unit =
            @Composable { innerTextField -> innerTextField() } // 允许在TextField周围添加修饰的Composable lambda,需要在布局中
            // 中调用innerTextField()才能完成TextField的创建
    )
    

    我们可以看到,BasicTextField的参数和TextField的参数有很多共同的地方,我们自定义的关键在于最后一个参数decorationBox,decorationBox是一个Composable,它回调了一个innerTextField函数给我们,innerTextField是框架定义好给我们使用的,它就是文字输入的入口,所以需要创建一个完整的输入框界面,并且在合适的地方调用这个函数,我们实现一个仿当前大多是app都会使用的输入框结束今天的内容:代码如下

    @Composable
    fun SearchBar() {
        var text by remember {
            mutableStateOf("")
        }
        Box(
            modifier = Modifier
                .fillMaxSize()
                .background(Color(0xFFD3D3D3)),
            contentAlignment = Alignment.Center
        )
        {
            BasicTextField(value = text, onValueChange = {
                text = it
            }, decorationBox = { innerTextField ->
                Row(
                    verticalAlignment = Alignment.CenterVertically,
                    modifier = Modifier.padding(vertical = 2.dp, horizontal = 8.dp)
                ) {
                    Icon(imageVector = Icons.Filled.Search, contentDescription = null)
                    Box(
                        modifier = Modifier.padding(horizontal = 10.dp),
                        contentAlignment = Alignment.CenterStart
                    ) {
                        if (text.isEmpty()) {
                            Text(
                                text = "请输入", style = TextStyle(
                                    color = Color(0, 0, 0, 128)
                                )
                            )
                        }
                        innerTextField()
                    }
                    Box(
                        modifier = Modifier.fillMaxWidth(),
                        contentAlignment = Alignment.CenterEnd
                    ) {
                        if (text.isNotEmpty()) {
                            IconButton(onClick = { text = "" }, modifier = Modifier.size(16.dp)) {
                                Icon(
                                    imageVector = Icons.Filled.Close, contentDescription = null
                                )
                            }
                        }
                    }
                }
            }, modifier = Modifier
                .padding(horizontal = 10.dp)
                .background(Color.White, CircleShape)
                .height(30.dp)
                .fillMaxWidth()
            )
        }
    }
    

    运行结果

    总结

    至此,我们的文字组件就介绍完了,本文只是简单的介绍了文字组件的入门功能,如果读者想要实现更加复杂绚丽的功能,请查看官方文档和3672js教程其它相关文章!

    您可能感兴趣的文章:
    • Jetpack Compose按钮组件使用实例详细讲解
    • Jetpack Compose图片组件使用实例详细讲解
    • Jetpack Compose之选择器使用实例讲解
    • Jetpack Compose实现对话框和进度条实例解析
    • Android使用Jetpack Compose开发零基础起步教程
    • Jetpack Compose实现对角线滚动效果
    • 融会贯通Android Jetpack Compose中的Snackbar
    • 使用Jetpack Compose实现翻转卡片效果流程详解

    用户评论