Jetpack Compose 从入门到入门(二)

2023-05-16

开始布局部分。这部分我个人感觉没有必要每个组件、属性都详细说到,否则篇幅会很长。建立起Compose中的组件与 Android Views的一个对应关系就够了。具体还是需要在实际的使用中去熟悉。

1. Column

子元素按竖直顺序排列,相当于竖直方向的LinearLayout

@Composable
inline fun Column(
    modifier: Modifier = Modifier,
    verticalArrangement: Arrangement.Vertical = Arrangement.Top,
    horizontalAlignment: Alignment.Horizontal = Alignment.Start,
    content: @Composable ColumnScope.() -> Unit
)
  • modifier是修饰符,我们放到下一篇详细说明。
  • verticalArrangement,指定子元素在Column中的排列方式,默认是Top。下图是文档给的各属性示意,很直观。
    在这里插入图片描述
  • horizontalAlignment,指定水平方向的对齐方式,有StartCenterHorizontallyEnd三种,默认Start。这部分和我们的android:gravity属性类似,这里是通过两个属性分开配置。
  • content,就是我们的子元素,用大括号包住。
@Composable
fun ArtistCard() {
    Column {
        Text("Alfred Sisley")
        Text("3 minutes ago")
    }
}

2. Row

子元素按水平顺序排列,相当于水平方向的LinearLayout。基本用法与Column一致,简单说明一下。

@Composable
inline fun Row(
    modifier: Modifier = Modifier,
    horizontalArrangement: Arrangement.Horizontal = Arrangement.Start,
    verticalAlignment: Alignment.Vertical = Alignment.Top,
    content: @Composable RowScope.() -> Unit
)
  • horizontalArrangement,指定子元素在水平方向的排列方式,默认是Start。直接上图:
    在这里插入图片描述
  • verticalAlignment,指定垂直方向的对齐方式,有TopCenterVerticallyBottom三种,默认Top

3. Box

box就像盒子一样,里面的东西可以层层摆放。大体相当于FrameLayout

@Composable
inline fun Box(
    modifier: Modifier = Modifier,
    contentAlignment: Alignment = Alignment.TopStart,
    propagateMinConstraints: Boolean = false,
    content: @Composable BoxScope.() -> Unit
)
  • contentAlignment,指定子元素的对齐方式,八个方向加一个正中九种位置,默认是左上角(LTR)。这个属性我个人觉得使用频率不高,主要还是需要单独去指定各个子元素位置(使用Modifieralign方法)。
    这里可以看个文档中的例子:
	Box {
        Box(Modifier.fillMaxSize().background(Color.Cyan))
        Box(
            Modifier.matchParentSize()
                .padding(top = 20.dp, bottom = 20.dp)
                .background(Color.Yellow)
        )
        Box(
            Modifier.matchParentSize()
                .padding(40.dp)
                .background(Color.Magenta)
        )
        Box(
            Modifier.align(Alignment.Center)
                .size(300.dp, 300.dp)
                .background(Color.Green)
        )
        Box(
            Modifier.align(Alignment.TopStart)
                .size(150.dp, 150.dp)
                .background(Color.Red)
        )
        Box(
            Modifier.align(Alignment.BottomEnd)
                .size(150.dp, 150.dp)
                .background(Color.Blue)
        )
    }

预览效果:
在这里插入图片描述
Box中的各个子Box从底部向上叠加。通过align指定位置,通过sizepadding调整大小。matchParentSize类似match_parent属性,宽高填充满父布局。

注意:这个子元素的Box和父元素Box虽然长得一样,但实际不是一个组件。前者类似于View,不能添加子View,可以指定大小样式,而后者类似ViewGroup。

  • propagateMinConstraints,子元素是否使用指定的最小约束,默认false。这个属性直接这么解释很抽象,我们可以接着用上面的例子,添加下面的代码:
	Box(
        Modifier.sizeIn(100.dp, 200.dp),
        propagateMinConstraints = true
    ) {
    ...
    }

我们指定子元素最小宽是100dp,高是200dp后,预览效果如下:
在这里插入图片描述
可以看到原本的红蓝色块因为高度只有150dp,所以被约束为了最小的200dp,变成的长方形。

4.BoxWithConstraints

BoxWithConstraints和上面的Box很相似,唯一不同是它多了约束。我们先看源码:

