首页 > 其他分享 >Android开发 Jetpack_Compose_7 文字

Android开发 Jetpack_Compose_7 文字

时间:2023-10-13 11:55:06浏览次数:38  
标签:modifier Compose Jetpack sp text Text fontSize Android Modifier

前言

  此篇博客主要讲解Compose里的文字相关的UI功能。文本处理相关的内容与细节较多,此篇博客尽量涵盖完整,所以博客较长需要耐心看完。

  官网文档:https://developer.android.google.cn/jetpack/compose/text?hl=zh-cn

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,              //最大行数
    minLines: Int = 1,                          //最小行数
    onTextLayout: (TextLayoutResult) -> Unit = {},//文本变化回调
    style: TextStyle = LocalTextStyle.current   //字体风格
){}

显示资源里的文字

Text(text = stringResource(id = R.string.hello))

文字的大小单位

有两种单位分别是sp与em。

sp是与屏幕密度有关换算后的数值单位,特点是不会跟随屏幕分辨率大小的改变而改变,能保持文字大小的一致性。一般情况下是常用这个单位。

em是相对字体大小的数值单位,1.em等于100%, 2.em则是200%相对大小,这时候在需要适配大小屏设备的应用上使用。这样在大屏上也能跟随改变文字的相对大小。

代码

@Composable
fun FontSizeDemo() {
    Box(modifier = Modifier.fillMaxSize()) {
        Column(modifier = Modifier.align(Alignment.Center)) {
            Text(text = "以sp为单位的文字", fontSize = 20.sp)
            Text(text = "以em为单位的文字", fontSize = 2.em)
        }
    }
}

效果图

斜体

代码

Column(modifier = Modifier.align(Alignment.Center)){
    Text(text = "斜体", fontSize = 30.sp, fontStyle = FontStyle.Italic)
    Text(text = "正常", fontSize = 30.sp, fontStyle = FontStyle.Normal)
}

效果图

字体粗细

这可能要分辨率高的设备才能明显看出每阶字体粗细的区别

代码

Column(modifier = Modifier.align(Alignment.Center)){
    Text(text = "细", fontSize = 30.sp, fontWeight = FontWeight.Thin)
    Text(text = "较细", fontSize = 30.sp, fontWeight = FontWeight.ExtraLight)
    Text(text = "轻微细", fontSize = 30.sp, fontWeight = FontWeight.Light)
    Text(text = "正常", fontSize = 30.sp, fontWeight = FontWeight.Normal)
    Text(text = "中", fontSize = 30.sp, fontWeight = FontWeight.Medium)
    Text(text = "半粗", fontSize = 30.sp, fontWeight = FontWeight.SemiBold)
    Text(text = "粗", fontSize = 30.sp, fontWeight = FontWeight.Bold)
    Text(text = "大号粗体", fontSize = 30.sp, fontWeight = FontWeight.ExtraBold)
    Text(text = "黑体", fontSize = 30.sp, fontWeight = FontWeight.Black)
}

效果图

设置字体

首先需要搞个字体,这里推荐百度搜索阿里矢量图,在里面找到字体库(全是免费开源),选择一个下载,如下图:

在Android studio创建字体目录

选择font文件夹,然后ok创建

将下载完成的字体且后缀名是.ttf的文件放到font文件夹中

代码

