第一单元:构建基本布局
💡核心概念:Jetpack Compose 使用声明式 UI范式,你只需描述界面"长什么样",Compose 会自动处理如何渲染。通过可组合函数(Composable Functions),你可以用 Kotlin 代码构建整个用户界面,告别传统 XML 布局文件。
📋 本单元学习目标
- ✅ 理解什么是界面(UI)以及它的作用
- ✅ 掌握可组合函数(Composable Functions)的概念与用法
- ✅ 使用
Text、Column、Row等基础布局元素构建界面 - ✅ 理解并运用 Modifier(修饰符)来控制界面样式
- ✅ 了解注解(Annotation)在 Compose 中的作用
- ✅ 完成一个生日祝福卡片应用
🎨 什么是界面(UI)?
应用的**用户界面(UI)**就是我们在屏幕上看到的一切内容——文本、图片、按钮以及各种交互元素,以及它们在屏幕上的排列方式。
UI 既是应用向用户展示内容的方式,也是用户与应用程序交互的载体。一个良好的 UI 设计直接影响用户体验。
💡提示:在 Compose 中,UI 不再由 XML 文件定义,而是通过 Kotlin 函数来描述——这让我们可以用代码的逻辑思维来构建界面。
🚀 什么是 Jetpack Compose?
Jetpack Compose是 Google 推出的用于构建 Android 原生界面的现代化 UI 工具包。相比传统的 View 系统,Compose 具有以下核心优势:
| 特性 | 说明 |
|---|---|
| 更少的代码 | 用更简洁的声明式语法替代冗长的 XML 布局 |
| 强大的工具 | 实时预览、Material You 动态取色等开箱即用 |
| 直观的 Kotlin | 使用 Kotlin 函数构建界面,逻辑与 UI 合一 |
借助 Compose,开发者通过定义一组函数来构建页面,这些函数称为可组合函数(Composable Functions)。它们接收数据作为输入,并描述屏幕上应显示的内容。
📦 可组合函数
什么是可组合函数?
可组合函数是 Compose 中构建 UI 的基本构建块。它具备以下特征:
- 描述界面的一部分(如一个文本、一个按钮或一组元素)
- 不返回任何值,而是直接"组合"出界面对象
- 接收一些输入参数(如文本内容、样式等),生成屏幕上显示的内容
注解(Annotation)
注解是用于在代码中附加额外元信息的方式。这些信息可以帮助 Compose 编译器、其他开发者理解代码的用途和行为。
💡语法提示:在需要注解的声明开头添加
@字符作为前缀即可。注解可以应用于属性、函数、类等各种代码元素。
带注解的属性示例:
// 示例代码,请勿复制使用@JsonvalimgSrcUrl:String@VolatileprivatevarINSTANCE:AppDatabase?=null带参数的注解
注解还可以携带参数,为处理它们的工具提供额外的配置信息。
可组合函数示例
可组合函数必须使用@Composable注解进行标记。该注解告诉 Compose 编译器:此函数用于将数据转换为界面。
一个简单的可组合函数示例:
@ComposablefunGreeting(name:String){Text(text="Hello$name!")}💡理解要点:
@Composable是 Compose 的"身份证"——没有它,函数就只是一个普通的 Kotlin 函数;有了它,Compose 编译器就知道需要对这个函数进行特殊处理,以便生成界面元素。
✏️ 设置文本样式
更改字体大小
Text(text=message,fontSize=100.sp// 修改此值即可改变字体大小)⚠️注意:如果只调整字体大小而不调整行高,文字的行间距会显得非常紧凑。
为获得更好的视觉效果,需要同时设置lineHeight(行高):
@ComposablefunGreetingText(message:String,modifier:Modifier=Modifier){Text(text=message,fontSize=100.sp,lineHeight=116.sp,// 行高通常比字体大 16dp 左右)}📝 添加多个文本元素
现在我们来添加第二个文本元素(签名):
// 在函数参数中增加一个 from 参数funGreetingText(message:String,from:String,modifier:Modifier=Modifier)// 添加第二个 Text 组件@ComposablefunGreetingText(message:String,from:String,modifier:Modifier=Modifier){Text(text=message)Text(text=from)}// 在预览函数中调用GreetingText(message="Happy Birthday Sam!",from="From Emma")如果直接添加而不指定排列方式,两个文本会重叠在一起:
💡思考:为什么会出现这种情况?因为默认情况下,多个元素没有指定排列方向,它们会堆叠在同一位置。我们需要使用布局容器来解决这个问题。
🏗️ 界面层次结构与布局元素
什么是界面层次结构?
界面层次结构基于包含机制——一个组件可以包含一个或多个子组件。在层级关系中,我们通常使用**父级(Parent)和子级(Child)**来描述这种关系。
Compose 中的三大基础布局元素
Compose 提供了三个最基本的布局可组合项:Column、Row和Box。
Row:将子元素水平排列成一行Column:将子元素垂直排列成一列Box:将子元素重叠堆叠在一起
Row 示例
// 请勿复制使用Row{Text("第一个元素")Text("第二个元素")}🔤 尾随 Lambda 语法
在上面的代码中,Row可组合函数使用的是花括号{}而不是圆括号()。这就是 Kotlin 中的尾随 Lambda(Trailing Lambda)语法。
💡原理:当函数的最后一个参数是一个函数类型时,Kotlin 提供了一种简洁的语法——将 Lambda 表达式放在圆括号之外的大括号中。
将函数作为参数传递时,可以使用尾随 Lambda 语法,使代码更加简洁易读。
例如,Row的最后一个参数是content,它是一个描述子元素的函数。如果要创建一个包含三个元素的行,可以这样写:
// 完整写法(使用圆括号)Row(content={Text("文本一")Text("文本二")Text("文本三")})由于content是最后一个参数,我们可以使用更简洁的尾随 Lambda 形式:
// 简洁写法(尾随 Lambda)Row{Text("文本一")Text("文本二")Text("文本三")}💡记忆技巧:尾随 Lambda 就是"把最后那个函数参数拿出来,放在括号外面用花括号包起来"。
📐 排列文本元素
将文本排成一行(Row)
@ComposablefunGreetingText(message:String,from:String,modifier:Modifier=Modifier){Row{Text(text=message,fontSize=100.sp,lineHeight=116.sp,)Text(text=from,fontSize=36.sp)}}预览效果:
将文本排成一列(Column)
@ComposablefunGreetingText(message:String,from:String,modifier:Modifier=Modifier){Column{Text(text=message,fontSize=100.sp,lineHeight=116.sp,)Text(text=from,fontSize=36.sp)}}预览效果:
🔧 Modifier(修饰符)的作用
为什么需要传递 Modifier?
我们需要将modifier参数传递给可组合项中的子元素(如Column),这样才能对外部传入的样式进行统一控制。
@ComposablefunGreetingText(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)}}Modifier 的作用范围规则
⚠️核心规则:谁加 Modifier,效果就作用在谁自身。
场景一:Modifier 加在 Column 上(推荐)
如果你把modifier传给Column,那么内边距、背景、阴影、对齐、宽高、点击事件等全部作用在整个 Column 容器上(两行文字整体生效)。
// 外部传入的修饰统一作用于整个 Column(两行文字整体)Column(modifier=modifier){Text(message)Text(from)}外部调用:
GreetingText(message="Hello",from="Android",modifier=Modifier.padding(20.dp).background(Color.Gray))场景二:Modifier 加在每个 Text 上(不推荐)
如果不给 Column 传递 Modifier,而是单独给两个 Text 分别加修饰,就需要重复写两遍padding/background,代码冗余,且两个文字会各自独立修饰,中间没有统一的容器样式。
// ❌ 不推荐:代码冗余,样式不统一Column(){Text(text=message,modifier=Modifier.padding(20.dp).background(Color.Gray))Text(text=from,modifier=Modifier.padding(20.dp).background(Color.Gray))}💡最佳实践:优先将 Modifier 加在布局容器(如 Column、Row)上,这样既能保证样式统一,又能减少代码重复。
🏃 在真实应用中运行
预览效果满意后,我们就可以在真实的MainActivity中调用自定义的可组合函数了。
操作步骤:
- 找到
MainActivity中的onCreate函数 - 在
setContent代码块中调用自己创建的可组合函数 - 给可组合函数传递相应的参数
onCreate 代码:
classMainActivity:ComponentActivity(){overridefunonCreate(savedInstanceState:Bundle?){super.onCreate(savedInstanceState)setContent{HappyBirthdayTheme{Surface(modifier=Modifier.fillMaxSize(),color=MaterialTheme.colorScheme.background){GreetingText(message="Happy Birthday Sam!",from="From Emma")}}}}}模拟器运行结果:
🎯 美化界面
将内容居中对齐
如果需要将问候语垂直居中,需要添加verticalArrangement参数并设置为Arrangement.Center:
@ComposablefunGreetingText(message:String,from:String,modifier:Modifier=Modifier){Column(verticalArrangement=Arrangement.Center,modifier=modifier.padding(8.dp)){// ...}}💡提示:内边距值最好以
4.dp为增量使用(如 4dp、8dp、12dp、16dp),这样能保证界面元素的间距协调统一。
文本居中对齐
进一步美化,可以将主文本进行居中对齐:
Text(text=message,fontSize=100.sp,lineHeight=116.sp,textAlign=TextAlign.Center// 文本内容水平居中)运行效果:
签名右对齐并添加内边距
Text(text=from,fontSize=36.sp,modifier=Modifier.padding(16.dp)// 添加 16dp 的内边距.align(alignment=Alignment.End)// 右对齐)运行效果:
📜 完整代码示例
packagecom.example.happybirthdayimportandroid.os.Bundleimportandroidx.activity.ComponentActivityimportandroidx.activity.compose.setContentimportandroidx.compose.foundation.layout.Arrangementimportandroidx.compose.foundation.layout.Columnimportandroidx.compose.foundation.layout.fillMaxSizeimportandroidx.compose.foundation.layout.paddingimportandroidx.compose.material3.MaterialThemeimportandroidx.compose.material3.Surfaceimportandroidx.compose.material3.Textimportandroidx.compose.runtime.Composableimportandroidx.compose.ui.Alignmentimportandroidx.compose.ui.Modifierimportandroidx.compose.ui.text.style.TextAlignimportandroidx.compose.ui.tooling.preview.Previewimportandroidx.compose.ui.unit.dpimportandroidx.compose.ui.unit.spimportcom.example.happybirthday.ui.theme.HappyBirthdayThemeclassMainActivity:ComponentActivity(){overridefunonCreate(savedInstanceState:Bundle?){super.onCreate(savedInstanceState)setContent{HappyBirthdayTheme{Surface(modifier=Modifier.fillMaxSize(),color=MaterialTheme.colorScheme.background){GreetingText(message="Happy Birthday Sam!",from="From Emma",modifier=Modifier.padding(8.dp))}}}}}@ComposablefunGreetingText(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)@ComposablefunBirthdayCardPreview(){HappyBirthdayTheme{GreetingText(message="Happy Birthday Sam!",from="From Emma")}}🔗 参考链接
https://developer.android.com/courses/pathways/android-basics-compose-unit-1-pathway-3?hl=zh-cn#codelab-https://developer.android.com/codelabs/basic-android-kotlin-compose-text-composables
📌本单元小结:通过本单元的学习,我们掌握了 Compose 的核心概念——可组合函数、布局容器(Column/Row)以及 Modifier 修饰符的使用。这些是构建一切 Android UI 的基石,后续所有复杂的界面都可以基于这些基础元素组合而成。