D03 / 怎麽摆放我的画面 - Layout & Alignment

今天大概会聊到的范围

  • basic layout
  • arrangement & alignment

在 Compose 之中,我们有三个可以乘载其他 component 的基础 container。他们分别是纵向排列的 Column 、横向排列的 Row  以及图层式排列的 Box 。透过这三个 container,我们可以摆出各式各样的画面。

https://ithelp.ithome.com.tw/upload/images/20210917/20141597QKLJk0lcdt.png
(image source: Compose layout basics | Android Developers)

在摆放 Layout 时,大致可以透过两个面向来异动 component 在 container 中的位置:

  1. 从 container 一次异动所有的 item
  2. 对单个 component(item) 调整他在 container 内的位置。

很类似原本的 xml 排版中, gravity  和 layout_gravity 这两个 attribute 的行为。

注:这边会用 container 来代表在 Row / Column 这种可以装其他 composable 的 composable。而装在内 composable 则的会用 item 来称呼。

从 Container 控制

以 Row 举例,Row 中的 item 会是横向排列。不同的 item 的高度不同时,就有怎麽对齐的问题。
透过 Row 的 verticalAlignment 这个参数,可以定义对齐方式。

常见的有对齐方式有:Alignment.Bottom, Alignment.TopAlignment.CenterVertically

@Preview
@Composable
fun `Row Alignment Bottom`() {
    Row(
        verticalAlignment = Alignment.Bottom, // <<< 
        modifier = Modifier
            .height(130.dp)
            .fillMaxWidth()
    ) {
        ChildA()
        ChildB()
        ChildC()
    }
}
Alignment.Bottom Alignment.CenterVertically Alignment.Top
Alignment.Bottom Alignment.CenterVertically Alignment.Top

另外,还可以透过 BiasAlignment.Vertical(bias) 在 1 ~ -1 之间的某一个特定比例做对齐 ( -1 = Top , 1 = Bottom, 0 = Center )

@Preview
@Composable
fun `Row Alignment Bias Vertical`() {
    Row(
        verticalAlignment = BiasAlignment.Vertical(-0.4f),
        modifier = Modifier
            .height(130.dp)
            .fillMaxWidth()
    ) {
        ChildA()
        ChildB()
        ChildC()
    }
}
BiasAlignment.Vertical
BiasAlignment.Vertical

除了 Alignment 外,还有 Arrangement ,Arrangment 调整的是 item 在 container 摆放的位置。最基本的是 StartEnd ,代表着 item 从 container 中最左 or 最右开始摆放。Center 则是代表所有 item 集合在最中间

@Preview
@Composable
fun `Row Arrangement Start`() {
    Row(
        horizontalArrangement = Arrangement.Start, // <<< 
        modifier = Modifier
            .height(130.dp)
            .fillMaxWidth()
    ) {
        ChildA()
        ChildB()
        ChildC()
    }
}
Arrangement.Start Arrangement.End Arrangement.Center
Arrangement.Start Arrangement.End Arrangement.Center

另外,还有 SpaceEvently , SpaceBetweenSpaceAround 三种设定可以将物件平均分布在 container 内。

SpaceEvently 就是普通的平均分布。SpaceBetween 也是平均分布,但是两端不留空间。最後 SpaceAround 是每个 item 的两边都有一个间隔,意味着 item 与 item 间的空间会是最两端 item 与 container 边界间的两倍

Arrangement.SpaceEvently Arrangement.SpaceBetween Arrangement.SpaceAround
Arrangement.SpaceEvently Arrangement.SpaceBetween Arrangement.SpaceAround

Column 也有完全相同的结构只是方向改成垂直的,这边就不多做介绍。


从 Item 控制

有时候,我们只需要某一个 item 摆在特殊的位置,这时候可以对特定 item 设定 align 这个 modifier 。align 在对应的 container 中能使用的参数与稍早提到的 alignment 参数是相同的。在 Row 中可以使用 Top / Bottom / CenterVerticallyColumn 中可以做 Start / End / CenterHorizontally。在 Box 中摆放的位置更自由,有上下左右、四角及中间等九个位子(如下图)。当然,前面提到的 BiasAlignment 也是可以使用的。

@Preview(group = "item arrangement")
@Composable
fun `Arrangement Item`() {
    Box(
        modifier = Modifier.size(360.dp)
    ) {
        Item(name = "TopStart", modifier = Modifier.align(Alignment.TopStart))
        Item(name = "TopCenter", modifier = Modifier.align(Alignment.TopCenter))
        Item(name = "TopEnd", modifier = Modifier.align(Alignment.TopEnd))
        Item(name = "CenterStart", modifier = Modifier.align(Alignment.CenterStart))
        Item(name = "Center", modifier = Modifier.align(Alignment.Center))
        Item(name = "CenterEnd", modifier = Modifier.align(Alignment.CenterEnd))
        Item(name = "BottomStart", modifier = Modifier.align(Alignment.BottomStart))
        Item(name = "BottomCenter", modifier = Modifier.align(Alignment.BottomCenter))
        Item(name = "BottomEnd", modifier = Modifier.align(Alignment.BottomEnd))
    }
}

https://ithelp.ithome.com.tw/upload/images/20210917/20141597j22MVabZ67.png


有了这些调整位置的方式、基本的 padding、再加上对 Layout 的嵌套,已经可以大致排出各种需求了。


<<:  [Day 3] 排版布局Container

>>:  [Golang] Array and Slice

【Day23】SwiftUI Essentials - SwiftUI 基础

在这边先声明,这篇是是WWDC大会的部分翻译,我找到的也是别人翻译以及笔记的 文章,只是我觉得很适合...

第二十六天:UI切版 & 元件-图文资讯元件、ICON字型 & SVG、通知讯息元件

今天的内容 一、图文资讯元件 二、ICON: Webfont & SVG 三、通知讯息元件 ...

Day 23 - 天眼CNN 的耳朵和嘴巴 - Transformer

RNN问题及解法 RNN 有字数限制, 最多到200字, 超过效果不好。The fall of RN...

DAY2 练习文件内容

以下就是我请学长帮我写的练习专案内容 一、功能列表(Flex 按钮) 1.注册:存取使用者姓名和组别...

Day17

arrary很别好理解,一维arrary就是线,二维arrary就是面,三维arrary就是立方体,...