详解Jetpack Compose的标准布局

news2024/12/23 13:30:02

前言

Compose是一个声明式UI系统,其中,我们用一组函数来声明UI,并且一个Compose函数可以嵌套另一个Compose函数,并以树的结构来构造所需要的UI。

在Compose中,我们称该树为UI 图,当UI需要改变的时候会刷新此UI图,比如Compose函数中有 if 语句,那么Kotlin编译器就需要注意了。

在Compose的世界中,没有类的概念,全都是函数,并且都是顶层函数,因此不会有任何继承和层次机构问题。

Jetpack Compose也是第一个使用Kotlin正在开发中的大型项目,因此Android团队正在探索Kotlin API指南的新世界,以创建一组特定于Compose API的指南。

在这里为大家讲解一下Jetpack Compose中的Column、LazyColumn、Row、LazyRow、Box等,这些标准布局的使用。

Column

Column是垂直布局,让子元素以垂直的方式排序。

简单的例子

代码:

@Preview()
@Composable
fun MyColumn() {
    val spacerModifier = Modifier
        .size(100.dp, 50.dp)
        .padding(5.dp)
        .background(color = Color(0xFF96FF9A))

    val columnModifier = Modifier
        .background(color = Color.White)
        .padding(10.dp)
        .border(width = 1.dp, color = Color.Black, shape = RoundedCornerShape(5.dp))

    Column(modifier = columnModifier) {
        for (i in 0..2){
            Spacer(modifier = spacerModifier)
        }
    }
} 

效果图:

 

Column 的对齐方式

关键是 horizontalAlignment 与 verticalArrangement

代码:

@Preview(widthDp = 100, heightDp = 200)
@Composable
fun MyColumn() {
    val textModifier = Modifier
        .size(100.dp, 50.dp)
        .padding(5.dp)
        .background(color = Color(0xFF3F51B5))

    Column(
        //让子元素件水平对齐
        //Alignment.CenterHorizontally 为居中对齐,还能使用Start靠左对齐,End靠右对齐
        horizontalAlignment = Alignment.CenterHorizontally,
        //让子元素垂直对齐
        verticalArrangement = Arrangement.Center,
        modifier = Modifier
            .size(150.dp, 300.dp)
            .border(1.dp, color = Color.Black, shape = RectangleShape)
            .background(color = Color.White)
            .padding(10.dp)
    ) {
        for (i in 0..2) {
            Text(
                text = "$i",
                color = Color.White,
                textAlign = TextAlign.Center,
                modifier = textModifier
            )
        }
    }
} 

效果图:

 

 其他的垂直对齐方式

在官方文档里有一些其他的对齐方式效果,但是实际代码中已经没有了,可能那部分Api是实验性代码,这里只举例存在的。

指定间隔对齐

关键是spacedBy方法。说实话,这个方法提供的有点多余.. padding完全可以满足间隔的需求

代码:

Column(
    horizontalAlignment = Alignment.CenterHorizontally,
    //让子元素垂直对齐   Alignment.Top  Alignment.CenterVertically  Alignment.Bottom
    verticalArrangement = Arrangement.spacedBy(5.dp, alignment = Alignment.CenterVertically),
    modifier = columnModifier
) {
    for (i in 0..2) {
        Text(
            text = "$i",
            color = Color.White,
            textAlign = TextAlign.Center,
            modifier = textModifier.background(color = Color(0xFF004564))
        )
    }
}

 

效果图:

Column的滚动

代码:

@Preview(widthDp = 100, heightDp = 200)
@Composable
fun MyColumnScroll() {
    val textModifier = Modifier
        .size(100.dp, 50.dp)
        .padding(5.dp)
        .background(color = Color(0xFF3F51B5))

    Column(
        modifier = Modifier
            .fillMaxSize()
            .background(color = Color.White)
            .verticalScroll(rememberScrollState())
    ) {
        for (i in 0..50) {
            Text(
                text = "$i",
                color = Color.White,
                textAlign = TextAlign.Center,
                modifier = textModifier
            )
        }
    }
} 

 效果图:

Row

Row是横向布局,让子元素以水平的方式排序

简单的例子

代码:

@Preview(widthDp = 350, heightDp = 100)
@Composable
fun MyRow() {
    val textModifier = Modifier
        .size(100.dp, 50.dp)
        .padding(5.dp)
        .background(color = Color(0xFF3F51B5))

    Row(
        modifier = Modifier
            .fillMaxSize()
            .border(1.dp, color = Color.Black, shape = RectangleShape)
            .background(color = Color.White)
            .padding(10.dp)
    ) {
        for (i in 0..2) {
            Text(
                text = "$i",
                color = Color.White,
                textAlign = TextAlign.Center,
                modifier = textModifier
            )
        }
    }
} 

 

