从0开始学Jetpack Compose|第二篇:基础组件+核心布局,从零搭建实用UI

37 阅读9分钟

👋 哈喽大家好,欢迎回到Compose零基础系列~ 第一篇我们已经搞定了环境搭建、跑通了第一个Compose页面,还吃透了@Composable、@Preview、Modifier这几个核心基础概念,顺利迈出了入门第一步。

本篇作为系列第二篇,是新手实操的关键篇章,我们彻底告别单一的Text组件,全面学习Compose常用基础组件三大核心布局,这也是后续所有复杂UI开发的底层基础。全文依旧零基础友好,每一个知识点都搭配代码示例+效果说明,最后还会带大家实战做一个个人信息卡片,把所学内容落地,看完就能直接上手写简单页面!

本篇核心目标:掌握Text/Button/TextField/Image基础组件用法;吃透Column垂直、Row水平、Box层叠三大布局;熟练运用常用Modifier修饰符;独立完成简单卡片UI实战。

🔗 前文回顾:第一篇《告别XML,零基础上手Android现代声明式UI》,还没看的同学建议先补完,再学习本篇内容衔接更顺畅~

一、Modifier修饰符进阶:UI组件的“万能调节器”

第一篇我们简单提了Modifier的作用,它作为Compose UI的核心工具,几乎所有组件的样式、位置、交互都靠它实现,相当于传统XML里的layout_width、layout_margin、padding等属性的集合体,而且用法更灵活、更连贯,新手必须先把常用Modifier吃透。

1.1 常用基础Modifier(高频必记)

  • fillMaxSize() :让组件占满父布局的全部宽高,对应XML的match_parent
  • fillMaxWidth()/fillMaxHeight() :单独占满父布局宽度或高度
  • size(width, height) :给组件设置固定宽高,也可以用width()、height()单独设置
  • padding(value) :设置内边距,支持统一边距、单独设置上下左右(paddingStart/paddingTop等)
  • margin(value) :设置外边距,注意Compose中margin属于Modifier属性,和padding用法区分开
  • background(color) :设置组件背景颜色
  • clickable {} :给组件添加点击事件,替代传统setOnClickListener
  • align(Alignment) :设置组件在父布局中的对齐方式,配合Box、Column、Row使用

1.2 Modifier使用注意事项

Modifier的调用顺序会影响最终效果,比如先设置padding再设置background,和先设置background再设置padding,展示效果完全不同,新手建议先按照“尺寸→边距→背景→交互”的顺序编写,养成规范习惯。

// 正确示例:先内边距,再背景,最后点击事件
Modifier
    .padding(16.dp)
    .background(Color.LightGray)
    .clickable { /* 点击逻辑 */ }
    .fillMaxWidth()

💡 小贴士:Compose中尺寸单位默认用dp,文字尺寸用sp,与XML保持一致,直接在数值后加单位即可,无需额外转换。

二、Compose核心基础组件详解

Compose内置了大量开箱即用的组件,日常开发中高频使用的基础组件主要有Text、Button、TextField、Image四种,掌握它们的基础用法和常用配置,就能满足大部分简单UI需求,下面逐个拆解。

2.1 Text组件:文本展示核心

Text是最基础的文本展示组件,第一篇我们已经用过,这里补充常用配置,实现更丰富的文本样式。

@Composable
fun CommonText() {
    Text(
        text = "Compose零基础学习",
        fontSize = 18.sp, // 文字大小
        color = Color.Black, // 文字颜色
        fontWeight = FontWeight.Bold, // 文字加粗
        textAlign = TextAlign.Center, // 文字居中
        maxLines = 1, // 最大行数
        overflow = TextOverflow.Ellipsis, // 超出省略号
        modifier = Modifier
            .fillMaxWidth()
            .padding(12.dp)
    )
}

2.2 Button组件:点击交互按钮

Button是常用的点击按钮组件,默认自带Material3样式,支持自定义文案、点击事件、样式修改,适配大部分交互场景。

@Composable
fun CommonButton() {
    Button(
        onClick = {
            // 点击事件逻辑
            Log.d("ComposeButton", "按钮被点击了")
        },
        modifier = Modifier
            .padding(12.dp)
            .width(150.dp),
        colors = ButtonDefaults.buttonColors(
            containerColor = Color.Blue, // 按钮背景色
            contentColor = Color.White // 按钮文字颜色
        ),
        shape = RoundedCornerShape(8.dp) // 按钮圆角
    ) {
        // 按钮内部文案,嵌套Text组件
        Text(text = "点击提交")
    }
}

2.3 TextField组件:输入框

TextField对应XML的EditText,用于用户输入文本,是表单、登录、搜索页面的核心组件,需配合状态管理实现输入内容监听(本篇先讲基础用法,状态管理将在后续篇章详细讲解)。

