美文网首页
Jetpack Compose 基础知识

Jetpack Compose 基础知识

作者: qiufeng1ye | 来源:发表于2022-08-11 17:02 被阅读0次

    教程取自于Google官方课程之Jetpack Compose 基础知识


    1. 准备工作

    Jetpack Compose 是一款新型工具包,旨在帮助简化界面开发。该工具包将响应式编程模型与简洁易用的 Kotlin 编程语言相结合,并采用完全声明式的代码编写方式,让您可以通过调用一系列函数来描述界面,这些函数会将数据转换为界面层次结构。当底层数据发生变化时,框架会自动重新执行这些函数,为您更新界面层次结构。

    Compose 应用由可组合函数构成。可组合函数即带有 @Composable 标记的常规函数,这些函数可以调用其他可组合函数。使用一个函数就可以创建一个新的界面组件。该注解会告知 Compose 为函数添加特殊支持,以便后续更新和维护界面。借助 Compose,您可以将代码设计成多个小代码块。可组合函数通常简称为“可组合项”。

    通过创建可重用的小型可组合项,您可以轻松构建应用中所用界面元素的库。每个可组合项对应于屏幕的一个部分,可以单独修改。

    注意:在本 Codelab 中,“界面组件”、“可组合函数”和“可组合项”几个术语可以互换使用来指代同一个概念。

    2. 启动新的 Compose 项目

    如需启动新的 Compose 项目,请打开 Android Studio Bumblebee,然后选择 Start a new Android Studio project,如下所示:

    新的 Compose 项目
    如果系统未显示上述界面,请依次进入 File > New > New Project。
    创建新项目时,请从可用模板中选择 Empty Compose Activity。
    Empty Compose Activity
    点击 Next,然后照常配置项目,并将其命名为 Basics Codelab。请确保您选择的 minimumSdkVersion 至少为 API 级别 21,这是 Compose 支持的最低 API 级别。

    注意:如需详细了解如何使用空 activity 设置 Compose,或如何将其添加到现有项目,请查看此文档
    选择 Empty Compose Activity 模板后,会在项目中为您生成以下代码:

    • 该项目已配置为使用 Compose。
    • 已创建 AndroidManifest.xml 文件。
    • build.gradle 和 app/build.gradle 文件包含 Compose 所需的选项和依赖项。

    同步项目后,请打开 MainActivity.kt 并查看代码。

    class MainActivity : AppCompatActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContent {
                BasicsCodelabTheme {
                    // A surface container using the 'background' color from the theme
                    Surface(color = MaterialTheme.colors.background) {
                        Greeting("Android")
                    }
                }
            }
        }
    }
    
    @Composable
    private fun Greeting(name: String) {
        Text(text = "Hello $name!")
    }
    
    @Preview(showBackground = true)
    @Composable
    fun DefaultPreview() {
        BasicsCodelabTheme {
            Greeting("Android")
        }
    }
    

    警告:setContent 中使用的应用主题取决于项目名称。本 Codelab 假定项目名称为 LayoutsCodelab。如果您从 Codelab 中复制并粘贴代码,请记得使用 ui/Theme.kt 文件中提供的主题名称来更新 BasicsCodelabTheme。本 Codelab 后面会讲到如何设置主题。

    本 Codelab 的解决方案
    您可以从 GitHub 获取本 Codelab 的解决方案代码:https://github.com/googlecodelabs/android-compose-codelabs/archive/main.zip
    您可以在 BasicsCodelab 项目中找到解决方案代码。建议您按照自己的节奏逐步完成 Codelab,必要时再查看解决方案。在此 Codelab 的学习过程中,我们会为您提供需要添加到项目的代码段。

    3. Compose 使用入门

    了解 Android Studio 为您生成的与 Compose 相关的各种类和方法。

    可组合函数

    可组合函数是带有 @Composable 注解的常规函数。这类函数自身可以调用其他 @Composable 函数。我们会展示如何为 Greeting 函数添加 @Composable 标记。此函数会生成一段显示给定输入 String 的界面层次结构。Text 是由库提供的可组合函数。

    @Composable
    private fun Greeting(name: String) {
       Text(text = "Hello $name!")
    }
    

    注意:可组合函数是带有 @Composable 注解的 Kotlin 函数,如上述代码段所示。

    Android 应用中的 Compose
    使用 Compose 时,Activities 仍然是 Android 应用的入口点。在我们的项目中,用户打开应用时会启动 MainActivity(如 AndroidManifest.xml 文件中所指定)。您可以使用 setContent 来定义布局,但不同于在传统 View 系统中使用 XML 文件,您将在该函数中调用可组合函数。

    class MainActivity : AppCompatActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContent {
                BasicsCodelabTheme {
                    // A surface container using the 'background' color from the theme
                    Surface(color = MaterialTheme.colors.background) {
                        Greeting("Android")
                    }
                }
            }
        }
    }
    

    BasicsCodelabTheme 是为可组合函数设置样式的一种方式。有关详细内容,请参阅设置应用主题部分。如需查看文本在屏幕上的显示效果,您可以在模拟器或设备上运行该应用,或使用 Android Studio 预览进行查看。

    若要使用 Android Studio 预览,您只需使用 @Preview 注解标记所有无参数可组合函数或采用默认参数的函数,然后构建您的项目即可。现在 MainActivity.kt 文件中已经包含了一个 Preview Composable 函数。您可以在同一个文件中包含多个预览,并为它们指定名称。

    @Preview(showBackground = true, name = "Text preview")
    @Composable
    fun DefaultPreview() {
        BasicsCodelabTheme {
            Greeting(name = "Android")
        }
    }
    
    Preview

    注意:在此项目中导入与 Jetpack Compose 相关的类时,请从以下位置导入:
    androidx.compose.*(针对编译器和运行时类)

    androidx.compose.ui.*(针对界面工具包和库)

    4. 调整界面

    首先,为 Greeting 设置不同的背景颜色。为此,您可以用 Surface 包围 Text 可组合项。Surface 会采用一种颜色,因此请使用 MaterialTheme.colors.primary。

    注意:SurfaceMaterialTheme 是与 Material Design 相关的概念。Material Design 是 Google 提供的一个设计系统,旨在帮助您构建界面和体验。

    @Composable
    private fun Greeting(name: String) {
        Surface(color = MaterialTheme.colors.primary) {
            Text (text = "Hello $name!")
        }
    }
    

    嵌套在 Surface 内的组件将在该背景颜色之上绘制。
    将上述代码添加到项目后,您会在 Android Studio 的右上角看到 Build & Refresh 按钮。点按该按钮或构建项目即可在预览中查看新更改。



    您可以在预览中查看新更改:



    您可能忽略了一个重要的细节:文字现在是白色的。我们是何时对此进行定义的?

    我们并没有对此进行过定义!Material 组件(例如 androidx.compose.material.Surface)旨在提供应用中可能需要的常见功能(例如为文本选择适当的颜色),让您获得更好的体验。我们之所以说 Material 很实用,是因为它提供在大多数应用中都会用到的实用默认值和模式。Compose 中的 Material 组件是在其他基础组件(位于 androidx.compose.foundation 中)的基础上构建的。如果您需要更高的灵活性,也可以从您的应用组件中访问这些组件。

    在这种情况下,Surface 会了解,当该背景设置为 primary 颜色后,其上的任何文本都应使用 onPrimary 颜色,此颜色也在主题中进行了定义。如需了解详情,请参阅设置应用主题部分。

    注意:如需查看 Compose 中 Material 组件的交互式列表,请查看 Compose Material Catalog 应用。
    修饰符
    大多数 Compose 界面元素(例如 Surface 和 Text)都接受可选的 modifier 参数。修饰符会指示界面元素如何在其父级布局中放置、显示或表现。

    例如,padding 修饰符会在其修饰的元素周围应用一定的空间。您可以使用 Modifier.padding() 创建内边距修饰符。

    现在,为屏幕上的 Text 添加内边距:

    import androidx.compose.foundation.layout.padding
    import androidx.compose.ui.Modifier
    import androidx.compose.ui.unit.dp
    ...
    点击 Build & Refresh 即可查看新更改。
    @Composable
    private fun Greeting(name: String) {
        Surface(color = MaterialTheme.colors.primary) {
            Text(text = "Hello $name!", modifier = Modifier.padding(24.dp))
        }
    }
    

    点击 Build & Refresh 即可查看新更改。


    5. 重复使用可组合项

    您添加到界面的组件越多,创建的嵌套层级就越多。如果函数变得非常大,可能会影响可读性。通过创建可重用的小型组件,可以轻松构建应用中所用界面元素的库。每个组件对应于屏幕的一个部分,可以单独修改。

    创建一个名为 MyApp 的可组合项,该组合项中包含问候语。

    @Composable
    private fun MyApp() {
        Surface(color = MaterialTheme.colors.background) {
            Greeting("Android")
        }
    }
    

    这样一来,由于现在可以重复使用 MyApp 可组合项,您就可以省去 onCreate 回调和预览,从而避免重复编写代码。您的 MainActivity.kt 文件应如下所示:

    import android.os.Bundle
    import androidx.activity.ComponentActivity
    import androidx.activity.compose.setContent
    import androidx.compose.foundation.layout.padding
    import androidx.compose.material.MaterialTheme
    import androidx.compose.material.Surface
    import androidx.compose.material.Text
    import androidx.compose.runtime.Composable
    import androidx.compose.ui.Modifier
    import androidx.compose.ui.tooling.preview.Preview
    import androidx.compose.ui.unit.dp
    import com.codelab.basicstep1.ui.theme.BasicsCodelabTheme
    
    class MainActivity : ComponentActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContent {
                BasicsCodelabTheme {
                    MyApp()
                }
            }
        }
    }
    
    @Composable
    private fun MyApp() {
        Surface(color = MaterialTheme.colors.background) {
            Greeting("Android")
        }
    }
    
    @Composable
    private fun Greeting(name: String) {
        Surface(color = MaterialTheme.colors.primary) {
            Text(text = "Hello $name!", modifier = Modifier.padding(24.dp))
        }
    }
    
    @Preview(showBackground = true)
    @Composable
    private fun DefaultPreview() {
        BasicsCodelabTheme {
            MyApp()
        }
    }
    

    6. 创建列和行

    Compose 中的三个基本标准布局元素是 ColumnRowBox 可组合项。


    它们是接受可组合内容的可组合函数,因此您可以在其中放置内容。例如,Column 中的每个子级都将垂直放置。
    // Don't copy over
    Column {
        Text("First row")
        Text("Second row")
    }
    

    现在尝试更改 Greeting,使其显示包含两个文本元素的列,如以下示例中所示:



    请注意,您可能需要移动周围的内边距。

    将您的结果与此解决方案进行比较:

    import androidx.compose.foundation.layout.Column
    ...
    
    @Composable
    private fun Greeting(name: String) {
        Surface(color = MaterialTheme.colors.primary) {
            Column(modifier = Modifier.padding(24.dp)) {
                Text(text = "Hello,")
                Text(text = name)
            }
        }
    }
    

    Compose 和 Kotlin
    可组合函数可以像 Kotlin 中的其他函数一样使用。这会使界面构建变得非常有效,因为您可以添加语句来影响界面的显示方式。

    例如,您可以使用 for 循环向 Column 中添加元素:

    @Composable
    fun MyApp(names: List<String> = listOf("World", "Compose")) {
        Column {
            for (name in names) {
                Greeting(name = name)
            }
        }
    }
    

    您尚未设置可组合项的尺寸,也未对可组合项的大小添加任何限制,因此每一行仅占用可能的最小空间,预览时的效果也是如此。让我们更改预览效果,以模拟小屏幕手机的常见宽度 320dp。按如下所示向 @Preview 注解添加 widthDp 参数:

    @Preview(showBackground = true, widthDp = 320)
    @Composable
    fun DefaultPreview() {
        BasicsCodelabTheme {
            MyApp()
        }
    }
    

    修饰符在 Compose 中使用得非常广泛,现在我们来练习更高级的用法:尝试使用 fillMaxWidthpadding 修饰符复制以下布局。

    现在,将您的代码与解决方案进行比较:
    @Composable
    fun MyApp(names: List<String> = listOf("World", "Compose")) {
        Column(modifier = Modifier.padding(vertical = 4.dp)) {
            for (name in names) {
                Greeting(name = name)
            }
        }
    }
    
    @Composable
    private fun Greeting(name: String) {
        Surface(
            color = MaterialTheme.colors.primary,
            modifier = Modifier.padding(vertical = 4.dp, horizontal = 8.dp)
        ) {
            Column(modifier = Modifier.fillMaxWidth().padding(24.dp)) {
                Text(text = "Hello, ")
                Text(text = name)
            }
        }
    }
    

    请注意:

    修饰符可以包含重载,因而具有相应的优势,例如您可以指定不同的方式来创建内边距。
    若要向一个元素添加多个修饰符,您只需要将它们链接起来即可。
    有多种方式可以实现此结果,因此,如果您的代码与此代码段不同,并不表示您的代码就是错的。不过,为了继续完成此 Codelab,仍请复制并粘贴此代码。

    添加按钮
    接下来,您将添加一个用于展开 Greeting 的可点击元素,因此需要先添加对应的按钮。您的目标是要创建以下布局:


    Button 是 Material 软件包提供的一种可组合项,它采用可组合项作为最后一个参数。由于尾随 lambda 可以移到括号之外,因此您可以向按钮添加任何内容作为子级,例如 Text
    // Don't copy yet
    Button(
        onClick = { } // You'll learn about this callback later
    ) {
        Text("Show less")
    }
    

    注意:Compose 根据 Material Design 按钮规范提供了不同类型的 ButtonButtonOutlinedButtonTextButton。在本示例中,您将使用包围 Text 作为 Button 内容的 OutlinedButton

    为了实现这一点,您需要学习如何在行尾放置可组合项。由于没有 alignEnd 修饰符,因此您需要在开始时为该可组合项赋予一定的 weight。weight 修饰符会让元素填满所有可用空间,使其“具有弹性”,也就是会推开其他没有权重的元素(即“无弹性”元素)。该修饰符还会使 fillMaxWidth 修饰符变得多余。

    现在尝试添加该按钮,并按照上述图片中所示放置该按钮。

    下面列出了对应的解决方案代码:

    import androidx.compose.material.Button
    import androidx.compose.runtime.mutableStateOf
    import androidx.compose.runtime.remember
    ...
    
    @Composable
    private fun Greeting(name: String) {
    
        Surface(
            color = MaterialTheme.colors.primary,
            modifier = Modifier.padding(vertical = 4.dp, horizontal = 8.dp)
        ) {
            Row(modifier = Modifier.padding(24.dp)) {
                Column(modifier = Modifier.weight(1f)) {
                    Text(text = "Hello, ")
                    Text(text = name)
                }
                OutlinedButton(
                    onClick = { /* TODO */ }
                ) {
                    Text("Show more")
                }
            }
        }
    }
    

    相关文章

      网友评论

          本文标题:Jetpack Compose 基础知识

          本文链接:https://www.haomeiwen.com/subject/lsyxgrtx.html