Jetpack Compose是Android推出的新一代声明式UI框架,随着alpha版本的发布,其API也逐渐趋于稳定,是时候深入学习一波了。

Compose借鉴了React的设计思想,配合Kotlin函数式编程的语法特性,通过函数声明UI组件:

@Composable
fun AnyUiComponent() {// Code for UI element
}

而开发者唯一需要做的是添加@Composable注解,它会在编译期将创建真正的Composer对象参与底层渲染逻辑。

本文不针对底层原理作介绍,主要是向大家安利一个Compose项目

Learn Jetpack Compose for Android by example
通过例子快速上手Compose

本文基于上述内容做一个摘要介绍,帮助大家更快速地了解和熟悉Compose的基本使用

Simple TextView


@Composable
fun SimpleText(displayText: String) {Text(text = displayText)
}

我们使用@Composable创建了一个自定义组件SimpleText,其内部嵌套调用了Compose内置组件Text,并向其传递参数

完成SimpleText的定义后,我们便可以在Activity中使用

class SimpleTextActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContent {Column(modifier = Modifier.fillMaxSize(),verticalArrangement = Arrangement.Center,horizontalAlignment = Alignment.CenterHorizontally,) {SimpleText(getString("I am learning Compose"))}}}
}

作为声明式UI框架,Compose与React、Flutter等的使用方式类似,都是通过声明+组合的方式实现UI的搭建。如上,我们在Column中调用了我们自定义的SimpleText,用近似写XML的方式写Kotlin代码,这就是声明式的魅力。

Text Styling


通过为Text指定Style,可以设置字体、颜色等。

@Composable
fun StyleText(displayText: String, style: TextStyle? = null, maxLines: Int? = null) {Text(text = displayText,modifier = Modifier.padding(16.dp),style = style ?: TextStyle.Default,overflow = TextOverflow.Ellipsis,maxLines = maxLines ?: Int.MAX_VALUE)
}

上例中定义了一个StyleText组件,内部通过Text的参数设置样式,例如:

  • 设置字体:
style = TextStyle(fontSize = 24.sp
)
  • 设置粗体
fontWeight = FontWeight.Bold

TextField(EditText)


Compose使用BaseTextField实现文本输入,类似Android的EditTextBaseTextField是不稳定的API,使用时需要添加@ExperimentalFoundationApi

@ExperimentalFoundationApi
@Composable
fun SimpleTextFieldComponent() {Surface(color = Color.LightGray, modifier = Modifier.padding(16.dp)) {var text by remember { mutableStateOf(TextFieldValue("Enter text here")) }BaseTextField(value = text,modifier = Modifier.padding(16.dp).fillMaxWidth(),onValueChange = {text = it})}
}

其中onValueChange响应文本框的输入更新。

另外,还可以使用 Material Design还提供的基于BaseTextField的默认实现TextField

@Composable
fun SimpleMaterialTextFieldComponent() {var text by savedInstanceState { "" }TextField(value = text,modifier = Modifier.padding(16.dp).fillMaxWidth(),onValueChange = { text = it },label = { Text("Label") })
}

当没有输入内容时,label通过Text提供默认文本显示,相当于hint

我们可以通过参数对TextField或者BaseTextField进行配置,例如:

  • 数字键盘
var text by remember { mutableStateOf(TextFieldValue("0123")) }
BaseTextField(value = text,keyboardType = KeyboardType.Number, onValueChange = {text = it}
)
  • 密码输入
keyboardType = KeyboardType.Password,
visualTransformation = PasswordVisualTransformation()
  • 当没有输入时的占位显示
placeholder = { Text("MindOrks") }

更多参数的使用,例如icon、errorColor 、backgroundColor等可以参考项目中的示例

Simple Preview


最新的AndroidStudio支持基于Compose的布局预览(手头版本 AS 4.1 Preview)