系统会自带一些字体,我们可以直接使用,但是只支持英文

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContent {
        Box(modifier = Modifier.fillMaxSize()) {
            Column(modifier = Modifier.align(Alignment.Center)) {
                Text(
                    text = "默认字体效果Default",
                    fontSize = 30.sp,
                    fontFamily = FontFamily.Default
                )
                //无衬线
                Text(
                    text = "无衬线SansSerif",
                    fontSize = 30.sp,
                    fontFamily = FontFamily.SansSerif
                )
                //衬线体,这个字体不支持中文,想看效果需要英文
                Text(text = "衬线体Serif", fontSize = 30.sp, fontFamily = FontFamily.Serif)
                //等宽字体,这个字体不支持中文,想看效果需要英文
                Text(
                    text = "等宽字体Monospace",
                    fontSize = 30.sp,
                    fontFamily = FontFamily.Monospace
                )
                //手写体Cursive,这个字体不支持中文,想看效果需要英文
                Text(text = "手写体Cursive", fontSize = 30.sp, fontFamily = FontFamily.Cursive)
                //添加我们下载的阿里的字体,此外这里的weight与style属性是用来设置字体粗细与斜体的,这个可能需要字体库本身支持这些设置
                Text(
                    text = "阿里方圆体字体效果",
                    fontSize = 30.sp,
                    fontFamily = FontFamily(
                        Font(
                            R.font.alimama_fang_yuan_tivf_thin,
                            weight = FontWeight.Normal,
                            style = FontStyle.Normal
                        )
                    )
                )
            }
        }
    }
}

效果图

字体间距

代码

Column(modifier = Modifier.align(Alignment.Center)) {
    Text(
        text = "文字间距测试1",
        fontSize = 30.sp,
        letterSpacing = 5.sp
    )
    Text(
        text = "文字间距测试2",
        fontSize = 30.sp,
        letterSpacing = 20.sp
    )
}

效果图

 

下划线与中划线

代码

Column(modifier = Modifier.align(Alignment.Center)) {
    Text(
        text = "下划线效果",
        fontSize = 30.sp,
        textDecoration = TextDecoration.Underline
    )
    Text(
        text = "中划线效果",
        fontSize = 30.sp,
        textDecoration = TextDecoration.LineThrough                    )
}

效果图

字体对齐方向

代码

Column(modifier = Modifier.align(Alignment.Center)) {
    Text(
        text = "左",
        color = Color.White,
        fontSize = 14.sp,
        textAlign = TextAlign.Start,
        //这里设置一个背景,让文字对齐方向有参照物
        modifier = Modifier.padding(top = 20.dp).size(100.dp).background(color = Color.DarkGray)
    )
    Text(
        text = "中",
        color = Color.White,
        fontSize = 14.sp,
        textAlign = TextAlign.Center,
        modifier = Modifier.padding(top = 20.dp).size(100.dp).background(color = Color.DarkGray)
    )
    Text(
        text = "右",
        color = Color.White,
        fontSize = 14.sp,
        textAlign = TextAlign.End,
        modifier = Modifier.padding(top = 20.dp).size(100.dp).background(color = Color.DarkGray)
    )
    //什么都没设置的效果,作为下面TextAlign.Justify左右对齐效果的参照物。
    Text(
        text = "Stretch lines of text that end with a soft line break to fill the width of the container.Lines that end with hard line breaks are aligned towards the Start edge.",
        color = Color.White,
        fontSize = 14.sp,
        modifier = Modifier.padding(top = 20.dp).size(160.dp).background(color = Color.DarkGray)
    )
    //设置后TextAlign.Justify 左右对齐后的效果。注意!这个属性对英文有有意义所以下面使用英文来演示,对中文没什么意义,因为中文文字宽度都一样,没有英文单词有长度上的变化。
    Text(
        text = "Stretch lines of text that end with a soft line break to fill the width of the container.Lines that end with hard line breaks are aligned towards the Start edge.",
        color = Color.White,
        fontSize = 14.sp,
        textAlign = TextAlign.Justify,
        modifier = Modifier.padding(top = 20.dp).size(160.dp).background(color = Color.DarkGray)
    )
}

效果图

行间距

代码