效果图:

Row 的对齐方式

代码:

@Preview(widthDp = 350, heightDp = 100)
@Composable
fun MyRow() {
    val textModifier = Modifier
        .size(100.dp, 50.dp)
        .background(color = Color(0xFF3F51B5))

    Row(
        //水平对齐
        horizontalArrangement = Arrangement.SpaceBetween,
        //垂直对齐
        verticalAlignment = Alignment.CenterVertically,
        modifier = Modifier
            .fillMaxSize()
            .border(1.dp, color = Color.Black, shape = RectangleShape)
            .background(color = Color.White)
            .padding(5.dp)
    ) {
        for (i in 0..2) {
            Text(
                text = "$i",
                color = Color.White,
                textAlign = TextAlign.Center,
                modifier = textModifier
            )
        }
    }
} 

效果图:

其他对齐方式

LazyColumn 与 LazyRow

LazyColumn 与 LazyRow的使用其实差不多,代码上不同的地方已经在上面展示了。 所以这里归为一类进行代码演示。

   首先你要知道LazyColumn 与 Column 的区别是什么? 区别是 Column 一般是静态的元素数量的列表,而LazyColumn 一般是动态的元素数量的列表(比如可以上拉加载更多的情况)。 当然并不是说Column 无法通过状态管理改造成动态的,只是没必要,因为LazyColumn可以满足需求。  最后你还需要知道LazyColumn的使用必须配合item与items使用。

LazyRow同上描述,不在重复啰嗦。

代码:

@Preview()
@Composable
fun MyColumnScroll() {
    val textModifier = Modifier
        .fillMaxWidth()
        .padding(5.dp)
        .background(color = Color(0xFF3F51B5))

    val list = remember {
        mutableStateListOf<String>("1", "2", "3", "4", "5", "6", "7", "8")
    }

    LazyColumn(
        modifier = Modifier
            .fillMaxSize()
            .background(color = Color.White)
    ) {

        //注意这里使用的是item
        item {
            TextButton(
                onClick = { list.add("${list.size + 1}") },
                modifier = Modifier
                    .padding(5.dp)
                    .fillMaxWidth()
                    .background(color = Color(0xFF3F51B5))

            ) {
                Text(
                    text = "添加",
                    color = Color.White,
                    fontSize = 18.sp,
                    textAlign = TextAlign.Center,
                    modifier = textModifier
                )
            }
        }

        //注意这里使用的是items
        items(list.size) { index ->
            Text(
                text = "${list[index]}",
                color = Color.White,
                fontSize = 18.sp,
                textAlign = TextAlign.Center,
                modifier = textModifier
            )
        }

        item {
            TextButton(
                onClick = { list.removeRange(list.size - 1, list.size) },
                modifier = Modifier
                    .padding(5.dp)
                    .fillMaxWidth()
                    .background(color = Color(0xFF3F51B5))

            ) {
                Text(
                    text = "删除",
                    color = Color.White,
                    fontSize = 18.sp,
                    textAlign = TextAlign.Center,
                    modifier = textModifier
                )
            }
        }
    }
} 

 效果图:

监听滚动位置 

rememberLazyListState是关键

@Preview()
@Composable
fun MyColumnScroll() {
    val textModifier = Modifier
        .fillMaxWidth()
        .padding(5.dp)
        .background(color = Color(0xFF3F51B5))

    val scrollState = rememberLazyListState()
    val scope = rememberCoroutineScope()

    //scrollState.isScrollInProgress判断是否正在滚动
    if (scrollState.isScrollInProgress){
        DisposableEffect(Unit){
            Log.e("zh", "开始滚动")
            onDispose {
                Log.e("zh", "停止滚动")
                if (scrollState.firstVisibleItemIndex == 0){
                    Toast.makeText(this@MainActivity, "已经到顶了", Toast.LENGTH_SHORT).show()
                    Log.e("zh", "已经到顶了")
                }
                if (scrollState.firstVisibleItemIndex + scrollState.layoutInfo.visibleItemsInfo.size == scrollState.layoutInfo.totalItemsCount){
                    Toast.makeText(this@MainActivity, "已经到底了", Toast.LENGTH_SHORT).show()
                    Log.e("zh", "已经到底了")
                }
            }
        }
    }

    Column {
        Text(
            text = "当前滚动位置 = ${scrollState.firstVisibleItemIndex}",
            fontSize = 18.sp,
            color = Color.White,
            modifier = Modifier
                .background(Color.Black)
                .fillMaxWidth()
        )
        Text(
            text = "回到顶上",
            fontSize = 18.sp,
            color = Color.White,
            modifier = Modifier
                .background(Color.Black)
                .fillMaxWidth()
                .clickable {
                    scope.launch {
                        scrollState.animateScrollToItem(0)
                    }
                }
        )
        LazyColumn(
            state = scrollState,
            modifier = Modifier
                .fillMaxSize()
                .background(color = Color.White)
        ) {
            items(list.size) { index ->
                Text(
                    text = "${list[index]}",
                    color = Color.White,
                    fontSize = 18.sp,
                    textAlign = TextAlign.Center,
                    modifier = textModifier
                )
            }
        }
    }
} 