@Composable
fun BoxWithConstraints(
    modifier: Modifier = Modifier,
    contentAlignment: Alignment = Alignment.TopStart,
    propagateMinConstraints: Boolean = false,
    content: @Composable BoxWithConstraintsScope.() -> Unit
)

注意到不同处是BoxWithConstraintsScope,它继承自BoxScopeBoxScope就是提供了上面使用到的alignmatchParentSize方法的作用域。

/**
 * Receiver scope being used by the children parameter of [BoxWithConstraints]
 */
@Stable
interface BoxWithConstraintsScope : BoxScope {
    /**
     * The constraints given by the parent layout in pixels.
     *
     * Use [minWidth], [maxWidth], [minHeight] or [maxHeight] if you need value in [Dp].
     */
    val constraints: Constraints
    /**
     * The minimum width in [Dp].
     *
     * @see constraints for the values in pixels.
     */
    val minWidth: Dp
    /**
     * The maximum width in [Dp].
     *
     * @see constraints for the values in pixels.
     */
    val maxWidth: Dp
    /**
     * The minimum height in [Dp].
     *
     * @see constraints for the values in pixels.
     */
    val minHeight: Dp
    /**
     * The maximum height in [Dp].
     *
     * @see constraints for the values in pixels.
     */
    val maxHeight: Dp
}

所以BoxWithConstraints不同就是在Box的基础上多了最大最小宽度高度的属性。可以用它来做一些页面适配之类的工作,使用例子如下:

	BoxWithConstraints {
        if (maxWidth < 400.dp) {
            Column {
                Image(/* ... */)
                Title(/* ... */)
            }
        } else {
            Row {
                Column {
                    Title(/* ... */)
                    Description(/* ... */)
                }
                Image(/* ... */)
            }
        }
    }

5.ConstraintLayout

使用 Android View 系统时,在嵌套某些 View(如 RelativeLayout)时,可能会出现一些性能问题。由于 Compose 可以避免多次测量,因此可以根据需要进行深层次嵌套,而不会影响性能。

虽然不用考虑嵌套带来的性能问题,但是这写起来一层套一层的也挺闹心的。加上ConstraintLayout我个人已经非常习惯使用了,所以也很希望在Compose中也能使用到它。个人感觉ConstraintLayout 可以提高可读性。

使用Compose中的ConstraintLayout需要额外添加依赖:

implementation "androidx.constraintlayout:constraintlayout-compose:1.0.0-rc02"
@Composable
inline fun ConstraintLayout(
    modifier: Modifier = Modifier,
    optimizationLevel: Int = Optimizer.OPTIMIZATION_STANDARD,
    crossinline content: @Composable ConstraintLayoutScope.() -> Unit
)

optimizationLevellayout_optimizationLevel一样,用来约束优化的。默认OPTIMIZATION_STANDARD,只优化直接约束和barrier约束。通常我们不需要修改它。

这里用官方的一个例子简单说明一下它的使用方法:

	ConstraintLayout(
        modifier = Modifier
            .fillMaxSize()
    ) {
        val (image, header, tag1, tag2, tag3, bSignup, bLogin, disclaimer) = createRefs()
        val g1 = createGuidelineFromStart(44.dp)
        val g2 = createGuidelineFromEnd(44.dp)
        Image(
            modifier = Modifier.constrainAs(image) {
                width = Dimension.value(201.dp)
                height = Dimension.value(179.dp)
                top.linkTo(parent.top, 32.dp)
                start.linkTo(g1)
            },
            painter = painterResource(id = R.drawable.intercom_snooze),
            contentDescription = null
        )
        Text(
            modifier = Modifier.constrainAs(header) {
                top.linkTo(image.bottom, 32.dp)
                start.linkTo(g1)
                end.linkTo(g2)
                width = Dimension.fillToConstraints
            },
            text = stringResource(id = R.string.welcome_header),
            style = MaterialTheme.typography.h5,
        )
        Text(
            modifier = Modifier.constrainAs(tag1) {
                top.linkTo(header.bottom, 16.dp)
                start.linkTo(g1)
                end.linkTo(g2)
                width = Dimension.fillToConstraints
            },
            text = stringResource(id = R.string.welcome_tagline1)
        )
        Text(
            modifier = Modifier.constrainAs(tag2) {
                top.linkTo(tag1.bottom, 8.dp)
                start.linkTo(g1)
                end.linkTo(g2)
                width = Dimension.fillToConstraints
            },
            text = stringResource(id = R.string.welcome_tagline2)
        )
        Text(
            modifier = Modifier.constrainAs(tag3) {
                top.linkTo(tag2.bottom, 8.dp)
                start.linkTo(g1)
                end.linkTo(g2)
                width = Dimension.fillToConstraints
            },
            text = stringResource(id = R.string.welcome_tagline3)
        )
        Button(
            modifier = Modifier.constrainAs(bSignup) {
                bottom.linkTo(bLogin.top, 16.dp)
                start.linkTo(g1)
                end.linkTo(g2)
                width = Dimension.fillToConstraints
            },
            onClick = {}
        ) {
            Text(text = stringResource(id = R.string.sign_up))
        }
        Button(
            modifier = Modifier.constrainAs(bLogin) {
                bottom.linkTo(disclaimer.top, 16.dp)
                start.linkTo(g1)
                end.linkTo(g2)
                width = Dimension.fillToConstraints
            },
            onClick = {},
        ) {
            Text(text = stringResource(id = R.string.log_in))
        }
        Text(
            modifier = Modifier.constrainAs(disclaimer) {
                bottom.linkTo(parent.bottom, 8.dp)
                start.linkTo(g1)
                end.linkTo(g2)
                width = Dimension.fillToConstraints
            },
            text = stringResource(id = R.string.trial_disclaimer),
            style = MaterialTheme.typography.caption,
        )
    }