@Composable
fun CommonTextField() {
    // 临时状态,后续篇章详解remember和mutableStateOf
    var inputText by remember { mutableStateOf("") }
    TextField(
        value = inputText,
        onValueChange = { inputText = it }, // 监听输入内容变化
        label = { Text("请输入用户名") }, // 输入框提示标签
        placeholder = { Text("请输入手机号/账号") }, // 占位提示文字
        modifier = Modifier
            .fillMaxWidth()
            .padding(12.dp),
        singleLine = true, // 单行输入
        keyboardOptions = KeyboardOptions(
            keyboardType = KeyboardType.Text // 输入键盘类型
        )
    )
}

2.4 Image组件:图片展示

Image组件用于展示本地图片、网络图片、矢量图,基础用法先讲本地资源图片加载,网络图片后续结合框架讲解。

@Composable
fun CommonImage() {
    Image(
        painter = painterResource(id = R.drawable.ic_launcher_background), // 替换为自己项目的图片id
        contentDescription = "应用图标", // 图片描述,适配无障碍访问
        modifier = Modifier
            .size(80.dp)
            .clip(CircleShape), // 裁剪为圆形
        contentScale = ContentScale.Crop // 图片缩放模式
    )
}

三、Compose三大核心布局:Column、Row、Box

Compose抛弃了XML的LinearLayout、RelativeLayout、FrameLayout,只用Column、Row、Box三个布局,就能实现所有页面布局效果,理解它们的排列逻辑,就能轻松搭建复杂页面,堪称Compose布局“三剑客”。

3.1 Column:垂直线性布局

Column对应XML的垂直方向LinearLayout,内部子组件会从上到下垂直排列,支持设置子组件对齐方式、竖直滚动(配合verticalScroll)。

核心参数

  • horizontalAlignment:水平方向对齐方式(Start/Center/End)
  • verticalArrangement:垂直方向排列方式(Top/Center/Bottom/SpaceBetween等)
@Composable
fun VerticalColumnLayout() {
    Column(
        modifier = Modifier
            .fillMaxSize()
            .padding(16.dp),
        horizontalAlignment = Alignment.CenterHorizontally, // 子组件水平居中
        verticalArrangement = Arrangement.Top // 子组件垂直顶部排列
    ) {
        // 嵌套子组件,垂直依次排列
        Text(text = "第一个组件")
        Button(onClick = {}) {
            Text(text = "垂直排列按钮")
        }
        Image(
            painter = painterResource(id = R.drawable.ic_launcher_background),
            contentDescription = null,
            modifier = Modifier.size(60.dp)
        )
    }
}

3.2 Row:水平线性布局

Row对应XML的水平方向LinearLayout,内部子组件会从左到右水平排列,支持设置子组件对齐方式、水平滚动(配合horizontalScroll)。

核心参数

  • verticalAlignment:垂直方向对齐方式(Top/Center/Bottom)
  • horizontalArrangement:水平方向排列方式(Start/Center/End/SpaceBetween等)
@Composable
fun HorizontalRowLayout() {
    Row(
        modifier = Modifier
            .fillMaxWidth()
            .padding(16.dp),
        verticalAlignment = Alignment.CenterVertically, // 子组件垂直居中
        horizontalArrangement = Arrangement.SpaceBetween // 子组件水平均分间距
    ) {
        Text(text = "左侧文本")
        Button(onClick = {}) {
            Text(text = "中间按钮")
        }
        Text(text = "右侧文本")
    }
}

3.3 Box:层叠布局

Box对应XML的FrameLayout,内部子组件会层叠摆放,后写的组件会覆盖在先写的组件上方,适合实现角标、遮罩、图片叠加文字等场景。

核心参数

  • contentAlignment:子组件整体对齐方式(Center/TopStart/BottomEnd等)
@Composable
fun StackBoxLayout() {
    Box(
        modifier = Modifier
            .size(150.dp)
            .background(Color.LightGray),
        contentAlignment = Alignment.Center
    ) {
        // 底层背景
        Image(
            painter = painterResource(id = R.drawable.ic_launcher_background),
            contentDescription = null,
            modifier = Modifier.fillMaxSize()
        )
        // 上层覆盖文字
        Text(
            text = "层叠文字",
            color = Color.White,
            fontSize = 16.sp,
            fontWeight = FontWeight.Bold
        )
    }
}

四、布局嵌套实战:个人信息卡片

学完基础组件和三大布局,我们把知识点结合起来,实战做一个个人信息卡片,用到Column、Row嵌套,搭配Text、Image、Button组件,完整还原日常简单UI开发逻辑,代码可直接复制运行。

