Note_Android

朋友vibe了一个安卓端的Quiz APP,于是对安卓开发有点兴趣。找到Google官网的入门教程,学习了最简单的项目写法。简要记录如下:

IDE

Android Studio Quail 2 | 2026.1.2

注意点:

访问 dl.google.com 需要改host文件

gradle 更新和换镜像源

Project1:Greeting Card

Template

旧:Surface Container

新:Edge-to-Edge + Scaffold Container

官方示例,存在三种组合:

1)未开启EdgetoEdge,并使用Surface Container

效果:状态栏为亮色,内容为暗色,且内容与时间图标重叠。

2)开启EdgetoEdge,但还是使用Surface Container

效果:状态栏和内容均为暗色,但内容还是与时间图标重叠。

3)开启EdgetoEdge,并使用Scaffold Container

效果:状态栏和内容均为暗色,且内容不再与状态栏重叠了。

评价:3>2>1。

结论:建议使用Edge-to-Edge + Scaffold Container模板取代Surface Container。


onCreate()

The onCreate() function is the entry point to this Android app and calls other functions to build the user interface. In Kotlin programs, the main() function is the entry point/starting point of execution. In Android apps, the onCreate() function fills that role.

onCreate()是整个App的入口,相当于Kotlin程序中的main()函数。

setContent()

fun setContent(content: @Composable () -> Unit): Unit

Set the Jetpack Compose UI content for this view. Initial composition will occur when the view becomes attached to a window or when createComposition is called, whichever comes first.

The setContent() function within the onCreate() function is used to define your layout through composable functions. All functions marked with the @Composable annotation can be called from the setContent() function or from other Composable functions. The annotation tells the Kotlin compiler that this function is used by Jetpack Compose to generate the UI.


Jetpack Compose

Jetpack Compose is Android's recommended modern toolkit for building native UI. It simplifies and accelerates UI development on Android. Quickly bring your app to life with less code, powerful tools, and intuitive Kotlin APIs.

Jetpack Compose核心概念表

核心概念 通俗大白话 (是什么) 核心关键词 (怎么记)
@Composable UI 积木块。标记这只函数是用来画界面的。 函数式 UI、首字母大写、不能在普通函数里调用
Modifier 衣服/皮肤。用来改尺寸、换皮肤、加点击事件。 链式调用、顺序决定一切、无 Margin 概念
State & Recomposition 数据和刷新。数据变了,界面自动重新运行。 数据驱动、局部智能刷新、拒绝频繁触发
Declarative UI 设计理念。只声明界面长什么样,不管怎么画。 告别 findViewById、状态同步、懒人式 UI
Side-Effects 安全防护锁。在频繁刷新的组件里安全搞网络请求。 生命周期感知、防重复触发、控制外部逻辑

@Composable

API reference | Android Developers

Composable functions are the fundamental building blocks of an application built with Compose.

Composable can be applied to a function or lambda to indicate that the function/lambda can be used as part of a composition to describe a transformation from application data into a tree or hierarchy.

Annotating a function or expression with Composable changes the type of that function or expression. For example, Composable functions can only ever be called from within another Composable function. A useful mental model for Composable functions is that an implicit "composable context" is passed into a Composable function, and is done so implicitly when it is called from within another Composable function. This "context" can be used to store information from previous executions of the function that happened at the same logical point of the tree.

语义:Compose: to combine together to form a whole -> Composable:可组合的

语法@Composable:注解,用来告诉编译器,这是一个用来标记、绘制UI页面的函数。

意义:@Composable 是 Jetpack Compose 的核心灵魂。被其修饰的函数被称为组件Composable函数

Q:判断一个函数是普通Kotlin函数还是Composable函数最简单的方法:

看函数名首字母

在规范的开发中,所有被 @Composable 修饰的函数,函数名的首字母都是大写的(例如 GreetingTextSurface),而我们平时写的普通 Kotlin 函数首字母通常是小写的(例如 onCreateenableEdgeToEdge)。

Q:@Composable与普通函数的区别有哪些:

  1. @Composable annotation before the function.
  2. @Composable function names are capitalized.
  3. @Composable functions can't return anything.

Modifier

An ordered, immutable collection of modifier elements that decorate or add behavior to Compose UI elements. For example, backgrounds, padding and click event listeners decorate or add behavior to rows, text or buttons.

特点:

  • 链式调用

简单使用方法参见Iteration2

@Preview

To enable a preview of one composable, create another composable, annotated with @Composable and @Preview.

The @Preview annotation tells Android Studio that this composable should be shown in the design view of this file.

One of the primary benefits of using @Preview composables is to avoid reliance on the emulator in Android Studio. You can save the memory-heavy startup of the emulator for more final look-and-feel changes, and @Preview's ability to make and test small code changes with ease.

showBackground属性:值为true时,为组件预览填充背景,否则背景为透明。