预览效果如下(包括约束效果):

在这里插入图片描述 在这里插入图片描述

说明一下代码中的属性和方法:

  • createRefs()是创建引用。或者说定义需要使用的id。
  • Modifier.constrainAs是定义约束条件。括号内填写开始创建的引用。类似android:id="@+id/xxx"
  • createGuidelineFromXXX就是创建一个Guideline,例子中创建了左右两个Guideline作为左右两边间距参考线。
  • linkTo是用来指定约束条件的。例如top.linkTo(image.bottom, 32.dp) 相当于 app:layout_constraintTop_toBottomOf="@+id/image"android:layout_marginTop="32dp"
  • Dimension.fillToConstraints,填充满约束,类似宽高指定0dp。

当然还有许多的属性方法没有用到,也就不详细的介绍了,有兴趣的可以看官方demo。


到此,基础布局篇结束,下一篇详细介绍 Modifier修饰符。

6.参考

  • Compose 布局基础知识
  • Compose 的标准布局元素
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Jetpack Compose 从入门到入门(二) 的相关文章

  • Jetpack Compose 从入门到入门(九)

    本篇是Compose的手势部分 点击 添加clickable修饰符就可以轻松实现元素的点击 此外它还提供无障碍功能 xff0c 并在点按时显示水波纹效果 span class token annotation builtin 64 Comp
  • Linux中如何查Jetson Nano中jetpack的版本

    命令 xff1a cat etc nv tegra release 如下图所示 xff0c 输入的内容为 R32 release REVISION 5 1 GCID 26202423 BOARD t210ref EABI aarch64 D
  • 树莓派安装 docker 和 docker-compose

    树莓派安装 docker 和 docker compose 本文地址 xff1a blog lucien ink archives 518 因为总是频繁地初始化树莓派 xff0c 所以把安装 docker 的过程也记录下来 1 安装 doc
  • docker-compose构建mysql服务

    docker安装mysql服务显得很快捷 xff0c 我们如果使用了docker compose那就更快了 xff0c 我们只需要按照我们的要求 xff0c 设置相应的端口映射 xff0c 如果有需求 xff0c 也可以设置数据映射 配置如
  • macbook m1上安装docker-compose

    之前我已安装好了docker 在网站https github com docker compose releases 下载docker compose linux aarch64 放到我的 Users a1目录下 进入目录cd Users
  • JETSON TX2镜像备份与恢复以及刷机的巨详细教程(Jetpack 4.4版本)

    摘自 xff1a https blog csdn net Feizhai2 article details 109068697 utm medium 61 distribute pc relevant t0 none task blog B
  • 更新docker镜像及容器,使用docker-compose命令

    第一种方法 xff1a docker stop 容器名或镜像id 下面一样 docker rm 容器名 docker rmi 镜像名 docker builder 镜像名 docker run d name 容器名 p 对外端口 内部端口
  • Docker之基于docker-compose创建vsftpd容器

    前言 因为本人很菜 xff0c 每次配置vsftpd都头疼的要死 又因为网上vsftpd的教程会版本不一导致配置总是会出错 因此尝试使用docker来解决这个问题 而单纯只是用docker每次启动需要输入长串命令 xff0c 因此再结合do
  • SEATAdocker-compose部署

    docker compose 文件 span class token key atrule version span span class token punctuation span span class token string 39
  • docker-compose 部署ELK

    目录结构 docker compose 文件 span class token key atrule version span span class token punctuation span span class token strin
  • Jetpack Compose 不止是一个UI框架~

    Jetpack Compose是用于构建原生Android UI的现代工具包 Jetpack Compose使用更少的代码 xff0c 强大的工具和直观的Kotlin API xff0c 简化并加速了Android上的UI开发 这是Andr
  • Docker Compose

    1 Docker Compose官网说明 理解 Compose是Docker官方的开源项目 需要安装 xff01 Dockerfile 让程序在任何地方运行 web服务 redis mysql nginx 多个容器 run Compose的
  • 【Docker】ubuntu下安装Docker和Docker-Compose

    文章目录 一 先决条件 xff08 一 xff09 操作系统要求 xff08 二 xff09 卸载旧版本Docker 二 安装Docker xff08 一 xff09 使用存储库安装Docker 三 安装Docker Compose xff
  • JetsonTX2 之刷机 ——Jetpack 4.3

    2020年再次使用Nvidia Jetson tx2 xff0c Jetpack已经发行了4 4 xff0c TX2默认的系统也升级到了ubuntu 18 04 xff0c 刷机方式也发生了变化 这里记录我的刷机过程 xff0c 亲测有效
  • Jetpack练手(03):DataBinding

    文章目录 一 导入依赖二 搭建布局三 创建 ViewModel 数据对象四 修改布局为 DataBinding 布局五 绑定数据六 Demo 效果 一 导入依赖 新建 DataBindingDemo 工程 xff0c 参照 LiveData
  • docker-compose 中 volumes、environment、privileged、network_mode的使用

    privileged xff1a 用来给容器root权限 xff0c 不安全的environment xff1a 设置容器中的环境变量volumes xff1a 用来存储docker持久化的数据 xff0c 启动tomcat容器后 xff0
  • 不贴代码能说明白Jetpack LiveData原理吗(一)

    LifecycleOwner如何提供周期生命周期的变化 LifecycleObserver如何得知生命周期的变化 LiveData的背后隐藏了多少不为人知的秘密 这一切都要从观察者模式说起 起源 何为观察者模式 在代码中最直接的表现就是在事
  • 一文带你了解ViewModel

    Lifecycle库可以有效避免内存泄漏和解决常见的Android生命周期难题 1 引言 ViewModel属于lifecycle 生命周期感知型组件 中的一员 通常与LiveData DataBinding一起使用 它们是MVVM架构的重
  • LiveData详细分析2

    一 LiveData是什么东西 1 基于观察者设计模式 LiveData是一种持有可被观察数据的类 被观察者 LiveData需要一个观察者对象 一般是Observer类的具体实现 当观察者的生命周期处于STARTED或RESUMED状态时
  • Jetpack Compose多平台用于Android和IOS

    JetBrains和外部开源贡献者已经努力工作了几年时间来开发Compose Multiplatform 并最近发布了适用于iOS的Alpha版本 自然地 我们对其功能进行了测试 并决定通过使用该框架在iOS上运行我们的Dribbble复制