效果图:

Box

Box其实就是相对布局的概念

Box上的属性

代码:

@Preview()
@Composable
fun MyBox() {
    Box(
        //Alignment.TopStart ; Alignment.TopCenter ; Alignment.TopEnd ;
        //Alignment.CenterStart ; Alignment.Center Alignment.CenterEnd ;
        //Alignment.BottomStart ; Alignment.BottomCenter ; Alignment.BottomEnd
        contentAlignment = Alignment.BottomCenter,
        modifier = Modifier
            .background(Color.Gray)
            .fillMaxHeight()
            .fillMaxWidth()
    ) {
        Text(text = "Text", fontSize = 50.sp, color = Color.White)
    }
} 

效果图:

 

子元素上的属性

@Preview()
@Composable
fun MyBox() {
    Box(
        modifier = Modifier
            .background(Color.Gray)
            .fillMaxHeight()
            .fillMaxWidth()
    ) {
        Text(
            text = "TopStart",
            fontSize = 18.sp,
            color = Color.White,
            modifier = Modifier
                .background(Color.Black)
                .align(Alignment.TopStart)
        )
        Text(
            text = "TopCenter",
            fontSize = 18.sp,
            color = Color.White,
            modifier = Modifier
                .background(Color.Black)
                .align(Alignment.TopCenter)
        )
        Text(
            text = "TopEnd",
            fontSize = 18.sp,
            color = Color.White,
            modifier = Modifier
                .background(Color.Black)
                .align(Alignment.TopEnd)
        )
        Text(
            text = "CenterStart",
            fontSize = 18.sp,
            color = Color.White,
            modifier = Modifier
                .background(Color.Black)
                .align(Alignment.CenterStart)
        )
        Text(
            text = "Center",
            fontSize = 18.sp,
            color = Color.White,
            modifier = Modifier
                .background(Color.Black)
                .align(Alignment.Center)
        )
        Text(
            text = "CenterEnd",
            fontSize = 18.sp,
            color = Color.White,
            modifier = Modifier
                .background(Color.Black)
                .align(Alignment.CenterEnd)
        )
        Text(
            text = "BottomStart",
            fontSize = 18.sp,
            color = Color.White,
            modifier = Modifier
                .background(Color.Black)
                .align(Alignment.BottomStart)
        )
        Text(
            text = "BottomCenter",
            fontSize = 18.sp,
            color = Color.White,
            modifier = Modifier
                .background(Color.Black)
                .align(Alignment.BottomCenter)
        )
        Text(
            text = "BottomEnd",
            fontSize = 18.sp,
            color = Color.White,
            modifier = Modifier
                .background(Color.Black)
                .align(Alignment.BottomEnd)
        )
    }
} 

效果图:

LazyVerticalGrid 与 LazyHorizontalGrid 网格布局

LazyVerticalGrid是竖向网格布局的,实现效果请查看下列代码。而LazyHorizontalGrid是横向网格布局的,只是滚动方向上的不同可以完全参考下面的LazyVerticalGrid。就不在重复举例了

设置目标列数

下面的代码中使用GridCells.Fixed(5)设置了5列

@Preview(widthDp = 1280, heightDp = 720)
@Composable
fun textList() {
    LazyVerticalGrid(columns = GridCells.Fixed(5)) {
        items(100) { index ->
            Text(
                text = index.toString(),
                fontSize = 30.sp,
                textAlign = TextAlign.Center,
                color = Color.Black,
                modifier = Modifier
                    .padding(10.dp)
                    .fillMaxSize()
                    .background(color = Color.LightGray)
            )
        }
    }
}

效果图

根据Item大小自动变化列数

下面代码中使用了GridCells.Adaptive(minSize = 400.dp),将item最小宽度设置成400dp