// This is a Composable function to display a Text
@Composable
fun SimpleText(displayText: String) {Text(text = displayText)
}@Preview
@Composable
fun SimpleTextPreview() {SimpleText("Hi I am learning Compose")
}

一个简单的可预览的Composable函数需满足以下条件:

  • 添加@Preiview注解
  • 不能有参数

因为预览的本质就是自动运行一下Compose函数,所以无法运行带有参数的函数。添加@Preview后,便可以在Studio中实时预览当前效果。

当有同时预览多个组件时,为了便于区分可以为其指定name

@Preview(name = "Named Preview")

Preview Parameter


通常的预览不支持传入参数,通过使用@PreviewParameter也可以实现参数预览,准备过程会繁琐一些:

  1. 定义数据
data class Blog(val name: String,val author: String
)
  1. 构建Provider
class DummyBlogProvider : PreviewParameterProvider<Blog> {override val values =sequenceOf(Blog("Learning Compose", "MindOrks"), Blog("Learning Android", "MindOrks"))override val count: Int = values.count()
}
  1. 传入数据
@Preview
@Composable
fun BlogInfo(@PreviewParameter(DummyBlogProvider::class) blog: Blog) {SimpleTextComponent("${blog.name} by ${blog.author}")
}

Simple Column


Column类似一个Vertical的LinearLayout

@Composable
fun SimpleColumnComponent() {Column(modifier = Modifier.padding(16.dp)) {Text(text = "Hello! I am Text 1", color = Color.Black)Text(text = "Hello! I am Text 2", color = Color.Blue)}
}

Scrollable Column


当Column中的内容超出屏幕高度时,需要使用ScrollableColumn,相当于ScrollView

@Composable
fun ScrollableColumnComponent(blogList: List<Blog>) {ScrollableColumn {val context = ContextAmbient.currentColumn {for (blog in blogList) {Card(shape = RoundedCornerShape(4.dp),modifier = Modifier.fillMaxWidth().padding(16.dp).clickable(onClick = {Toast.makeText(context, "Author: ${blog.author}", Toast.LENGTH_SHORT).show()}),backgroundColor = Color(0xFFFFA867.toInt())) {Text(blog.name, style = TextStyle(fontSize = 16.sp,textAlign = TextAlign.Center), modifier = Modifier.padding(16.dp))}}}}
}

Lazy Column


LazyColumnFor可以当item进入屏幕时再加载,而无需一次加载全部数据,相当于RecyclerView

@Composable
fun LazyColumnScrollableComponent(blogList: List<Blog>) {LazyColumnFor(items = blogList, modifier = Modifier.fillMaxHeight()) { blog ->val context = ContextAmbient.currentCard(shape = RoundedCornerShape(4.dp),modifier = Modifier.fillParentMaxWidth().padding(16.dp).clickable(onClick = {Toast.makeText(context, "Author: ${blog.author}", Toast.LENGTH_SHORT).show()}),backgroundColor = Color(0xFFFFA867.toInt())) {Text(blog.name, style = TextStyle(fontSize = 16.sp,textAlign = TextAlign.Center), modifier = Modifier.padding(16.dp))}}
}

相应的,在水平方向有RowScrollableRowLazy Row可供选择。

Box


Box内部的子控件会在Z轴上按顺序叠加,类似FrameLayout。在Flutter中类似的Widget称为Stack,Compose早期的API中也叫做Stack,如今已废弃被Box取代。

@Composable
fun SimpleBoxComponent() {Box(modifier = Modifier.fillMaxSize().padding(16.dp)) {Image(imageResource(R.drawable.mindorks_cover))Text(modifier = Modifier.padding(start = 16.dp, top = 16.dp),text = "I am a text over Image",fontSize = 16.sp,color = Color.Red)}
}

Button


@Composable
fun SimpleButtonComponent() {val context = ContextAmbient.currentButton(onClick = {Toast.makeText(context, "Thanks for clicking!", Toast.LENGTH_LONG).show()},modifier = Modifier.padding(8.dp).fillMaxWidth()) {Text("Click Me")}
}