@Composable
fun UserInfoCard() {
    // 卡片外层容器:垂直排列,承载所有卡片内容
    Column(
        modifier = Modifier
            .fillMaxWidth() // 占满父布局宽度
            .padding(16.dp) // 与父布局保持间距,避免贴边
            .background(Color.White, RoundedCornerShape(12.dp)) // 白色背景+12dp圆角
            .padding(20.dp) // 内部内边距,让内容更舒展
            .shadow(4.dp, RoundedCornerShape(12.dp)), // 4dp阴影增强立体感
        horizontalAlignment = Alignment.Start // 内部子组件左对齐
    ) {
        // 头像+用户名区域:水平排列,让头像与文字同行
        Row(
            verticalAlignment = Alignment.CenterVertically, // 垂直居中对齐
            modifier = Modifier.fillMaxWidth() // 占满卡片宽度
        ) {
            // 圆形头像:加载本地资源,裁剪为圆形
            Image(
                painter = painterResource(id = R.drawable.ic_user_avatar), // 替换为自己项目的头像id
                contentDescription = "用户头像", // 无障碍描述
                modifier = Modifier
                    .size(60.dp) // 固定60dp尺寸
                    .clip(CircleShape) // 裁剪圆形
                    .background(Color.LightGray) // 占位背景,避免图片加载失败空白
            )
            // 用户名+个性签名:垂直排列在头像右侧
            Column(modifier = Modifier.padding(start = 12.dp)) { // 与头像保持12dp间距
                Text(
                    text = "Compose初学者",
                    fontSize = 18.sp,
                    fontWeight = FontWeight.Bold // 用户名加粗突出
                )
                Text(
                    text = "持续学习,不断进阶",
                    fontSize = 14.sp,
                    color = Color.Gray,
                    modifier = Modifier.padding(top = 4.dp) // 与用户名间距4dp
                )
            }
        }
        // 分割线:分隔头像区域与按钮区域,增强层次感
        Divider(
            modifier = Modifier
                .fillMaxWidth()
                .padding(vertical = 12.dp), // 上下各12dp间距
            color = Color.LightGray, // 浅灰色不突兀
            thickness = 1.dp // 1dp厚度更精致
        )
        // 操作按钮:占满宽度,点击可查看详情
        Button(
            onClick = { /* 可补充查看详情逻辑 */ },
            modifier = Modifier.fillMaxWidth(), // 占满卡片宽度
            colors = ButtonDefaults.buttonColors(containerColor = Color(0xFF6200EE)) // 紫色背景贴合Material3风格
        ) {
            Text(text = "查看个人详情")
        }
    }
}

实战效果说明:运行后会展示一个带阴影、圆角的白色卡片,包含圆形头像、用户名、个性签名和操作按钮,布局层次清晰,是日常开发中最常见的卡片样式。

image.png

五、新手常见避坑指南

第二篇避坑重点:这些错误新手极易踩中,提前避开少走弯路

  1. 布局嵌套混乱:Column、Row嵌套时,先确定整体排列方向,再拆分局部布局,避免无限嵌套导致UI错乱
  2. Modifier顺序错误:牢记先尺寸、边距,再背景、样式,最后交互的顺序,否则样式不生效
  3. TextField无输入内容:需配合remember和mutableStateOf使用,否则无法监听输入变化,本篇可先照搬写法,后续篇章将详细讲解状态管理。
  4. 图片加载失败:确认drawable资源存在,包名路径正确,避免图片id写错导致崩溃
  5. 组件超出屏幕:长列表或多组件布局,记得给Column/Row添加滚动修饰符,避免内容溢出

六、本篇总结 + 下篇预告

  • 熟练掌握Modifier常用属性,规范使用顺序,灵活调整组件样式
  • 吃透Text、Button、TextField、Image四大基础组件的基础用法
  • 理解Column垂直、Row水平、Box层叠三大核心布局的逻辑和用法
  • 完成布局嵌套实战,能独立搭建简单的卡片类UI页面

6.2 下篇内容预告

本篇我们重点讲解了静态UI搭建,而Compose的核心灵魂是状态管理,这也是新手入门的难点。下一篇我们将重点攻克状态管理,详解remember、mutableStateOf、rememberSaveable核心API,实现UI跟随数据动态刷新,彻底搞懂声明式UI的核心逻辑。

七、系列更新进度

七、系列更新进度(建议收藏追更)

  1. 第一篇:零基础入门,环境搭建 + 第一个 Compose 页面(已更新)
  2. 第二篇:基础组件 + 三大核心布局,实战简单 UI(当前)
  3. 第三篇:Modifier 修饰符全解,UI 样式灵活控制
  4. 第四篇:Compose 状态管理核心(remember、mutableStateOf)
  5. 第五篇:列表组件 LazyColumn、LazyRow(替代 RecyclerView)
  6. 第六篇:Material3 主题、样式与自定义主题
  7. 第七篇:导航组件 Navigation Compose
  8. 第八篇:ViewModel+Compose 架构实战
  9. 第九篇:Compose 动画基础与常用交互
  10. 第十篇:综合实战:仿写简单常用页面,吃透全流程

本篇代码均可直接复制到项目中运行,建议大家动手实操加深记忆。如果文章对你有帮助,欢迎点赞、收藏、关注三连,评论区可留下你的学习疑问或遇到的问题,下篇状态管理内容正在加急更新,带你彻底吃透Compose核心~