@Preview(widthDp = 1280, heightDp = 720)
@Composable
fun imageList() {
    val imageList =  remember {
        mutableStateListOf<Int>()
    }
    imageList.add(R.mipmap.ic_bg_1)
    imageList.add(R.mipmap.ic_bg_2)
    imageList.add(R.mipmap.ic_bg_3)
    imageList.add(R.mipmap.ic_bg_3)
    imageList.add(R.mipmap.ic_bg_1)
    imageList.add(R.mipmap.ic_bg_2)
    LazyVerticalGrid(columns = GridCells.Adaptive(minSize = 400.dp)) {
        items(imageList.size) { index ->
            Image(painter = painterResource(id = imageList[index]), contentDescription = null)
        }
    }
}

效果图

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/542774.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

UML类图与设计模式/原则

目录 类之间的关系依赖泛化(继承)实现关联聚合组合 设计模式的七大原则设计模式单例工厂模式原型模式&#xff08;深/浅拷贝&#xff09;建造者模式适配器模式桥接模式装饰者模式组合模式外观模式享元模式代理模式模板方法模式命令模式访问者模式迭代器模式观察者模式中介者模式…

chatgpt赋能Python-python3_8_5安装后怎么打开

Python3.8.5安装后怎么打开&#xff1a;简易步骤指南 Python是一种高级编程语言&#xff0c;被广泛用于数据分析、机器学习、自动化、网络编程等多个方面。Python语言优雅简洁&#xff0c;易于上手&#xff0c;是编程初学者的最佳入门语言之一。本文将介绍Python3.8.5版本的安…

C++ 红黑树(更新中)

前言 上篇博客学习了平衡二叉搜索树(AVLTree)&#xff0c;了解到AVL树的性质&#xff0c;二叉搜索树因为其独特的结构&#xff0c;查找、插入和删除在平均和最坏情况下都是O(logn)。AVL树的效率就是高在这个地方。 但是在AVL树中插入或者删除结点&#xff0c;使得高度差的绝对…

学系统集成项目管理工程师(中项)系列22c_信息化知识(下)

1. 新一代信息技术对产业的推动 1.1. 加快建设宽带、泛在、融合、安全的信息网络基础设施&#xff0c;推动新一代移动通信、下一代互联网核心设备和智能终端的研发及产业化&#xff0c;加快推进三网融合&#xff0c;促进物联网、云计算的研发和示范应用 1.2. 大数据 1.2.1. …

申请GPT-4插件,等待GPT-4插件候补全过程

前言 GPT4相信大家都知道它的升级是带来更多惊喜的&#xff0c;目前GPT4已经推出了网页和插件功能&#xff0c;这些插件是专门为语言模型设计的工具。插件可以帮助 ChatGPT 访问最新信息、运行计算或使用第三方服务。写文记录一下&#xff0c;如果你现正好有需要GPT-4 插件的需…

基于springboot就业信息管理系统

开发技术与环境配置 以Java语言为开发工具&#xff0c;利用了当前先进的springboot框架&#xff0c;以MyEclipse10为系统开发工具&#xff0c;MySQL为后台数据库&#xff0c;开发的一个就业信息管理系统。 SpringBoot框架 SpringBoot是一个全新开源的轻量级框架。基于Spring…

chatgpt赋能Python-python3_8怎么打开

Python 3.8&#xff1a;如何下载和打开 Python 3.8是一种高级编程语言&#xff0c;被广泛应用于人工智能、数据分析和网络编程等领域。本文将介绍如何下载和打开Python 3.8以及其优点和用途。 下载Python 3.8 Python 3.8的下载地址为官方网站。根据不同操作系统的需求&#…

系统清理优化工具:CCleaner

哈喽&#xff0c;大家好。今天带各位小伙伴们学习一款系统清理优化工具——CCleaner。 CCleaner是一款系统优化和隐私保护工具。它可以用来清除Windows系统不再使用的垃圾文件&#xff0c;以腾出更多硬盘空间。也可以清除使用者的上网记录。它的体积小&#xff0c;运行速度快&…

java+springboot高校校友校园信息管理系统

本高校校友信息管理系统使用Web开发&#xff0c;运行在Internet环境之上&#xff0c;系统的后台编程语言使用JAVA&#xff0c;数据库使用MySQL。完成了两个用户角色的功能&#xff0c;管理员管理所有信息&#xff0c;前台学生用户登录后查看公告&#xff0c;在线捐赠申请&#…

docker是怎么决定容器内容存储到哪个目录的?(存储驱动决定的)(乱七八糟的)