如上,Button内部摆放Text用来显示按钮的文字,onClick响应点击事件

通过参数可以进行其他配置,例如:

  • 圆角
shape = RoundedCornerShape(12.dp)
  • 边框
border = BorderStroke(width = 1.dp, brush = SolidColor(Color.Green))

更多参数的使用,例如icon、color 等可以参考项目中的示例

Card


Card相当于Material中的CardView

@Composable
fun SimpleCardComponent() {Card(backgroundColor = Color(0xFFFFA867.toInt()),modifier = Modifier.padding(16.dp).fillMaxWidth()) {Text(text = "Simple Card",textAlign = TextAlign.Center,style = TextStyle(fontSize = 16.sp),modifier = Modifier.padding(16.dp))}
}

Clickable


你可以为任意Compose组件添加Click功能,并支持单击、双击、长按等多种点击效果

@Composable
fun SimpleTextComponent() {val context = ContextAmbient.currentText(text = "Click Me",textAlign = TextAlign.Center,color = Color.Black,modifier = Modifier.padding(16.dp).fillMaxWidth().clickable(onClick = {Toast.makeText(context, "Thanks for clicking! I am Text", Toast.LENGTH_SHORT).show()}, onLongClick = {Toast.makeText(context, "Thanks for LONG click! I am Text", Toast.LENGTH_SHORT).show()}, onDoubleClick = {Toast.makeText(context, "Thanks for DOUBLE click! I am Text", Toast.LENGTH_SHORT).show()}))
}

Image


@Composable
fun SimpleImageComponent() {// Image is a composable that is used to display some image.val image = imageResource(R.drawable.mindorks_cover)Column(modifier = Modifier.padding(16.dp)) {Image(image)}
}

还可以通过Modifier设置圆角显示

Image(image,modifier = Modifier.fillMaxWidth().clip(shape = RoundedCornerShape(8.dp)),contentScale = ContentScale.Fit
)

Alert Dialog


@Composable
fun AlertDialogComponent() {val openDialog = remember { mutableStateOf(true) }if (openDialog.value) {AlertDialog(onDismissRequest = { openDialog.value = false },title = { Text(text = "Alert Dialog") },text = { Text("Hello! I am an Alert Dialog") },confirmButton = {TextButton(onClick = {openDialog.value = false/* Do some other action */}) {Text("Confirm")}},dismissButton = {TextButton(onClick = {openDialog.value = false/* Do some other action */}) {Text("Dismiss")}},backgroundColor = Color.Black,contentColor = Color.White)}
}

Material AppBar


Material规范中少不了AppBar的使用,TopAppBar实现顶部AppBar,可以设置action,并为其设置icon、onClick等

@Composable
fun TopAppBarComponent() {TopAppBar(modifier = Modifier.padding(16.dp).fillMaxWidth(),title = { Text("App Name") },navigationIcon = {IconButton(onClick = { /* doSomething() */ }) {Icon(Icons.Filled.Menu)}},actions = {IconButton(onClick = { /* doSomething() */ }) {Icon(Icons.Filled.Favorite)}IconButton(onClick = { /* doSomething() */ }) {Icon(Icons.Filled.Favorite)}})
}

类似的,BottomAppBar提供了底部AppBar的实现

Material BottomNavigation


BottomNavigation实现了NavigationBar效果,通过BottomNavigationItem往里添加Item

@Composable
fun BottomNavigationWithLabelComponent() {var selectedItem by remember { mutableStateOf(0) }val items = listOf("Home", "Blogs", "Profile")BottomNavigation(modifier = Modifier.padding(16.dp).fillMaxWidth(),backgroundColor = Color.Black,contentColor = Color.Yellow) {items.forEachIndexed { index, item ->BottomNavigationItem(label = { Text(text = item) },icon = { Icon(Icons.Filled.Favorite) },selected = selectedItem == index,onClick = { selectedItem = index })}}
}