@Preview注解的函数一般在原函数后加Preview来命名。简单例子如下:

@Composable
fun SimpleComposable() {
    Text("Hello World")
}

@Preview
@Composable
fun SimpleComposablePreview() {
    SimpleComposable()
}

Iteration1

需求:change the background color. = 为文本框加上背景色填充。

步骤点:

1)找到Greeting()函数中的文本框位置:Text()

  • 选中Text()并利用Android Studio中的快捷键:Alt+Enter 快速添加容器

2)将默认的容器Box替换为Surface()

  • 使用Surface()的color属性,设置容器颜色
  • 未引用依赖时,输入Color会飘红

3)添加androidx.compose.ui.graphics.Color依赖,并对依赖进行整理

  • 可利用Top Toolbar -> Help -> Find Action,快速找到想使用的 Action1
  • 可利用Top Toolbar -> Code -> Optimize imports,快速删除未使用依赖

Completed:

@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
//  使用Surface容器,缺点:会与状态栏重叠。
    Surface(color = Color.Cyan) {
        Text(
            text = "Hi, my name is $name!",
            modifier = modifier
        )
    }
}

Issue1:

Surface()会与状态栏重叠。

Solution1

Scaffold()代替Surface().

@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
//  重构方法:使用Scaffold取代Surface
    Scaffold(
        modifier = modifier, // 将传入的 modifier 给最外层的容器
        containerColor = Color.Red
    ) { innerPadding -> // Scaffold 会提供一个避开系统栏的 padding
        Text(
            text = "Hi, my name is $name!",
            // 必须通过 Modifier.padding(innerPadding) 把安全边距应用到内部的 Text 上
            modifier = Modifier.padding(innerPadding)
        )
    }
}

Problem: Scaffold占用的空间太大,不适合小组件。

⚠️小提示

在实际开发中,Scaffold 通常被用作整个页面的根底座(也就是全屏显示)。

如果你只是想做一个局部的小卡片、小方块并改变它的宽高,官方更推荐使用 SurfaceBox。因为 Scaffold 天生设计用来承载状态栏、导航栏等全屏组件,强行把它缩得很窄,它内部的计算可能会变得有些奇怪。

Solution2

将修饰符加在Text

Surface(
    modifier = modifier.fillMaxSize(), // 让容器填满整个屏幕
    color = Color.Cyan
) {
    Text(
        text = "Hi, my name is $name!",
        // 仅仅让文字避开顶部状态栏
        modifier = Modifier.statusBarsPadding() 
    )
}

Problem: 仅有文字避开了状态栏,Surface()容器还是会和状态栏重叠。

Solution3

Solution3.1:statusBarsPadding()

Surface()内加入修饰符statusBarsPadding(),作用:自动去计算顶部状态栏的高度,并转化为对应的内边距(Padding),完美避开重叠。

@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
    Surface(
        // 将传入的 modifier 与 statusBarsPadding 链式拼接
        modifier = modifier.statusBarsPadding(), 
        color = Color.Cyan
    ) {
        Text(
            text = "Hi, my name is $name!",
            // 这里的 modifier 就不需要再重复处理状态栏了
        )
    }
}

Solution3.2:safeDrawingPadding()

一次性避开所有不安全区域。包括:顶部状态栏,底部导航栏,刘海屏,挖孔屏等。

Surface(
    modifier = modifier.safeDrawingPadding(), // 自动避开四周所有系统栏和挖孔
    color = Color.Cyan
) {
    Text(text = "Hi, my name is $name!")
}

个人感觉2≈3>1

Iteration2

需求:add some space (padding) around the text. = 增加文本周围的填充空间。

介绍:

A Modifier is used to augment or decorate a composable. One modifier you can use is the padding modifier, which adds space around the element (in this case, adding space around the text). This is accomplished by using the Modifier.padding() function.

步骤点:

1)为modifier添加一个尺寸为 24.dp 的padding。

2)添加依赖

import androidx.compose.ui.unit.dp
import androidx.compose.foundation.layout.padding

Completed:

@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
    Surface(
        modifier = modifier.statusBarsPadding(),
        color = Color.Cyan
    ) {
        Text(
            text = "Hi, my name is $name!",
            modifier = modifier.padding(24.dp) // 新增行
        )
    }
}

Conclusion

Project1完结撒花。入门,看这么简单的项目很是享受。单文件,最简单皮实的文本框显示。

Annotation

可以把 Android Studio 想象成一个巨大的工具箱,里面有上千个工具(按钮、菜单项、设置页)。平时你要找“格式化代码”这个工具,得先点开 Code 菜单,再往下找 Reformat Code。而 Find Action 相当于一个语音遥控器。你不需要知道这个工具放在哪个抽屉里,只要对着遥控器喊出功能的名字(如 “Format”),它立刻就把这个工具高亮送到你面前。

parentheses=()


  1. 万物皆 Action。

评论