Column(modifier = Modifier.align(Alignment.Center)) {
    Text(
        text = "行间距测试一,ABCDEFGHWJKL",
        color = Color.White,
        fontSize = 20.sp,
        lineHeight = 10.sp,
        modifier = Modifier.padding(top = 20.dp).size(200.dp).background(color = Color.DarkGray)
    )
    Text(
        text = "行间距测试二,ABCDEFGHWJKL",
        color = Color.White,
        fontSize = 20.sp,
        lineHeight = 50.sp,
        modifier = Modifier.padding(top = 20.dp).size(200.dp).background(color = Color.DarkGray)
    )
}

效果图

文本内超出显示

代码

Column(modifier = Modifier.align(Alignment.Center)) {
    Text(
        text = "裁剪_Clip the overflowing text to fix its container.",
        color = Color.White,
        fontSize = 20.sp,
        overflow = TextOverflow.Clip,
        modifier = Modifier.padding(top = 20.dp).size(80.dp).background(color = Color.DarkGray)
    )
    Text(
        text = "省略_Use an ellipsis to indicate that the text has overflowed.",
        color = Color.White,
        fontSize = 20.sp,
        overflow = TextOverflow.Ellipsis,
        modifier = Modifier.padding(top = 20.dp).size(80.dp).background(color = Color.DarkGray)
    )
}

效果图

文本内容、参数、布局回调

每次文本变化后都会回调

代码

@Composable
fun TextLayout() {
    val count = remember { mutableStateOf(0) }
    val log = remember { mutableStateOf("") }
    //创建一个计数功能
    LaunchedEffect(true){
        while (isActive){
            count.value++
            delay(1000)
        }
    }
    Box(modifier = Modifier.fillMaxSize()) {
        Column(modifier = Modifier.align(Alignment.Center)) {
            Text(
                text = count.value.toString(),
                color = Color.Black,
                fontSize = 38.sp,
                onTextLayout = {
                    log.value = "文本内容 = ${it.layoutInput.text} \n ${it.toString()}"
                }
            )
            //这里实现一个Text,用来显示上面Text的变化日志
            Text(text = log.value, modifier = Modifier.padding(top = 30.dp))
        }
    }
}

效果图

文字组合拼接

这里的text = buildAnnotatedString,是另一个重载函数Text的参数(text: AnnotatedString),用于实现文本的拼接与单独的风格设置。这里会涉及到style的内容,这个会在下面讲解,这里只是先演示文字拼接的代码与效果。

代码

@Composable
fun BuildAnnotatedStringDemo() {
    Box(modifier = Modifier.fillMaxSize()) {
        Column(modifier = Modifier.align(Alignment.Center)) {
            Text(fontSize = 20.sp, text = buildAnnotatedString {
                append("拼接文字效果:\n")
                withStyle(style = SpanStyle(color = Color.Red, fontSize = 20.sp)) {
                    append("红")
                }
                withStyle(style = SpanStyle(color = Color.Yellow, fontSize = 30.sp)) {
                    append("黄")
                }
                withStyle(style = SpanStyle(color = Color.Blue, fontSize = 35.sp)) {
                    append("蓝")
                }
                append("\n----------分割线----------")
                //还能以下面嵌套的方式,进行文字的拼接组合
                withStyle(style = ParagraphStyle(lineHeight = 80.sp)) {
                    withStyle(style = SpanStyle(fontSize = 45.sp)) {
                        withStyle(style = SpanStyle(color = Color.Cyan)) {
                            append("青\n")
                        }
                        withStyle(style = SpanStyle(color = Color.Gray)) {
                            append("灰\n")
                        }
                        withStyle(style = SpanStyle(color = Color.Black)) {
                            append("黑\n")
                        }
                    }

                }
            })
        }
    }
}

效果图

文字组合拼接后独立点击

有时候会需求一行文字需要2个点击效果的情况,例如 <用户协议>与<隐私政策> 这种情况,点击用户协议与隐私政策分别需要2个不一样的点击回调。这里就可以使用文字组合拼接的独立点击功能

代码