如果不想显示item的label,可以设置alwaysShowLabels = false

Material Checkbox


@Composable
fun SimpleCheckboxComponent() {val checkedState = remember { mutableStateOf(true) }Row {Checkbox(checked = checkedState.value,modifier = Modifier.padding(16.dp),onCheckedChange = { checkedState.value = it },)Text(text = "Checkbox Example", modifier = Modifier.padding(16.dp))}
}

onCheckedChange响应事件处理

Material ProgressBar


CircularProgressIndicatorLinearProgressIndicatorCompose分别实现了圆形和线形的ProgressBar,例如:

@Composable
fun SimpleCircularProgressComponent() {CircularProgressIndicator(modifier = Modifier.padding(16.dp))
}

progress = 0.4f 可以设置当前进度

Material Slider


Slider通过滑动实现数量调节,例如音量、亮度的调节等

@Composable
fun SimpleSliderComponent() {var sliderValue by remember { mutableStateOf(0.4f) }Slider(value = sliderValue,modifier = Modifier.padding(8.dp),onValueChange = { newValue ->sliderValue = newValue})Text(text = "Slider value: $sliderValue",modifier = Modifier.padding(8.dp))
}

还可以通过传递参数steps,实现步进式的调节

Material Snackbar


Snackbar从底部弹出,比toast提供跟丰富的交互能力

@Composable
fun SimpleSnackbarComponent() {Snackbar(modifier = Modifier.padding(16.dp),text = {Text(text = "I'm a Simple Snackbar")})
}

还可以为Snackbar添加更多action

action = {Text(text = "OK", style = TextStyle(color = Color.Green))
}

Custom View


除了上面介绍的各种组件以外,Compose还允许直接在Canvas上绘制更多自定义组件