文章目录 docker是怎么决定容器内容存储到哪个目录的&#xff1f;docker对我/var这个目录有没有什么要求&#xff0c;比如要求它的文件系统是指定的类型如果我Docker的默认存储驱动是overlay2&#xff0c;但是我/var目录的文件系统不是overlay2&#xff0c;这没影响吗&#xff…

chatgpt赋能Python-python3_7_1如何使用

Python 3.7.1使用指南 Python自从出现以来&#xff0c;已经成为了一个非常流行的编程语言&#xff0c;每年都会更新版本以满足不断变化的市场需求。其中最新版本是Python 3.7.1&#xff0c;它与其前身相比提供了许多改进和新功能&#xff0c;同时也解决了一些已知的问题。本文…

MobileNetV3详解及在pytorch下基于CIFAR10数据集的实现

1 MobileNetV3介绍 MobileNetV3 是由 google 团队在 2019 年提出的轻量化网络模型&#xff0c;传统的卷积神经网络&#xff0c;内容需求大&#xff0c;运算量大&#xff0c;无法再移动设备以及嵌入式设备上运行&#xff0c;为了解决这一问题&#xff0c;MobileNet网络应运而生。…

chatgpt赋能Python-python3_8下载numpy

Python3.8下载numpy&#xff1a;安装步骤与常见问题解决方案 Python3.8是最新版的Python编程语言&#xff0c;它提供了丰富的库和框架支持&#xff0c;包括科学计算库numpy。然而&#xff0c;有些用户可能会在安装numpy时遇到一些麻烦&#xff0c;本文将教你如何下载numpy&…

海康机器视觉工业相机客户端MVS-常用功能CCM

什么是CCM? CCM是一种功能。 CCM矩阵是通过对每一个RGB分量乘以一个校正矩阵来实现色彩校正。当图像经过白平衡处理后,图像整 体会显得比较黯淡,同时多种颜色可能存在不同程度地偏离其标准值。此时需要对图像的色彩乘以校正 矩阵来修正各颜色至其标准值,使图像的整体色彩更…

【智能算法1】模拟退火算法_Python实现

一、模拟退火算法&#xff08;SA&#xff09; 1.1 固体退火的原理 加热使得固体融化&#xff0c;然后缓慢地降低温度&#xff0c;以此来让固体内部的粒子排布更加均匀。 分为四个阶段&#xff1a; 升温阶段、降温阶段、等温阶段、达到目标温度退火完成 等温阶段就是在塑造…

chatgpt赋能Python-python3_8安装scrapy

Python3.8 安装 Scrapy 如果你是 Python 开发者&#xff0c;你可能已经听说过 Scrapy&#xff1a;一个开源框架&#xff0c;用于快速高效地抓取和提取网页数据。在本篇文章中&#xff0c;我们将介绍如何在 Python3.8 环境下安装 Scrapy&#xff0c;并解释该过程的每一个步骤。…

chatgpt赋能Python-python3_6怎么算

Python 3&6怎么算&#xff1f;—— Python版本的比较 Python是一款广泛使用的高级编程语言&#xff0c;已经有好几个版本了&#xff0c;其中比较常用的是Python 3和Python 2.7。近年来&#xff0c;Python 3越来越受欢迎&#xff0c;那么Python 3和6怎么算呢&#xff1f;本…

Doxygen源码分析: 根目录文件简要介绍

2023-05-18 22:54:02 ChrisZZ imzhuofoxmailcom Hompage https://github.com/zchrissirhcz 文章目录 1. doxygen 版本2. 文件介绍DockerfileLICENSE.dockerignore.codedocsVERSION.editorconfigLANGUAGE.HOWTOBUILD.txtINSTALL.gitignoreREADME.mdCMakeLists.txt 1. doxygen 版…

一图看懂 chardet 模块:字符编码检测器,兼容 Python2 和 Python3,资料整理+笔记(大全)

本文由 大侠(AhcaoZhu)原创&#xff0c;转载请声明。 链接: https://blog.csdn.net/Ahcao2008 一图看懂 chardet 模块&#xff1a;字符编码检测器&#xff0c;兼容 Python2 和 Python3&#xff0c;资料整理笔记&#xff08;大全&#xff09; &#x1f9ca;摘要&#x1f9ca;模块…

【1++的C++初阶】之内存管理

&#x1f44d;作者主页&#xff1a;进击的1 &#x1f929; 专栏链接&#xff1a;【1的C初阶】 文章目录 一&#xff0c;C/C的内存分布二&#xff0c;malloc&#xff0c;realloc&#xff0c;calloc的区别三&#xff0c;C的内存管理- -new和delete初识new和deletenew和delete操作…