随机推荐

  • git 放弃更改常用命令

    1 未add commit git checkout filename path 2 已add未commit git reset HEAD filename 3 放弃已经commit的修改 git reflog查看commit日志 git
  • linux解压缩常见命令

    tar详解 c 建立压缩档案 x xff1a 解压 t xff1a 查看内容 r xff1a 向压缩归档文件末尾追加文件 u xff1a 更新原压缩包中的文件 这五个是独立的命令 xff0c 压缩解压都要用到其中一个 xff0c 可以和别的
  • linux 安装 gcc 方法

    今天安装Linux虚拟机发现竟然没有gcc 感觉是崩溃的 xff0c 上网寻找一下安装方法 xff0c 借鉴总结了一下得出下面步骤 使用root权限下载 sudo yum y install gcc gcc c 43 43 autoconf
  • MFC编程基础(—)

    MFC类的基本层次结构如图所示 xff1a CObject类是MFC提供的绝大多数类的基类 该类完成动态空间的分配和回收 xff0c 支持一般的诊断 出错信息处理和文档序列化等 CCmdTarget类主要负责将系统事件 xff08 消息 x
  • 开启windows10系统组策略更新、开启Windows自动更新、关闭自动更新

    win 43 R键打开运行 xff0c 输入regedit 按路径 计算机 HKEY LOCAL MACHINE SOFTWARE Policies Microsoft Windows WindowsUpdate AU 找到NoAutoUp
  • linux 中 /etc/systemd/system和/usr/lib/systemd/system 的区别

    每一个 Unit xff08 服务等 xff09 都有一个配置文件 xff0c 告诉 Systemd 怎么启动这个 Unit Systemd 默认从目录 etc systemd system 读取配置文件 但是 xff0c 里面存放的大部分
  • Vue3使用axios请求数据后使用v-for显示不出数据

    getAccount let that 61 this axios url 39 http localhost 8080 api GetAllUniAccounts 39 method 39 post 39 then res 61 gt t
  • Axios请求中Content-Type的使用总结

    Axios请求头中的Content Type常见的有3种 xff1a 1 Content Type application json 2 Content Type application x www form urlencoded 3 Co
  • mycat全局序列号数据库方式

    1 server xml lt property name 61 34 sequnceHandlerType 34 gt 1 lt property gt 2 schema xml lt table name 61 34 z test 34
  • Warning: Packets out of order. Expected 8 received 0

    环境 xff1a linux 43 mycat 43 hyperf 43 es 原因 xff1a mycat进行了分片 解决 xff1a 修改文件路径 xff1a vendor hyperf database src Connectors
  • Ubuntu下不能切换中文,qt creator无法输入中文,sogo输入法(详细步骤)

    目录 xff1a 1 解决ubuntu 不支持切换中文 xff0c 并安装sogo输入法步骤 xff1b 2 解决Qt Creator不支持中文输入 xff1a 详细步骤 xff1a 一 解决ubuntu 不支持切换中文 xff0c 并安装
  • wordpress插件API入口

    lt php 64 package Moodo Zhong 64 version 1 0 0 Plugin Name Moodo Zhong Plugin URI http wordpress org plugins hello dolly
  • PHP源码目录说明

    1 build 和编译有关的目录 2 ext 扩展库代码 xff0c 例如 MySQL zlib iconv 等我们熟悉的扩展库 其中 ext standard 目录下是常用的标准函数集 3 main 主目录包含主要的 PHP 宏和定义 4
  • 终端程序定义示例

    interrupt 0 外部中断0 interrupt 1 T0中断 interrupt 2 外部中断1 interrupt 3 T1中断 interrupt 4 串口中断 我来告诉你实质 xff1a 单片机的中断处理是这样工作的 xff0
  • lisp学习资料

    中文LISP学习网站 CL HTTP franz com 217条消息 使用hunchentoot搭建Lisp web 服务器 keyboardOTA的博客 CSDN博客
  • GO调用C语言之字符串传递

    C xff1a hello h include lt stdlib h gt include lt stdio h gt include lt string h gt char abc int strnum char str C hello
  • C++-基础语法-cin.getline() 与 cin.get() 的区别,以及getline()函数使用方法

    参考声明 xff1a C 43 43 primer plus https blog csdn net best fiends zxh article details 53064771 https blog csdn net u0114216
  • Kotlin开发中的一些Tips(二)

    接着上一篇 xff0c 最近又整理了一些 1 作用域函数选择 目前有let run with apply 和 also五个作用域函数 官方文档有张表来说明它们之间的区别 xff1a 总结一下有几点区别 xff1a apply和also返回上
  • Jetpack Compose 从入门到入门(一)

    Jetpack Compose 是用于构建原生 Android 界面的新工具包 它使用更少的代码 强大的工具和直观的 Kotlin API xff0c 可以帮助您简化并加快 Android 界面开发 xff0c 打造生动而精彩的应用 它可让
  • Jetpack Compose 从入门到入门(二)

    开始布局部分 这部分我个人感觉没有必要每个组件 属性都详细说到 xff0c 否则篇幅会很长 建立起Compose中的组件与 Android Views的一个对应关系就够了 具体还是需要在实际的使用中去熟悉 1 Column 子元素按竖直顺序