开始
什么是Compose
Jetpack Compose 谷歌推出的 UI 开发框架,目的是简化界面开发,无需在 XML 中定义 UI。该组件将响应式编程模型与简洁易用的 Kotlin 编程语言相结合,并采用完全声明式的代码编写方式,通过调用一系列函数来描述界面,这些函数会将数据转换为 UI 层次结构。当底层数据发生变化时,Compose 框架会自动重新执行这些函数,从而更新 UI。
总结来说,Android Compose 是一种“现代化”的 UI 开发框架,它通过声明式编程、可组合性、高效的状态管理和动画支持等特性,极大地简化了 Android 应用的界面开发工作,提升了代码质量和开发效率。
Hello Compose
创建项目
点击 Empty Activity 创建新项目,在Android Studio 2023.1.1 版本,默认创建的项目就是基于 Compose,所以无需进行特殊配置处理。
运行项目
官方 demo 实现的效果非常简单,就是一句 Hello Compose! ,接下来我们简单看一下代码是如何实现的。
查看代码
package com.example.composedemo
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import com.example.composedemo.ui.theme.ComposeDemoTheme
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
// 应用主题
ComposeDemoTheme {
// 一个通用的布局容修饰或扩充可组合项器,可以设置背景色、形状
Surface(
// 修饰或扩充可组合项
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
Greeting("Compose")
}
}
}
}
}
@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
Text(
text = "Hello $name!",
modifier = modifier
)
}
@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
ComposeDemoTheme {
Greeting("Android")
}
}
上述是 Android Studio 帮我们创建的默认项目,代码比较简单,关键地方也进行了注释。
@Composable 和 @Preview
需要注意的是 @Composable 和 @Preview 这两个注解,下面详细进行介绍。
@Composable
@Composable 是 Jetpack Compose 中的一个注解,它用于标记一个函数可以被 Compose 编译器用来构建 UI。这些函数被称为 Composable 函数,具有一下特点:
- 可组合:Composable 函数可以调用其他 Composable 函数,这样可以组合多个 UI 组件来构建复杂的 UI。
- 可重用:Composable 函数可以被多次调用,每次调用都会生成 UI 的一个独立实例。
- 响应式:Composable 函数可以响应状态的变化,当状态变化时,只有依赖于这个状态的 Composable 函数会被重新调用,并且更新 UI。
@Preview
@Preview 是 Jetpack Compose 中的一个注解,它用于在 Android Studio 的预览窗口中显示 Composable 函数的预览。当你在 Composable 函数上添加 @Preview 注解时,Android Studio 会在设计模式下渲染该函数的 UI,并显示在预览窗口中。这样可以在不运行整个应用程序的情况下,快速查看和检查你的 Composable UI,具体效果如下图所示。
初探
View
首先先带大家了解一下 View 控件,以图文的形式进行示例。除了少部分控件与 Android 有些许差异,大部分都是一样的。下面会依次介绍我们常用的控件,比较简单请放心食用。
名称 | 描述 |
---|---|
Text | 用于显示文本 |
Image | 用于显示图片 |
TextField | 文本输入控件 |
Button | 用于创建按钮 |
Checkbox | 复选框控件 |
RadioButton | 单选按钮控件 |
LinearProgressIndicator | 水平进度条控件 |
Slider | 滑块控件 |
Text
@Composable
fun MTextView(modifier: Modifier = Modifier) {
Text(
text = "Hello Text !",
fontSize = 36.sp,
color = Color(0xFF121113),
fontStyle = FontStyle.Italic,
modifier = modifier
)
}
Image
@Composable
fun ShowImage() {
val image = painterResource(R.drawable.ic_launcher)
Image(
painter = image,
contentDescription = "image",
modifier = Modifier.padding(16.dp),
contentScale = ContentScale.Crop,
alignment = Alignment.Center
)
}
TextField
@Composable
fun EditTextView() {
val text = remember { mutableStateOf("") }
TextField(
value = text.value,
onValueChange = { text.value = it },
//提示文本,当输入框为空时显示
placeholder = { Text("input user name", color = Color(0xFF666262)) },
singleLine = true,
maxLines = 1,
textStyle = TextStyle(color = Color(0xFF111111), fontSize = 28.sp),
)
}
Button
@Composable
fun ButtonView() {
val context = LocalContext.current
//创建一个协程
val scope = rememberCoroutineScope()
Button(onClick = {
scope.launch {
Toast.makeText(context, "This is Button", Toast.LENGTH_SHORT).show()
}
}, modifier = Modifier
.size(200.dp, 100.dp)
.padding(20.dp), enabled = true) {
Text("Click Me", fontSize = 20.sp)
}
}
Checkbox
@Composable
fun CheckboxView() {
// 保存状态
val state = remember { mutableStateOf(true) }
Checkbox(
checked = state.value,
onCheckedChange = { state.value = it }
)
}
RadioButton
@Composable
fun RadioButtonView() {
// 默认保存选择MVVM
val normal = remember { mutableStateOf("MVVM") }
val options = listOf("MVVM", "MVP", "MVI", "MVC")
Column {
options.forEach { option ->
Row(verticalAlignment = Alignment.CenterVertically) {
RadioButton(
selected = normal.value == option,
onClick = { normal.value = option }
)
Text(
text = option,
modifier = Modifier.padding(start = 8.dp)
)
}
}
}
}
LinearProgressIndicator
@Composable
fun ProgressBarView() {
val progress = remember { mutableFloatStateOf(0.8f) }
LinearProgressIndicator(
progress = progress.floatValue,
modifier = Modifier.padding(16.dp),
//进度条颜色
color = Color.Red,
//背景颜色
trackColor = Color.Gray,
//进度条样式
strokeCap = StrokeCap.Round
)
}
Slider
@Composable
fun SliderView() {
val position = remember { mutableFloatStateOf(0.3f) }
Slider(
value = position.floatValue,
onValueChange = { newValue -> position.floatValue = newValue },
valueRange = 0f..100f,
modifier = Modifier.padding(16.dp),
colors = SliderDefaults.colors(
//滑块颜色
thumbColor = Color.Red,
//滑轨颜色
activeTrackColor = Color.Green,
//滑轨背景颜色
inactiveTrackColor = Color.Gray
)
)
}
ViewGroup
接下来给大家介绍一下常用布局的简单使用,也是以图文形式进行示例。
名称 | 描述 |
---|---|
Scaffold | 一个基础布局,通常包含顶部栏、底部栏和一个内容区域 |
Column | 垂直布局 |
Row | 水平布局 |
Surface | 一个通用的布局容器,可以设置背景色、形状等 |
Card | 卡片布局 |
LazyColumn | 懒加载的垂直滚动列表 |
LazyRow | 懒加载的水平滚动列表 |
Scaffold
class MainActivity : ComponentActivity() {
@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyApplicationTheme {
Scaffold(
topBar = {
Text("Jetpack Compose", modifier = Modifier.padding(16.dp, 0.dp, 0.dp, 0.dp))
},
content = {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
GreetingPreview()
}
}
)
}
}
}
}
Column
@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
MyApplicationTheme {
Column(
modifier = Modifier
.fillMaxSize()
.padding(8.dp),
verticalArrangement = Arrangement.Center
) {
ButtonView()
ButtonView()
ButtonView()
ButtonView()
}
}
}
Row
@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
MyApplicationTheme {
Row(
modifier = Modifier
.fillMaxSize()
.padding(8.dp),
horizontalArrangement = Arrangement.Start
) {
ShowImage()
ShowImage()
ShowImage()
}
}
}
Surface
@Composable
fun SurfaceLayout() {
Surface(
color = Color.Blue,
modifier = Modifier
.padding(8.dp)
.size(300.dp, 200.dp)
) {
Text("This is Surface Layout", color = Color.White)
}
}
Card
@Composable
fun CardLayout() {
Card(
modifier = Modifier
.padding(8.dp)
.size(300.dp, 200.dp),
//设置圆角
shape = RoundedCornerShape(20.dp),
) {
Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center
) {
Text(
"This is Card Layout",
textAlign = TextAlign.Center,
color = Color.Black,
fontSize = 20.sp
)
}
}
}
LazyColumn
@Composable
fun LazyColumnLayout() {
val context = LocalContext.current
val items = mutableListOf<String>()
for (i in 0..50) {
items += "Item data $i"
}
//懒加载的列表,只有当item出现在屏幕上时才会加载
LazyColumn {
items(items) { item ->
Text(text = item, modifier = Modifier
.padding(16.dp)
.clickable {
Toast
.makeText(context, item, Toast.LENGTH_SHORT)
.show()
})
}
}
}
设计
主题和样式
//黑夜主题颜色
private val DarkColorScheme = darkColorScheme(
primary = Purple80,
secondary = PurpleGrey80,
tertiary = Pink80
)
//白天主题颜色
private val LightColorScheme = lightColorScheme(
primary = Purple40,
secondary = PurpleGrey40,
tertiary = Pink40
)
@Composable
fun MyApplicationTheme(
//主题模式
darkTheme: Boolean = isSystemInDarkTheme(),
//是否动态颜色
dynamicColor: Boolean = true,
//布局
content: @Composable () -> Unit
) {
val colorScheme = when {
dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
val context = LocalContext.current
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
}
darkTheme -> DarkColorScheme
else -> LightColorScheme
}
MaterialTheme(
colorScheme = colorScheme,
typography = Typography,
content = content
)
}
val Typography = Typography(
bodyLarge = TextStyle(
//字体样式
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Normal,
fontSize = 16.sp,
lineHeight = 24.sp,
letterSpacing = 0.5.sp
)
/* Other default text styles to override
titleLarge = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Normal,
fontSize = 22.sp,
lineHeight = 28.sp,
letterSpacing = 0.sp
),
labelSmall = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Medium,
fontSize = 11.sp,
lineHeight = 16.sp,
letterSpacing = 0.5.sp
)
*/
)
动画
开启 animateFloatAsState 动画
@Composable
fun StartFloatAnimation() {
var started by remember { mutableStateOf(false) }
// 使用 animateFloatAsState 创建浮点数动画
val size by animateFloatAsState(
if (started) {
200f
} else {
100f
},
visibilityThreshold = 0.1f,
// 使用 keyframes 定义动画的持续时间
animationSpec = keyframes {
durationMillis = 1000
}, label = ""
)
Box(
modifier = Modifier
.size(size.dp)
.background(Color.Blue)
.clickable { started = !started } // 点击时切换大小
)
}
开启 animateTo 动画
@Composable
fun StartAnimationToColor() {
val color = remember { Animatable(Color.Red) }
// //创建一个协程
val scope = rememberCoroutineScope()
Box(modifier = Modifier
.size(240.dp)
.background(color.value)
.clickable {
// 开启协程
scope.launch {
// 改变动画到目标颜色
color.animateTo(
targetValue = Color.Blue,
animationSpec = tween(durationMillis = 5000, easing = LinearOutSlowInEasing)
)
}
}
)
}
总结
以上就是 Compose 的简单使用,帮助大家对 Compose 有个初步的认识和了解,如果想要了解更多,建议直接访问官网。从个人角度出发,对于 Android 开发者来讲 Compose 还是比较容易上手,特别是有 Flutter 开发经验会更比较容易接受和掌握。所以,对于感兴趣的同学赶紧学起来吧!
总的来说,Compose 是一个强大、灵活、现代的 Android UI 工具包,可以帮助大家更高效地进行 UI 开发。
如果你看到了这里,觉得文章写得不错就给个赞呗?
更多Android进阶指南 可以扫码 解锁更多Android进阶资料
敲代码不易,关注一下吧。ღ( ´・ᴗ・` )