听说现在移动客户端已经逐渐没落了?为了应付实习,学习一下安卓客户端的简单用法。
本文章大部分内容都是从Android官方教程学习而来,若有侵权,可联系我删除。
虽千万人,吾往矣。
利用Jetpack Compose组件制作一个文本生日贺卡
Jetpack Compose介绍
Jetpack Compose 是 Google 提供的一个现代 Android UI 工具包,它极大地简化了构建原生 Android UI 的方式。Compose 使用 Kotlin 语言的构建和功能,允许开发者以一种更声明式和直观的方式来设计和构建复杂的用户界面。
以下是 Jetpack Compose 的一些关键特性:
- 声明式 UI:Compose 允许你使用 Kotlin 代码以声明的方式构建原生 Android UI,这使得 UI 的构建和维护更加简单。
- 响应式更新:在 Compose 中,UI 会自动响应状态变化。当应用的状态发生变化时,UI 会自动更新,无需手动刷新。
- 预构建的 UI 组件:Compose 提供了一系列预构建的 UI 组件(widgets),这些组件都是用 Kotlin 编写的,并且可以自由组合以构建丰富的用户界面。
- 动画和过渡效果:Compose 提供了简单易用的 API 来创建复杂的动画和过渡效果。
- 与现有 Views 兼容:Compose 可以与 Android 的传统 Views 共存,允许你在同一个应用中同时使用 Compose 和传统的 Views。
- 工具和插件支持:Android Studio 提供了对 Compose 的全面支持,包括预览功能、代码自动补全、实时模板等。
- 模块化:Compose 被设计为模块化,你可以按需添加或移除模块,这有助于控制应用的大小。
- Material Design 集成:Compose 与 Material Design 紧密集成,提供了一套遵循 Material Design 指南的预构建组件。
- 测试:Compose 支持 UI 的单元测试和界面测试,可以更容易地验证应用的 UI 行为。
- 性能:Compose 旨在提供高性能的 UI,它优化了渲染流程,减少了过度绘制和不必要的 UI 更新。
使用 Jetpack Compose,你可以创建平滑、反应灵敏且视觉上吸引人的 Android 应用界面。随着 Android 开发社区的不断进步,Compose 已经成为构建 Android UI 的推荐方法之一。
要开始使用 Jetpack Compose,你需要在你的项目中的 build.gradle
文件中添加 Compose 的依赖项。以下是如何添加这些依赖项的示例:
arduino
复制
dependencies {
// 添加 Compose UI 核心库
implementation "androidx.compose.ui:ui:版本号"
// 添加 Compose 的 Material Design 组件
implementation "androidx.compose.material:material:版本号"
// 添加 Compose 的工具包,用于 UI 工具和布局
implementation "androidx.compose.ui:ui-tooling:版本号"
// 添加 Kotlin 编译器插件
kotlinCompilerPlugin "androidx.compose.compiler:compiler:版本号"
}
请将 "版本号"
替换为适用于你项目的 Compose 库的最新版本。
准备工作
- 一台安装了Android Studio的电脑
- 了解简单的编程语言语法
开始
创建 Empty Activity 项目
- 在 Welcome to Android Studio 对话框中,选择 New Project。
- 在 New Project 对话框中,选择 Empty Activity ,然后点击 Next。
- 在 Name 字段中输入
Happy Birthday
,在 Minimum SDK 字段中选择最低 API 级别 24 (Nougat),然后点击 Finish。
- 等待 Android Studio 创建项目文件并构建项目。
- 点击 Run 'app' 。
应用应如下面的屏幕截图所示:
在您使用 Empty Activity 模板创建这个 Happy Birthday 应用时,Android Studio 会设置基本 Android 应用所需的各项资源,包括在屏幕上显示的 Hello Android! 消息。在本 Codelab 中,您将了解如何放置该消息、如何将其文本更改为生日祝福,以及如何添加额外的消息并为其设置格式。
Android Studio中的"Design"窗口
Android Studio 允许您在 IDE 中预览可组合函数,无需将应用安装到 Android 设备或模拟器中。正如您在之前的在线课程中学到的,您可以在 Android Studio 的 Design 窗格中预览应用的外观。
可组合函数必须为任何参数提供默认值才能对其进行预览。因此,我们建议您不要直接预览 Greeting()
函数,而是需要添加另一个函数(在本例中为 BirthdayCardPreview()
函数),由该函数使用适当的参数调用 Greeting()
函数。
less
@Preview(showBackground = true)
@Composable
fun BirthdayCardPreview() {
HappyBirthdayTheme {
Greeting("Android")
}
}
提示 :点击 Split 可同时查看代码和设计预览。
如需查看预览,请执行以下操作:
- 在
BirthdayCardPreview()
函数中,将Greeting()
函数中的"Android"
实参更改为您的名字。**
less
@Preview(showBackground = true)
@Composable
fun BirthdayCardPreview() {
HappyBirthdayTheme {
Greeting("James")
}
}
- 构建代码。预览会自动更新。
您应看到更新后的预览。
自定义更改问候语
添加新的可组合函数
- 在
MainActivity.kt
文件中,删除Greeting()
函数定义。在此 Codelab 稍后的部分,您将添加自己的函数,用于显示生日祝福。
移除以下代码
kotlin
@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
Text(
text = "Hello $name!",
modifier = modifier
)
}
- 在
onCreate()
函数内,您会看到Greeting()
函数调用现在显示为红色。红色表示存在错误。将光标悬停在此函数调用上,Android Studio 将显示有关该错误的信息。
- 从
onCreate()
和BirthdayCardPreview()
函数中删除Greeting()
函数调用及其实参。此时MainActivity.kt
文件将如下所示:
kotlin
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
HappyBirthdayTheme {
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
}
}
}
}
}
@Preview(showBackground = true)
@Composable
fun BirthdayCardPreview() {
HappyBirthdayTheme {
}
}
- 在
BirthdayCardPreview()
函数前,添加一个名为GreetingText()
的新函数。不要忘记在该函数前添加@Composable
注解,因为该函数是一个用于描述Text
可组合项的 Compose 函数。
kotlin
@Composable
fun GreetingText() {
}
- 最好让可组合项接受
Modifier
形参,并将该modifier
传递给其第一个子项。在后续任务和 Codelab 中,您将详细了解Modifier
和子元素。现在,请向GreetingText()
函数添加Modifier
形参。
kotlin
@Composable
fun GreetingText(modifier: Modifier = Modifier) {
}
- 将类型为
String
的message
形参添加到GreetingText()
可组合函数中。
kotlin
@Composable
fun GreetingText(message: String, modifier: Modifier = Modifier) {
}
- 在
GreetingText()
函数中,添加一个Text
可组合项并传入文本消息作为具名实参。
kotlin
@Composable
fun GreetingText(message: String, modifier: Modifier = Modifier) {
Text(
text = message
)
}
此 GreetingText()
函数用于在界面中显示文本。为此,它会调用 Text()
可组合函数。
预览函数
在此任务中,您将在 Design 窗格中预览 GreetingText()
函数。
- 在
BirthdayCardPreview()
函数中调用GreetingText()
函数。 - 将一个
String
参数(其内容是对朋友的生日祝福)传递给GreetingText()
函数。如果愿意,您可以使用朋友的名字进行自定义,例如"Happy Birthday Sam!"
。
less
@Preview(showBackground = true)
@Composable
fun BirthdayCardPreview() {
HappyBirthdayTheme {
GreetingText(message = "Happy Birthday Sam!")
}
}
- 在 Design 窗格中,系统会自动更新。预览您所做的更改。
修改文本框的属性
更改字体大小
您已将文本添加到界面中,但它看起来和最终应用还不太一样。在此任务中,您将了解如何更改大小、文本颜色以及影响文本元素外观的其他属性。此外,您还可以尝试使用不同的字体大小和颜色。
可缩放像素
可缩放像素 (SP) 是字体大小的度量单位。**Android 应用中的界面元素使用两种不同的度量单位:一种是您稍后将为布局使用的密度无关像素 (DP),另一种就是可缩放像素 (SP)。**默认情况下,SP 单位与 DP 单位大小相同,但前者的大小会根据用户在手机设置下的首选文本大小进行调整。
- 在
MainActivity.kt
文件中,滚动到GreetingText()
函数中的Text()
可组合项。 - 向
Text()
函数传递fontSize
实参作为第二个具名实参,并将其值设为100.``sp
。**
ini
Text(
text = message,
fontSize = 100.sp
)
Android Studio 突出显示了 .sp
代码,因为您需要导入一些类或属性来编译应用。
- 点击 Android Studio 突出显示的
.sp
。 - 点击弹出式窗口中的 Import 导入
androidx.compose.ui.unit.sp
,以使用.sp
扩展属性。
注意 :AndroidX(Android 扩展)库包含一组库和类,通过提供核心功能帮助您加快应用开发。您可以使用 androidx
软件包获得这些类、属性和其他工件。
- 滚动到文件顶部,您会发现一些
import
语句,其中有一个import androidx.compose.ui.unit.sp
语句,这表示 Android Studio 会将此软件包添加到您的文件中。
注意: 如果使用 Android Studio 导入遇到问题,可以在文件顶部手动添加 import 语句。
- 请注意更新后的字体大小预览。消息重叠的原因是您需要指定行高。
注意: sp
是 Int
的扩展属性,用于创建 sp
单位。同样,您也可以在 Float
和 Double
等其他数据类型中使用 .sp
扩展属性。
- 更新
Text
可组合项以包含行高。
kotlin
@Composable
fun GreetingText(message: String, modifier: Modifier = Modifier) {
Text(
text = message,
fontSize = 100.sp,
lineHeight = 116.sp,
)
}
现在,您可以尝试使用不同的字体大小。
再添加一个文本元素
在前面的任务中,您添加了一句对朋友的生日祝福语。在此任务中,您将在生日卡上签上自己的名字。
- 在
MainActivity.kt
文件中,滚动到GreetingText()
函数。 - 向该函数传递一个类型为
String
的from
参数作为您的签名。
kotlin
fun GreetingText(message: String, from: String, modifier: Modifier = Modifier)
注意:如果您在函数调用中使用的是具名实参,那么函数形参的顺序就无关紧要。
- 在生日祝福语
Text
可组合项之后,再添加一个接受text
实参(其值设为from
)的Text
可组合项。
kotlin
@Composable
fun GreetingText(message: String, from: String, modifier: Modifier = Modifier) {
Text(
// ...
)
Text(
text = from
)
}
- 添加一个
fontSize
具名实参,并将其值设为36.sp
。
ini
Text(
text = from,
fontSize = 36.sp
)
- 滚动到
BirthdayCardPreview()
函数。 - 再添加一个
String
实参来为生日卡签名,例如"From Emma"
。
ini
GreetingText(message = "Happy Birthday Sam!", from ="From Emma")
- 请注意预览结果。
一个可组合函数可能会描述多个界面元素。不过,如果您未提供有关如何排列这些元素的指导,Compose 可能会以您不喜欢的方式排列它们。例如,上面的代码生成了两个相互重叠的文本元素,因为您没有提供有关如何排列这两个可组合项的指导。
在下一个任务中,您将了解如何将可组合项排列成一行或一列。
将文本元素排列成一行或者一列
界面层次结构
界面层次结构基于包含机制,意即一个组件可以包含一个或多个组件,有时会用"父级"和"子级"这两个词来表述。这种说法是指,父界面元素包含子界面元素,而子界面元素还可以继续包含子界面元素。在此部分中,您将了解可用作父界面元素的 Column
、Row
和 Box
可组合项。
Compose 中的 3 个基本标准布局元素是 Column
、Row
和 Box
可组合项。下一个 Codelab 会详细介绍 Box
可组合项。
Column
、Row
和 Box
都是接受可组合内容作为参数的可组合函数,因此您可以在这些布局元素内放置项目。例如,Row
可组合项中的各个子元素彼此相邻地水平放置成一行。
scss
// Don't copy.
Row {
Text("First Column")
Text("Second Column")
}
这些文本元素会在屏幕上并排显示,如下图所示。
蓝色边框仅用于演示目的,不会实际显示。
尾随 lambda 语法
请注意,在上一个代码段中,Row
可组合函数中使用的是花括号而不是圆括号。这称为尾随 Lambda 语法。**本课程稍后会详细介绍 lambda 和尾随 lambda 语法。**现在,您只需要熟悉这个常用的 Compose 语法。
当最后一个形参是函数时,Kotlin 提供了一种特殊语法来将函数作为形参传递给函数。
将函数作为形参传递时,您可以使用尾随 lambda 语法。此语法不是将函数正文连同函数名称一起放在括号 ({}
) 内,而是将括号和函数正文放在函数名称后面。这是 Compose 中的一种常见且推荐的做法,因此您需要熟悉代码的格式。
例如,Row()
可组合函数中的最后一个形参是 content
形参,它是一个描述子界面元素的函数。假设您想要创建一个包含三个文本元素的行。以下代码行得通,但如果为尾随 lambda 使用具名形参,则非常麻烦:
scss
Row(
content = {
Text("Some text")
Text("Some more text")
Text("Last text")
}
)
由于 content
形参是函数签名中的最后一个形参,并且您要将其值作为 lambda 表达式传递(目前,如果您不知道 lambda 是什么也没关系,只需要熟悉一下语法即可),因此您可以移除 content
形参和括号,如下所示:
scss
Row {
Text("Some text")
Text("Some more text")
Text("Last text")
}
将文本元素排列成一行
在此任务中,您要将应用中的文本元素排列成一行,以免相互重叠。
- 在
MainActivity.kt
文件中,滚动到GreetingText()
函数。 - 添加
Row
可组合项将文本元素括起来,以显示包含两个文本元素的一行。选择两个Text
可组合项,然后点击灯泡。依次选择 Surround with widget > Surround with Row。
现在,该函数应如下面的代码段所示:
ini
@Composable
fun GreetingText(message: String, from: String, modifier: Modifier = Modifier) {
Row {
Text(
text = message,
fontSize = 100.sp,
lineHeight = 116.sp,
)
Text(
text = from,
fontSize = 36.sp
)
}
}
- Android Studio 会自动为您导入
Row
函数。滚动到顶部,然后观察"import"部分。import androidx.compose.foundation.layout.Row
应该已添加。 - 观察 Design 窗格中更新后的预览。暂时将生日祝福语的字体大小更改为
30.sp
。
现在,因为元素不再重叠,预览的效果大为改善。不过,这仍然不是您想要的效果,因为没有充足的空间显示签名。在下一个任务中,您要将文本元素排列成一列来解决此问题。
将文本元素排列成一列
在此任务中,该由您更改 GreetingText()
函数来将文本元素排成一列了。预览应如下面的屏幕截图所示:
既然您已尝试自行完成了此任务,那么现在您可以对照以下代码段中的解决方案代码检查您自己的代码:
ini
@Composable
fun GreetingText(message: String, from: String, modifier: Modifier = Modifier) {
Column {
Text(
text = message,
fontSize = 100.sp,
lineHeight = 116.sp
)
Text(
text = from,
fontSize = 36.sp
)
}
}
请注意 Android Studio 自动导入的软件包:
arduino
import androidx.compose.foundation.layout.Column
回想一下,您需要将修饰符形参传递给可组合项中的子元素。这意味着,您需要将修饰符形参传递给 Column
可组合项。
ini
@Composable
fun GreetingText(message: String, from: String, modifier: Modifier = Modifier) {
Column(modifier = modifier) {
Text(
text = message,
fontSize = 100.sp,
lineHeight = 116.sp
)
Text(
text = from,
fontSize = 36.sp
)
}
}
向应用添加问候语
对预览效果感到满意后,即可在设备或模拟器上向应用添加可组合项。
- 在
MainActivity.kt
文件中,滚动到onCreate()
函数。 - 从
Surface
代码块调用GreetingText()
函数。 - 传递
GreetingText()
函数、您的生日祝福和签名。
完成后的 onCreate()
函数应该会如同下面的代码段所示:
kotlin
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
HappyBirthdayTheme {
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
GreetingText(message = "Happy Birthday Sam!", from = "From Emma")
}
}
}
}
}
- 在模拟器中构建并运行您的应用。
将问候语居中对齐
- 如需在屏幕中心对齐问候语,请添加一个名为
verticalArrangement
的形参,并将其设置为Arrangement.Center
。在后续 Codelab 中,您将详细了解verticalArrangement
。
kotlin
@Composable
fun GreetingText(message: String, from: String, modifier: Modifier = Modifier) {
Column(
verticalArrangement = Arrangement.Center,
modifier = modifier
) {
// ...
}
}
- 围绕列添加
8.dp
内边距。最好以4.dp
为增量使用内边距值。
kotlin
@Composable
fun GreetingText(message: String, from: String, modifier: Modifier = Modifier) {
Column(
verticalArrangement = Arrangement.Center,
modifier = modifier.padding(8.dp)
) {
// ...
}
}
- 如需进一步美化应用,请使用
textAlign
将问候语文本居中对齐。
ini
Text(
text = message,
fontSize = 100.sp,
lineHeight = 116.sp,
textAlign = TextAlign.Center
)
在上面的屏幕截图中,由于使用了 textAlign
形参,因此只有问候语居中对齐。签名 From Emma 采用默认的对齐方式。
- 为签名添加内边距,并使其右对齐。
ini
Text(
text = from,
fontSize = 36.sp,
modifier = Modifier
.padding(16.dp)
.align(alignment = Alignment.End)
)
采用最佳实践
最好从父级可组合项传递修饰符属性和修饰符。更新 GreetingText()
中的修饰符形参,如下所示:
onCreate()
ini
Surface(
//...
) {
GreetingText(
message = "Happy Birthday Sam!",
from = "From Emma",
modifier = Modifier.padding(8.dp)
)
}
GreetingText()
kotlin
@Composable
fun GreetingText(message: String, from: String, modifier: Modifier = Modifier) {
Column(
verticalArrangement = Arrangement.Center,
modifier = modifier
) {
// ...
}
}
在模拟器上构建并运行应用以查看最终结果。
完整代码
完成后的 MainActivity.kt
:
kotlin
package com.example.happybirthday
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.example.happybirthday.ui.theme.HappyBirthdayTheme
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
HappyBirthdayTheme {
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
GreetingText(
message = "Happy Birthday Sam!",
from = "From Emma",
modifier = Modifier.padding(8.dp)
)
}
}
}
}
}
@Composable
fun GreetingText(message: String, from: String, modifier: Modifier = Modifier) {
Column(
verticalArrangement = Arrangement.Center,
modifier = modifier
) {
Text(
text = message,
fontSize = 100.sp,
lineHeight = 116.sp,
textAlign = TextAlign.Center
)
Text(
text = from,
fontSize = 36.sp,
modifier = Modifier
.padding(16.dp)
.align(alignment = Alignment.End)
)
}
}
@Preview(showBackground = true)
@Composable
fun BirthdayCardPreview() {
HappyBirthdayTheme {
GreetingText(message = "Happy Birthday Sam!", from = "From Emma")
}
}
总结
- Jetpack Compose 是用于构建 Android 界面的新款工具包。它使用更少的代码、强大的工具和直观的 Kotlin API,可以帮助您简化并加快 Android 界面开发。
- 应用的界面 (UI) 就是您在屏幕上所看到的内容,包括文本、图片、按钮和许多其他类型的元素。
- 可组合函数是 Compose 的基本构建块。可组合函数是用于描述界面中某一部分的函数。
- 可组合函数带有
@Composable
注解;此注解可告知 Compose 编译器:此函数用于将数据转换为界面。 - Compose 中的三个基本标准布局元素是
Column
、Row,
和Box
。它们是接受可组合内容的可组合函数,因此您可以在其中放置项目。例如,Row
中的各个子项将彼此相邻地水平放置。