@Composable
fun BuildAnnotatedStringDemo() {
    val context = LocalContext.current
    Box(modifier = Modifier.fillMaxSize()) {
        Column(modifier = Modifier.align(Alignment.Center)) {
            val annotatedText = buildAnnotatedString {
                pushStringAnnotation(tag = "userAgreement", annotation = "<用户协议>")
                withStyle(
                    style = SpanStyle(
                        fontSize = 20.sp,
                        color = Color.Blue,
                        fontWeight = FontWeight.Bold
                    )
                ) {
                    append("<用户协议>")
                }
                /*
                 * 这里的pop函数很重要,在每完成一段字符串注解后,都要使用pop进行记录,防止和下面新增的其他字符串注解混在一起
                 * 如果不设置就会出现下面的点击一次,就会返回2个字符串注解
                 */
                pop()
                append("与")
                pushStringAnnotation(tag = "privacyPolicy", annotation = "<隐私政策>")
                withStyle(
                    style = SpanStyle(
                        fontSize = 20.sp,
                        color = Color.Blue,
                        fontWeight = FontWeight.Bold
                    )
                ) {
                    append("<隐私政策>")
                }
                pop()
            }
            ClickableText(
                text = annotatedText,
                onClick = { offset ->
                    Log.e("zh", "offset = ${offset}: ")
                    annotatedText.getStringAnnotations(
                        tag = "userAgreement",
                        start = offset,
                        end = offset
                    ).firstOrNull()?.let { annotation ->
                        Toast.makeText(context, "点击 ${annotation.item}", Toast.LENGTH_SHORT)
                            .show()
                    }
                    annotatedText.getStringAnnotations(
                        tag = "privacyPolicy",
                        start = offset,
                        end = offset
                    ).firstOrNull()?.let { annotation ->
                        Toast.makeText(context, "点击 ${annotation.item}", Toast.LENGTH_SHORT)
                            .show()
                    }
                }
            )
        }
    }
}

效果图

style风格_作为通用文字风格的例子

这是一个相当重要的属性,它可以组合上面的全部文字配置,下面的例子创建了一个style作为通用的文字风格,可以添加到任意Text上作为通用风格,这样可以大大减少我们配置文字属性的冗余重复的代码。

代码

@Composable
fun TextStyleDemo() {
    val style = LocalTextStyle.current.merge(
        TextStyle(
            color = Color.Blue,
            fontSize = 30.sp,
            lineHeight = 10.sp,
            fontWeight = FontWeight.Bold,
            fontStyle = FontStyle.Normal,
            textAlign = TextAlign.Center,
            background = Color.Gray,
        )
    )
    Box(modifier = Modifier.fillMaxSize()) {
        Column(modifier = Modifier.align(Alignment.Center)) {
            Text(text = "文本1", style = style)
            Text(text = "文本2", style = style)
        }
    }
}

效果图

style风格_文字背景

上面的例子展示的都是上面已经说明过的属性,但是它可以完成更多的文字风格定制,从这里开始会讲解style特定的文字属性。

style风格的背景设置非常不一样,它并不是整个Text的背景颜色设置,而是根据文字占位的背景颜色

代码

