Jetpack Compose 象限布局学习

淮城一只猫 编程技术 阅读量 0 评论量 0

前言

嗨,好久不见,上一篇的技术文章还停留在2022年3月14日,嗯...一年没更新了,我这中间不知道经历了一些什么,总之感觉非常浮躁。不过这段时间差不多调整好了,打算从这篇文章开始好好学习 Android 软件开发,当然这指的是从「Kotlin 从零开始开发 Android 软件」的一个过程。前俩天看了一下 Kotlin 的基本语法,因为有之前编程的底子大致看得懂,所以后面直接跳到 Jetpack Compose 直接入门学习吧。希望今年学习 Jetpack Compose 能够沉下心来。

不过这类笔记看起来挺小白的,有时候我都不太想发布到博客,但是这样做又违约博客的定义,也罢,只做好自己就行,不管做什么事情都需要一个过程。

Jetpack Compose 是什么?

Jetpack Compose 是一个适用于 Android 的新式声明性界面工具包。Compose 提供声明性 API,让您可在不以命令方式改变前端视图的情况下呈现应用界面,从而使编写和维护应用界面变得更加容易。这段话听起来很像前端中的 Vue.jsReact 对他们的介绍,大概就是所谓的 MVVM 设计思想了。不过遥想当年的 Android 开发可是相当麻烦,各种 xml 写布局然后对应不同的业务,想想人都麻了,如今 Jetpack Compose 工具包可以解决这些问题,大致看了下过程很像前端的 JSX 语法,如果学习下去省了不少力气。当然 Jetpack Compose 编程语法还是 Kotlin,Kotlin 看起来很简洁,至少没 Java 那么啰嗦,有时候我也不得不吐槽 Java 啰哩啰嗦,真的很烦,当然也不能忽视他的优点。

象限布局

在写这篇文章之前,我已经看到构建基本布局的阶段了,在 Google Android 培训中我在做一道题目,名叫Compose 象限,这个题目上面俩个小题目轻轻松松过了下,这个题目刚看的时候还挺简单,实际上还是踩到坑了,所以看完相关资料后觉得有必要记下来,免得以后再踩到坑。

这个题目要求完成下图的布局:

933d596e0bcd63b8_1920

事实上看到这个图片的时候我脑海中已经构建出布局的样式,就是 col 分出一列,然后列中设置 row 分为俩行即可:

@Composable
fun ComposeQuadrantApp() {
    Column(modifier = Modifier) {
        Row(modifier = Modifier, horizontalArrangement = Arrangement) {
        }
    }
    Column(modifier = Modifier) {
        Row(modifier = Modifier, horizontalArrangement = Arrangement) {
        }
    }
}

实际上到这里我基本上和正确布局差不多,但是 Compose 布局样式和我经常接触的前端布局有点差距的,比如上图说的高宽各占一半,这个属性我愣是没想到,后面查阅文档也是没看明白:

@Composable
fun ComposeQuadrantApp() {
    Column(Modifier.fillMaxWidth()) {
        Row(modifier = Modifier.weight(1f)) {
        }
        Row(modifier = Modifier.weight(1f)) {
        }
    }
}

首选 Column 分成俩行,并且 Modifier.fillMaxWidth() 属性占满宽度,然后在在列中分俩行, Row 中的 Modifier.weight(1f) 当时把我看迷糊了,我以为这个是设置字体宽度属性用的,在我认知里 Android 的样式应该和前端差不多,不过走了一大圈弯后面才明白这个是指的是决定子项高或宽占比权重,比如上面俩个 Row(modifier = Modifier.weight(1f) 代表各占 50% 如果是:

@Composable
fun ComposeQuadrantApp() {
    Column(Modifier.fillMaxWidth()) {
        Row(modifier = Modifier.weight(1f)) {
        }
        Row(modifier = Modifier.weight(2f)) {
        }
    }
}

这样表现出来就是第一个 Row 占比高度是整列高度的三分之一,第二个则是三分之二,大概就这么来的,后面看完后恍然大悟,差点把自己绕进去了。当然这里的 Modifier.weight() 只在 ColumnRow 里面存在。

然后后面就简单了,写个函数,这个布局输出相同的布局和不同的文字、背景颜色即可:

package com.iiong.joinercomponent

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.iiong.joinercomponent.ui.theme.JoinerComponentTheme

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            JoinerComponentTheme {
                Surface(Modifier.fillMaxSize()) {
                    ComposeQuadrantApp()
                }
            }
        }
    }
}

@Composable
fun ComposeQuadrantApp() {
    Column(Modifier.fillMaxWidth()) {
        Row(modifier = Modifier.weight(1f, fill = true)) {
            ComposeQuadrantItem(
                title = stringResource(id = R.string.text_composable_title),
                description = stringResource(id = R.string.text_composable_description),
                backgroundColor = Color.Green,
                modifier = Modifier.weight(1f)
            )
            ComposeQuadrantItem(
                title = stringResource(id = R.string.text_composable_title),
                description = stringResource(id = R.string.text_composable_description),
                backgroundColor = Color.Yellow,
                modifier = Modifier.weight(1f)
            )
        }
        Row(modifier = Modifier.weight(1f, fill = true)) {
            ComposeQuadrantItem(
                title = stringResource(id = R.string.text_composable_title),
                description = stringResource(id = R.string.text_composable_description),
                backgroundColor = Color.Cyan,
                modifier = Modifier.weight(1f)
            )
            ComposeQuadrantItem(
                title = stringResource(id = R.string.text_composable_title),
                description = stringResource(id = R.string.text_composable_description),
                backgroundColor = Color.LightGray,
                modifier = Modifier.weight(1f)
            )
        }
    }
}

@Composable
fun ComposeQuadrantItem(
    title: String,
    description: String,
    backgroundColor: Color,
    modifier: Modifier = Modifier
) {
    Column(
        modifier = modifier
            .fillMaxSize().background(color = backgroundColor).padding(16.dp),
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center
    ) {
        Text(
            text = title,
            fontWeight = FontWeight.Bold,
            modifier = Modifier.padding(bottom = 16.dp)
        )
        Text(
            text = description
        )
    }
}

@Preview(showBackground = true)
@Composable
fun DefaultPreviewDemo3() {
    JoinerComponentTheme {
        ComposeQuadrantApp()
    }
}

还挺简单的,不算很难理解,一番操作下来感觉很像写 JSX 的感觉,就是不知道后面和业务上对接是什么样子的,如果真的和 MVVM 写法差不多那真的是太棒了,越来越期待后面的写法了,希望这次好的开头让我下面学习更顺利吧。

喵~