第一篇:Compose 基础知识 - 入门教程(A)

942 阅读2分钟

初步熟悉Jetpack Compose。学习并了解可组合函数、基本布局和状态、Material Design、列表和动画。

更多更全布局组件以及各类API参见Jetpack Compose 使用入门

一、可组合函数(Composable Functions)

1.1、基本概念

  • @Composable 注解:标记函数为 UI 组件
  • 声明式 UI:通过函数描述界面,而非 XML
  • 重组(Recomposition) :当输入参数变化时自动刷新 UI

1.2、示例:创建简单组件

@Composable
fun Greeting(name: String) {
    Text(text = "Hello, $name!") // 使用 Material Design 的 Text 组件
}

// 调用
Greeting(name = "Android")

1.3、参数与复用

@Composable
fun IconButton(icon: ImageVector, onClick: () -> Unit) {
    IconButton(onClick = onClick) {
        Icon(imageVector = icon, contentDescription = null)
    }
}

// 调用
IconButton(icon = Icons.Default.Favorite, onClick = { /* 处理点击 */ })

二、基本布局与状态管理

2.1、常用布局

布局组件描述示例
Column垂直排列子元素Column { Text("A"); Text("B") }
Row水平排列子元素Row { Text("A"); Text("B") }
Box叠加子元素Box { Image(); FloatingActionButton() }
Spacer填充空白Spacer(modifier = Modifier.width(16.dp))

2.2、状态管理

@Composable
fun Counter() {
    var count by remember { mutableStateOf(0) } // 状态变量
    Column {
        Text("Count: $count")
        Button(onClick = { count++ }) {
            Text("Increment")
        }
    }
}

2.3、状态提升(State Hoisting)

@Composable
fun HoistedCounter(count: Int, onCountChange: (Int) -> Unit) {
    Column {
        Text("Count: $count")
        Button(onClick = { onCountChange(count + 1) }) {
            Text("Increment")
        }
    }
}

// 父组件管理状态
@Composable
fun Parent() {
    var count by remember { mutableStateOf(0) }
    HoistedCounter(count = count, onCountChange = { newCount -> count = newCount })
}

三、Material Design 组件

3.1、常用组件

@Composable
fun MaterialComponents() {
    Column(modifier = Modifier.padding(16.dp)) {
        // 按钮
        Button(onClick = {}) { Text("Button") }
        // 输入框
        var text by remember { mutableStateOf("") }
        TextField(value = text, onValueChange = { text = it }, label = { Text("Input") })
        // 卡片
        Card(elevation = 4.dp) {
            Column(modifier = Modifier.padding(16.dp)) {
                Text("Card Title")
                Text("Card Content")
            }
        }
    }
}

3.2、主题定制

// 在 Activity 的 setContent 前设置
MaterialTheme(
    colors = darkColors(primary = Color.Blue), // 自定义颜色
    typography = Typography(body1 = TextStyle(fontFamily = FontFamily.Monospace)), // 字体
    shapes = Shapes(small = RoundedCornerShape(8.dp)) // 形状
) {
    // 组件树
}

四、列表处理(LazyColumn/LazyRow)

4.1、基本列表

@Composable
fun SimpleList(items: List<String>) {
    LazyColumn {
        items(items) { item ->
            Text(text = item, modifier = Modifier.padding(16.dp))
        }
    }
}

4.2、复杂列表(带点击事件)

data class User(val id: Int, val name: String)

@Composable
fun UserList(users: List<User>, onItemClick: (User) -> Unit) {
    LazyColumn {
        items(users, key = { it.id }) { user ->
            Card(
                modifier = Modifier
                    .fillMaxWidth()
                    .clickable { onItemClick(user) }
                    .padding(8.dp)
            ) {
                Text(text = user.name, modifier = Modifier.padding(16.dp))
            }
        }
    }
}

五、动画(Animations)

5.1、简单动画

@Composable
fun AnimatedButton() {
    var enabled by remember { mutableStateOf(true) }
    val backgroundColor by animateColorAsState(if (enabled) Color.Green else Color.Red)
    
    Button(
        onClick = { enabled = !enabled },
        colors = ButtonDefaults.buttonColors(backgroundColor = backgroundColor)
    ) {
        Text(if (enabled) "Enabled" else "Disabled")
    }
}

5.2、布局动画

@Composable
fun AnimatedVisibilityDemo() {
    var visible by remember { mutableStateOf(true) }
    Column {
        AnimatedVisibility(visible = visible) {
            Text("Hello, I can fade in/out!")
        }
        Button(onClick = { visible = !visible }) {
            Text("Toggle Visibility")
        }
    }
}

5.3、过渡动画

@Composable
fun TransitionDemo() {
    var isExpanded by remember { mutableStateOf(false) }
    val transition = updateTransition(targetState = isExpanded, label = "expandTransition")
    val rotation by transition.animateFloat(label = "rotation") { state ->
        if (state) 180f else 0f
    }

    IconButton(onClick = { isExpanded = !isExpanded }) {
        Icon(
            imageVector = Icons.Default.Expand,
            contentDescription = null,
            modifier = Modifier.rotate(rotation)
        )
    }
}

六、综合案例:示例应用

data class TodoItem(val id: Int, val task: String, var completed: Boolean)

@Composable
fun TodoApp() {
    var todos by remember { mutableStateOf(emptyList<TodoItem>()) }
    var newTask by remember { mutableStateOf("") }

    Column(modifier = Modifier.padding(16.dp)) {
        // 输入框
        TextField(
            value = newTask,
            onValueChange = { newTask = it },
            label = { Text("New Task") }
        )
        // 添加按钮
        Button(onClick = {
            if (newTask.isNotBlank()) {
                todos = todos + TodoItem(todos.size + 1, newTask, false)
                newTask = ""
            }
        }) {
            Text("Add Task")
        }
        // 列表
        LazyColumn {
            items(todos, key = { it.id }) { todo ->
                Row(verticalAlignment = Alignment.CenterVertically) {
                    Checkbox(
                        checked = todo.completed,
                        onCheckedChange = { checked ->
                            todos = todos.map { 
                                if (it.id == todo.id) it.copy(completed = checked) else it 
                            }
                        }
                    )
                    Text(
                        text = todo.task,
                        modifier = Modifier.padding(8.dp),
                        style = if (todo.completed) LocalTextStyle.current.copy(
                            color = Color.Gray,
                            textDecoration = TextDecoration.LineThrough
                        ) else LocalTextStyle.current
                    )
                }
            }
        }
    }
}

七、学习资源

通过以上教程,你可以逐步掌握 Compose 的核心概念,并构建出美观且功能完善的 Android 应用!