@Composable
fun TextStyleDemo() {
    val style = LocalTextStyle.current.merge(
        TextStyle(
            background = Color.Gray //注意,这里的背景与下面的Text的背景是不同的
        )
    )
    Box(modifier = Modifier.fillMaxSize()) {
        Column(modifier = Modifier.align(Alignment.Center)) {
            Text(text = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", style = style, modifier = Modifier.size(100.dp).background(color = Color.Cyan))
        }
    }
}

效果图

 

style风格_设置文字在行距的位置

一共有4种样式,FirstLineTop、LastLineBottom、Both、None

代码

@Composable
fun TextStyleDemo() {
    val noneStyle = LocalTextStyle.current.merge(
        TextStyle(
            //这里增加行距,让lineHeightStyle的属性效果更明显
            lineHeight = 3.em,
            /*
                platformStyle这个属性,根据官网文档说是为了给第一行文字顶部和最后一行文字底部的字体指标添加额外的内边距。
                这个属性会影响下面的lineHeightStyle行距调整,所以需要设置为false关闭。
             */
            platformStyle = PlatformTextStyle(
                includeFontPadding = false
            ),
            lineHeightStyle = LineHeightStyle(
                alignment = LineHeightStyle.Alignment.Center,
                trim = LineHeightStyle.Trim.None
            ),
            //加个背景,可以看的更清楚行距的区别
            background = Color.Gray
        )
    )
    val bothStyle = LocalTextStyle.current.merge(
        TextStyle(lineHeight = 3.em, platformStyle = PlatformTextStyle(includeFontPadding = false),
            lineHeightStyle = LineHeightStyle(alignment = LineHeightStyle.Alignment.Center, trim = LineHeightStyle.Trim.Both),
            background = Color.Gray
        )
    )
    val lastLineBottomStyle = LocalTextStyle.current.merge(
        TextStyle(lineHeight = 3.em, platformStyle = PlatformTextStyle(includeFontPadding = false),
            lineHeightStyle = LineHeightStyle(alignment = LineHeightStyle.Alignment.Center, trim = LineHeightStyle.Trim.LastLineBottom),
            background = Color.Gray
        )
    )
    val firstLineTopStyle = LocalTextStyle.current.merge(
        TextStyle(lineHeight = 3.em, platformStyle = PlatformTextStyle(includeFontPadding = false),
            lineHeightStyle = LineHeightStyle(alignment = LineHeightStyle.Alignment.Center, trim = LineHeightStyle.Trim.FirstLineTop),
            background = Color.Gray
        )
    )
    Box(modifier = Modifier.fillMaxSize()) {
        Column(modifier = Modifier.align(Alignment.Center)) {
            Text(text = "文字在行距中间\nLineHeightStyle.Trim.None\nLineHeightStyle.Trim.None", style = noneStyle)
            Text(text = "第一行在行距上面,最后一行在行距下面,中间行在中间\nLineHeightStyle.Trim.Both\nLineHeightStyle.Trim.Both", style = bothStyle, modifier = Modifier.padding(top = 20.dp))
            Text(text = "文字在行距下面\nLineHeightStyle.Trim.LastLineBottom\nLineHeightStyle.Trim.LastLineBottom", style = lastLineBottomStyle, modifier = Modifier.padding(top = 20.dp))
            Text(text = "第一行在行距上面,其他行在中间\nLineHeightStyle.Trim.FirstLineTop\nLineHeightStyle.Trim.FirstLineTop", style = firstLineTopStyle, modifier = Modifier.padding(top = 20.dp))
        }
    }
}

效果图

style风格_文字阴影

代码

@Composable
fun TextStyleDemo() {
    val shadowStyle1 = LocalTextStyle.current.merge(
        TextStyle(
            //offset是阴影的范围,范围越大阴影越大
            //blurRadius是阴影的模糊半径,数值越大阴影越模糊,越小而越清晰
            shadow = Shadow(color = Color.Blue, offset = Offset(2f, 2f), blurRadius = 1f)
        )
    )
    val shadowStyle2 = LocalTextStyle.current.merge(
        TextStyle(
            shadow = Shadow(color = Color.Blue, offset = Offset(5f, 5.0f), blurRadius = 10f)
        )
    )
    Box(modifier = Modifier.fillMaxSize()) {
        Column(modifier = Modifier.align(Alignment.Center)) {
            Text(text = "文字阴影", fontSize = 20.sp, style = shadowStyle1)
            Text(text = "文字阴影", fontSize = 20.sp, style = shadowStyle2)
        }
    }
}

效果图

选中文字

 

TextField 输入框

 

 

 

End

标签:modifier,Compose,Jetpack,sp,text,Text,fontSize,Android,Modifier
From: https://www.cnblogs.com/guanxinjing/p/17023101.html

相关文章

  • Android sdkmanager not found. Update to the latest Android SDK and ensure that t
     (base)cloud@Robotbin%flutterdoctor--android-licensesAndroidsdkmanagernotfound.UpdatetothelatestAndroidSDKandensurethatthecmdline-toolsareinstalledtoresolvethis.     ......
  • Android 外置存储卡无法使用FileProvider问题
    解决办法:<?xmlversion="1.0"encoding="utf-8"?><paths><external-files-pathname="my_images"path="."/></paths>修改为<?xmlversion="1.0"encoding="utf-8&......
  • 实时美妆魅力尽显:探索相芯轻美妆SDK功能及集成方法(Android)
    随着人工智能技术的不断发展,相芯SDK的轻美妆功能为用户带来了一种全新的美妆体验。轻美妆是妆容和美妆的结合,使用比较轻薄的妆效使轻美妆效果更佳。这一功能集成了多项先进技术,通过人脸识别、图像处理和分割等技术,实现了实时美妆效果的展示和应用。本文将深入介绍相芯SDK轻美妆功能......
  • Android 通过bin二进制程序调用jar原理
    最近在研究monkey测试,发现monkey测试的代码都是JAVA编写的,通过编译生成jar包,而我们在执行测试时直接执行/system/bin/monkey这个二进制程序的,那么它是如何能调起java程序的呢?先来看看monkey二进程程序的生成.development\cmds\monkey\Android.mkLOCAL_PATH:=$(callmy-dir)i......
  • Android 设置任意View的背景为圆形或圆角
    原文地址:Android设置任意View的背景为圆形或圆角-Stars-One的杂货小窝我的需求主要还是在SurfaceView需要设置为圆形背景,在网上找了下,发现一个可行方法,做个记录importandroid.graphics.Outline;importandroid.graphics.Rect;importandroid.view.View;importandr......
  • 安装 Android x86 并开启 arm 兼容
    安装Androidx86并开启arm兼容尝试了各种安卓模拟器,要么不能设置代理(BlueStacks),要么/system目录没办法设置。获取Androidx86这里使用的是Android7版本,在本次操作时houdini对Android8/Android9的版本支持有限。从Android-x86旧版本获取7.1的Android-x86_......
  • 金九银十Android面试该怎么有效的回答,看完这篇文章就懂了
    今年的严寒使得许多职场人的求职时间变长,以往火热的金三银四不再,金九银十九承载着广大程序员的希望。但是在这个特殊情况下,竞争压力也会增大,各大企业对于求职者的要求也随之增高。很多小伙伴都面临着这样的情况:千辛万苦拿到面试机会,却因各种原因翻车。“在面试的时候不能将自己的真......
  • Android入门教程 | ImageView 图片显示
    为了让App界面更美观生动,我们可以放上图片。显示图片是“刚需”。不论是书籍,报纸,网站,都有显示图片的需求。毕竟“无图无真相”。在Android应用开发中,我们通常使用ImageView来显示图片。ImageView的主要属性ImageView的使用ImageView经常用来显示图片。例如直接显示drawable里......
  • 调用Android设备中已经安装的软件打开各种类型的指定文件
    最近因项目需求需要在android应用程序中下载一些附件,并打开这些附件,比如音视频视频以及图片这些。开始还好,文件类型不是很多,但是后来需求又加上doc/xls/ppt等,后来又兼容了pdf。这时候已经被需求改的烦不胜烦,觉得有必要针对打开本地文件做一个通用的封装了,判断File的类型,然后用指......
  • 视频直播源码,AndroidStudio登录页面的切换
    视频直播源码,AndroidStudio登录页面的切换xml代码 <?xmlversion="1.0"encoding="utf-8"?><RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android"  xmlns:app="http://schemas.android.com/apk/res-auto"  ......