@Composable
fun CustomViewComponent() {Canvas(modifier = Modifier.fillMaxSize().padding(16.dp)) {drawRect(color = Color.Red,// topLeft is the coordinate of top-left pointtopLeft = Offset(0f, 0f),size = Size(800f, 400f))drawArc(Color.Gray,startAngle = 0f,sweepAngle = 120f,useCenter = true,size = Size(600f, 600f),topLeft = Offset(300f, 300f))}
}

Animation


Compose提供了多种效果的动画能力,例如我们可以实现CrossFade的动画效果

@Composable
fun CrossFadeAnimation() {val colors = listOf(Color.Red, Color.Green, Color.Blue, Color.Gray)var current by remember { mutableStateOf(colors[0]) }Column(modifier = Modifier.fillMaxSize()) {Crossfade(current = current) { color ->Box(Modifier.fillMaxSize().clickable(onClick = {current = colors.random()}).background(color))Text(modifier = Modifier.fillMaxSize(),textAlign = TextAlign.Center,text = "Click To See")}}
}

如上,当我们点击Box时,Box将会通过Crossfade的动画过渡到指定颜色。

更多详细实例,请移步 Learn Jetpack Compose for Android by example

Jetpack Compose UI组件入门教程相关推荐

  1. Jetpack Compose Animations 超简单教程

    Node:本文基于Jetpack Compose 1.0.0-beta01 Animation是由state驱动的 Compose的核心思想状态驱动UI刷新,这一思想同样体现在动画上. Compose ...

  2. 原创教程之——reactjs 组件入门教程

    在学习react之前,希望你有以下准备: react的安装 ECMAScript 6基础 本文不讲解react的安装步骤,若需了解请移步官方网站(https://reactjs.org/),那里讲解非 ...

  3. android ui组件开发教程,安卓开发入门教程-UI控件_Switch

    什么是Switch Switch是一种用于显示开关状态的UI控件. 基础样例 1.普通开关 效果图 代码 android:layout_width="wrap_content" a ...

  4. UI设计入门教程之如何快速掌握PS工具

    PS被看做是修图神器,是每一个UI设计师必须掌握的软件工具之一.如何才能快速掌握PS.制作出好的作品进而走上高薪路呢?小编的答案是掌握常用知识点.遵守五大设计原则. 学习PS应该掌握哪些知识点? 1) ...

  5. 告别XML,Android新声明式UI框架《Jetpack Compose入门到精通》最全开发指南

    什么是Jetpack Compose? Jetpack Compose是Android的新声明式UI框架.长期以来, Android 开发人员习惯于使用带有状态视图的xml编写UI,这些状态视图通过逐 ...

  6. Jetpack Compose 深入探索系列四: Compose UI

    通过 Compose runtime 集成 UI Compose UI 是一个 Kotlin 多平台框架.它提供了通过可组合函数发出 UI 的构建块和机制.除此之外,这个库还包括 Android 和 ...

  7. UI设计(PS+AI)入门教程【视频+素材】

    最近几天很多粉丝私信问我,有没有UI设计教程可以分享一些UI设计教程吗,于是小编就整理了一整套的UI设计入门教程. 今天免费分享给大家,希望对大家学习UI设计过程中有所帮助 PS.AI是UI设计师必不 ...

  8. Jetpack Compose中的Modifier

    Modifier的基本使用 Modifier修饰符是Jetpack Compose中用来修饰组件的,提供常用的属性,写布局时几乎所有Composable组件的大部分属性都可以用Modifier 来修饰 ...

  9. 学不动了,尝试用Android Jetpack Compose重写微信经典飞机大战游戏

    前段时间看了TechMerger大佬写的<一气呵成:用Compose完美复刻Flappy Bird!>,甚是有趣,按耐不住那躁动的心,笔者决定跟随大佬的脚步通过写游戏的方式学习Jetpac ...

  10. 使用Jetpack Compose竟能做出如此漂亮的倒计时APP

    Compose开发者挑战赛二周目 迎合Jetpack Compose beta版的发布,Google官方发起了Compose开发者挑战赛活动,目前已经入二周目 android-dev-challeng ...

最新文章

  1. java 装配_java – 无法自动装配方法
  2. win8安装11gR2[INS-13001] 环境不满足最低要求
  3. 【[AHOI2013]差异】
  4. a good resource gathering system from sustech
  5. 北斗导航 | GPS 信号频谱分析
  6. IOS的一些文件操作。(沙箱) 在Documents目录下创建文件
  7. java getchildren用法_Java ZkClient.getChildren方法代碼示例
  8. 适配器模式之迭代器模式
  9. VOIP语音电话配置
  10. YALMIP介绍及怎么在Matlab中加YALMIP、SDPT3
  11. vs2010 vs2012 插件小番茄 visual assist x破解版下载
  12. Poi 为word 添加页眉 获取页眉
  13. java excel 导入 格式转换_【转】JAVA实现EXCEL的导入和导出(二)
  14. PDF文件打开口令如何破解
  15. 学一点Wi-Fi:WPA3 BP/OCV/SCV/PK/H2E/TD
  16. Biorhythms(信息学奥赛一本通 1639)
  17. 【代码随想录】刷题笔记Day5
  18. 目前最强性能的人脸检测算法(Wider Face Dataset)
  19. 利用图的广度优先遍历解决城市最短路径问题
  20. 计算机bois界面无法保存,主板BIOS不能保存是怎么回事?

热门文章

  1. tomcat图标修改——东子破解
  2. 基于vue3.0的遮罩
  3. Python:实现binomial distribution二项分布算法(附完整源码)
  4. 0068-【数据质控】-Illumina的Barcode的设计用于16S测序
  5. 如何整合JIRA、FishEye、Crucible进行CodeReview-摘自网络
  6. 举个简单例子说明条件独立
  7. Factory reset会黑屏一段时间进入Provision首页
  8. 手机游戏怎么独占世界手游鳌头
  9. 被知网侵权长达13年!小说作家:一周前才知道
  10. 2019 年第 29 周 DApp 影响力排行榜 | TokenInsight