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()
        )
    }
}

运行结果

总结

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

(0)

相关推荐

  • 融会贯通Android Jetpack Compose中的Snackbar

    目录 正文 主要的实现思路 Snackbar UI部分 正文 开始写Compose的时候,真的有点不习惯.思考方式和以前完全不同,有点类似ReactNative. 写习惯了之后,还真有点欲罢不能,行云流水~ Snackbar感觉就是Toast Plus版,可以自定义视图,还可以进行交互,可以用在很多地方实现意想不到的效果. 主要的实现思路 主要的实现思路有两部步: 1.Snackbar的控制逻辑 2.Snackbar的UI部分 Snackbar UI部分 class MainActivity :

  • Jetpack Compose按钮组件使用实例详细讲解

    目录 概述 1.普通Button按钮 2.IconButton图标按钮 3.FloatingActionButton悬浮按钮 总结 概述 按钮组件Button是用户和系统交互的重要组件之一,它按照Material Design风格实现,我们先看下Button的参数列表,通过参数列表了解下Button的整体功能 @Composable fun Button( onClick: () -> Unit, // 点击按钮时的回调 modifier: Modifier = Modifier, // 修饰符

  • Jetpack Compose实现对角线滚动效果

    目录 缘起 初试 探索 学习 FreeScrollState freeScroll 总结 缘起 不久前刷到 newki 前辈的文章,用自定义 viewGroup的方式实现了如图效果: Android自定义ViewGroup嵌套与交互实战,幕布全屏滚动效果 我当时的反应: new bee ! new bee ! 这效果不错 初试 大佬用 Android View 出来了,那能否用 Google 新一代 UI Compose 来整一个呢? 正好手上有本 fun 神写得书 <Jetpack Compo

  • Android使用Jetpack Compose开发零基础起步教程

    目录 永远的Hello World 分解的HelloWorld代码 预览函数 先搭建好之后呢,我们就来做第1个例子. 永远的Hello World 先搭建好之后呢,我们就来做第1个例子,编程的第1个例子永远是hello world的,下面呢,我们就来做hello world的例子. 实现hello的例子步骤如下. 创建项目,启动Android Studio工具,新建一个项目,在New Project对话框中Empty Compose Activity,如图所示. 然后点击下一步打开对话框,如图所

  • 使用Jetpack Compose实现翻转卡片效果流程详解

    目录 介绍 执行 ML Kit银行卡识别 输出 结论 如何使用 Jetpack Compose 创建翻转卡片效果 介绍 在电子商务和银行应用程序中输入卡信息是很常见的情况.我认为让用户更轻松地处理这种情况并创建更吸引眼球的 UI 将很有用.大多数应用程序/网站都喜欢它. 执行 在开发阶段,您需要做的是打开一个 Android 项目并实施 Compose 库. 如果我们继续编码,我们可以检查以下 Compose 代码. 您可以根据上面的设计在屏幕上创建您的卡片. @Composable fun A

  • Jetpack Compose图片组件使用实例详细讲解

    目录 概述 示例解析 1.Icon图标组件 2.Image图片组件 总结 概述 在Compose中,图片组件主要有两种,分别是显示图标的Icon组件和显示图片的Image组件,当我们显示一系列的小图标的时候,我们可以使用Icon组件,当显示图片时,我们就用专用的Image组件.在Android传统的View中,我们显示图片和图标都是使用ImageView.我个人比较喜欢Compose的这种分开的方式,增加了代码的可读性. 示例解析 1.Icon图标组件 Icon组件用于展示一系列的小图标,它支持

  • Jetpack Compose常用组件详细介绍

    目录 1. Text 2. Image 3. LazyColumn 1. Text 日常最常用的应该就是显示文字,所以有必要说一下Text控件.首先源码如下: @Composable fun Text( text: String, modifier: Modifier = Modifier, color: Color = Color.Unspecified, fontSize: TextUnit = TextUnit.Unspecified, fontStyle: FontStyle? = nu

  • Android Jetpack组件Navigation导航组件的基本使用

    目录 1.Navigation 基本概念 2.Navigation 使用入门 2.1 添加Navigation依赖 2.2 创建导航图 2.3 导航图中添加目的地Fragment 2.4 Activity添加 NavHost 2.5 LoginFragment 代码编写 2.6 welcomeFragment 代码编写 总结 本篇主要介绍一下 Android Jetpack 组件 Navigation 导航组件的 基本使用 当看到 Navigation单词的时候 应该就大概知道 这是一个关于导航

  • 微信小程序 基础组件与导航组件详细介绍

    微信小程序 基础组件与导航组件详解: 1.基础组件 1.1 图标 icon 1.2 文本 text 1.3 进度条 progress 2.导航组件(navigator)  1.基础组件    1.1 图标 icon (1)总结 (2) 案例 效果截图 page.wxml <view class="type-group"> <block wx:for="{{iconType}}"> <icon type="{{item}}&qu

  • Jetpack Compose布局的使用详细介绍

    目录 一.标准布局组件 二.修饰符 三.滑动组件 1.ScrollableRow和ScrollableColumn 2.LazyRowFor和LazyColumnFor 一.标准布局组件 Compose中可以将多个控件元素组合使用,例如下面这样, @Composable fun WidgetGroup() { Text(text = "不为往事扰") Text(text = "余生只愿笑") } 但是我们会发现,如果仅仅是这样,两个文本控件会重叠在一起,类似于下面这

  • Android Jetpack Compose开发实用小技巧

    目录 前言 实用小技巧 如何移除View点击阴影 Text文本如何垂直居中 如何移除Button的点击阴影 Dialog宽度如何全屏 如何提升编码效率 前言 在Compose开发的过程中,我们会经常遇到一些看起来很简单却不知道如何处理的小问题,比如去除点击阴影.Dialog全屏等问题,本文记录了这些常见小问题的处理方式.如有更好方案欢迎大佬们交流探讨- 实用小技巧 如何移除View点击阴影 这里的View指的是除了Button系列的之外,如Button.TextButton等,也就是自身没有on

  • Android Jetpack Compose无限加载列表

    目录 前言 方法一: paging-compose 方法二:自定义实现 添加 LoadingIndicator 总结 前言 Android 中使用 ListView 或者 RecycleView 经常有滚动到底部自动 LoadMore 的需求,那么在 Compose 中该如何实现呢? 两种方法可供选择: 基于 paging-compose 自定义实现 方法一: paging-compose Jetpack 的 Paging 组件提供了对 Compose 的支持 dependencies { ..

  • 利用Jetpack Compose复刻游戏Flappy Bird

    目录 1.拆解游戏 2.复刻画面 ⅰ.布置远近景 ⅱ.摆放管道 ⅲ.放置小鸟 3.状态管理和架构 4.路面动起来 5.管道动起来 6.小鸟飞起来 7.碰撞和实时分值 8.结束分值和重新开始 9.最终效果 Flappy Bird是13年红极一时的小游戏,其简单有趣的玩法和变态的难度形成了强烈反差,引发全球玩家竞相把玩,欲罢不能!遂选择复刻这个小游戏,在实现的过程中向大家演示Compose工具包的UI组合.数据驱动等重要思想. 1.拆解游戏 不记得这个游戏或完全没玩过的朋友,可以点击下面的链接,体验

  • 利用Jetpack Compose实现主题切换功能

    目录 前言 color.kt Theme.kt 关于compositionLocalOf 完整代码 前言 新建的Compose项目默认的 Material 主题为我们提供了一些颜色,但对我这种花里胡哨的人来说根本不够呀. 所以系统提供的主题不能满足需求时候可以自己配置主题 compose 实现换肤很简单 之前xml方法可复杂了 通过LayoutInflater调用inflate方法加载XML布局,在inflate方法中有一个createViewFromTag,再根据LayoutInflater当

  • Jetpack Compose对比React Hooks API相似度

    目录 React Component vs Composable JSX vs DSL loop If statement key component Children Prop vs Children Composable Context vs Ambient(CompositionLocal) createContext : ambientOf Provider : Provider useContext : Ambient.current useState vs State useMemo

  • Jetpack Compose 分步指南教程详解

    目录 前言 可组合函数 显示简单文本 将样式应用于文本 使用 TextField 进行输入 在 Android Studio 中预览 预览参数 Column Scrollable Column Lazy Column Box Button Card Clickable Image Alert Dialog Material AppBar Material BottomNavigation Material Checkbox Material ProgressBar Material Slider

随机推荐