
Compose简介Jetpack Compose利用声明式编程构建Android原生界面UI的 工具包优势更少的代码、代码量锐减强大的工具/组件支持直观的 Kotlin API简单易用Compose 编程思想声明性编程范式声明性的函数构建一个简单的界面组件无需修改任何 XML 布局也不需要使用布局编辑器只需要调用 Jetpack Compose 函数来声明想要的元素Compose 编译器即会完成后面的所有工作举个栗子简单的可组合函数class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { Text(Hello world!) } } }动态 组合函数是用 Kotlin 而不是 XML 编写见上$name的传入需要注意的事项可组合函数可以按任何顺序执行//可以按任何顺序进行,不能让 StartScreen() 设置某个全局变量附带效应并让 MiddleScreen() 利用这项更改。相反其中每个函数都需要保持独立。 Composable fun ButtonRow() { MyFancyNavigation { StartScreen() MiddleScreen() EndScreen() } }可组合函数可以并行执行Compose 可以通过并行运行可组合函数来优化重组这样一来Compose 就可以利用多个核心并以较低的优先级运行可组合函数不在屏幕上这种优化意味着可组合函数可能会在后台线程池中执行如果某个可组合函数对 ViewModel 调用一个函数则 Compose 可能会同时从多个线程调用该函数调用某个可组合函数时调用可能发生在与调用方不同的线程上这意味着应避免使用修改可组合 lambda 中的变量的代码既因为此类代码并非线程安全代码又因为它是可组合 lambda 不允许的附带效应//此代码没有附带效应 Composable fun ListComposable(myList: ListString) { Row(horizontalArrangement Arrangement.SpaceBetween) { Column { for (item in myList) { Text(Item: $item) } } Text(Count: ${myList.size}) } }//如果函数写入局部变量则这并非线程安全或正确的代码 Composable Deprecated(Example with bug 有问题的代码) fun ListWithBug(myList: ListString) { var items 0 Row(horizontalArrangement Arrangement.SpaceBetween) { Column { for (item in myList) { Text(Item: $item) items // Avoid! Side-effect of the column recomposing. } } Text(Count: $items) } } //每次重组时都会修改 items。这可以是动画的每一帧或是在列表更新时。但不管怎样界面都会显示错误的项数。因此Compose 不支持这样的写入操作通过禁止此类写入操作我们允许框架更改线程以执行可组合 lambda。重组会跳过尽可能多的 可组合函数和 lambda重组是乐观的操作可能会被取消可组合函数可能会像动画的每一帧一样非常频繁地运行环境准备已了解的同学可直接跳过需要升级到Arctic Fox 2020-3-1 版本以上此版本以下Android studio 无此支持-【下载最新Android studio】我们注意到此项目只支持Kotlin 最低sdk 版本为21Android 5.0Gradle Compose相关依赖implementation androidx.compose.ui:ui:$compose_version implementation androidx.compose.material:material:$compose_version implementation androidx.compose.ui:ui-tooling-preview:$compose_version implementation androidx.lifecycle:lifecycle-runtime-ktx:2.3.1 implementation androidx.activity:activity-compose:1.3.0-alpha06 testImplementation junit:junit:4. androidTestImplementation androidx.test.ext:junit:1.1.3 androidTestImplementation androidx.test.espresso:espresso-core:3.4.0 androidTestImplementation androidx.compose.ui:ui-test-junit4:$compose_version debugImplementation androidx.compose.ui:ui-tooling:$compose_versionkotlinOptions { jvmTarget 1.8 useIR true//在 Gradle 构建脚本中指定额外编译器选项即可启用新的 JVM IR 后端 } composeOptions { kotlinCompilerExtensionVersion compose_version kotlinCompilerVersion 1.5.10 } buildFeatures { compose true } packagingOptions { resources { excludes /META-INF/{AL2.0,LGPL2.1} } }由于新版本邀请java 11安装 java 8 环境的需要以下修复Android Gradle plugin requires Java 11 to run. You are currently using Java 1.8. You can try some of the following options: - changing the IDE settings. - changing the JAVA_HOME environment variable. - changing org.gradle.java.home in gradle.properties.org.gradle.java.home/Library/Java/JavaVirtualMachines/jdk-11.0.11.jdk/Contents/HomePreview起作用环境正常布局Android 传统从xml-状态的变更关系程序员需要大量的代码维护Ui 界面以达到界面状态的正确性费时费力即便是借助MVVM架构一样需要维护状态因为布局只有一套声明式与传统XML 实现区别Compose 声明式布局是直接重建了UI所以不会有状态问题TextCompose 提供了基础的BasicText和BasicTextField它们是用于显示文字以及处理用户输入的主要函数。Compose 还提供了更高级的Text和TextFieldText(Hello World)重组Text-ButtonComposable fun ClickCounter(clicks: Int, onClick: () - Unit) { Button(onClick onClick) { Text(Ive been clicked $clicks times) } }Modifier可以修改控件的位置、高度、边距、对齐方式等等//padding 设置各个UI的padding。padding的重载的方法一共有四个。 Modifier.padding(10.dp) // 给上下左右设置成同一个值 Modifier.padding(10.dp, 11.dp, 12.dp, 13.dp) // 分别为上下左右设值 Modifier.padding(10.dp, 11.dp) // 分别为上下和左右设值 Modifier.padding(InnerPadding(10.dp, 11.dp, 12.dp, 13.dp))// 分别为上下左右设值 //这里设置的值必须为DpCompose为我们在Int中扩展了一个方法dp帮我们转换成Dp。 //plus 可以把其他的Modifier加入到当前的Modifier中。 Modifier.plus(otherModifier) // 把otherModifier的信息加入到现有的modifier中 //fillMaxHeight,fillMaxWidth,fillMaxSize 类似于match_parent,填充整个父layout。 Modifier.fillMaxHeight() // 填充整个高度 //width,heigh,size 设置Content的宽度和高度。 Modifier.width(2.dp) // 设置宽度 Modifier.height(3.dp) // 设置高度 Modifier.size(4.dp, 5.dp) // 设置高度和宽度 //widthIn, heightIn, sizeIn 设置Content的宽度和高度的最大值和最小值。 Modifier.widthIn(2.dp) // 设置最大宽度 Modifier.heightIn(3.dp) // 设置最大高度 Modifier.sizeIn(4.dp, 5.dp, 6.dp, 7.dp) // 设置最大最小的宽度和高度 //gravity 在Column中元素的位置。 Modifier.gravity(Alignment.CenterHorizontally) // 横向居中 Modifier.gravity(Alignment.Start) // 横向居左 Modifier.gravity(Alignment.End) // 横向居右 //rtl, ltr 开始布局UI的方向。 Modifier.rtl // 从右到左 //更多Modifier学习https://developer.android.com/jetpack/compose/modifiers-listColumn线性布局≈Android LinearLayout-VERTICALRow水平布局≈Android LinearLayout-HORIZONTALBox帧布局≈Android FrameLayout可将一个元素放在另一个元素上如需在Row中设置子项的位置请设置horizontalArrangement和verticalAlignment参数。对于Column请设置verticalArrangement和horizontalAlignment参数相对布局需要引入ConstraintLayout引入implementation androidx.constraintlayout:constraintlayout-compose:1.0.0-beta02constraintlayout-compose用法流程完整用法示例Composable fun testConstraintLayout() { ConstraintLayout() { //通过createRefs创建三个引用 val (imageRef, nameRef) createRefs() Image(painter painterResource(id R.mipmap.test), contentDescription 图, modifier Modifier .constrainAs(imageRef) {//通过constrainAs将Image与imageRef绑定,并增加约束 top.linkTo(parent.top) start.linkTo(parent.start) bottom.linkTo(parent.bottom) } .size(100.dp) .clip(shape RoundedCornerShape(5)), contentScale ContentScale.Crop) Text( text 名称, modifier Modifier .constrainAs(nameRef) { top.linkTo(imageRef.top, 2.dp) start.linkTo(imageRef.end, 12.dp) end.linkTo(parent.end) width Dimension.fillToConstraints } .fillMaxWidth(), fontSize 18.sp, maxLines 1, textAlign TextAlign.Left, overflow TextOverflow.Ellipsis, ) } }列表可以滚动的布局//我们可以使用 verticalScroll() 修饰符使 Column 可滚动 Column ( modifier Modifier.verticalScroll(rememberScrollState())){ messages.forEach { message - MessageRow(message) } }但以上布局并无法实现重用可能导致性能问题下面介绍我们重点布局列表LazyColumn/LazyRowRecylerView/listView列表布局解决了滚动时的性能问题LazyColumn和LazyRow之间的区别就在于它们的列表项布局和滚动方向不同内边距LazyColumn( contentPadding PaddingValues(horizontal 16.dp, vertical 8.dp), ) { // ... }item间距LazyColumn( verticalArrangement Arrangement.spacedBy(4.dp), ) { // ... }浮动列表的浮动标题使用LazyColumn实现粘性标题可以使用实验性stickyHeader()函数OptIn(ExperimentalFoundationApi::class) Composable fun ListWithHeader(items: ListItem) { LazyColumn { stickyHeader { Header() } items(items) { item - ItemRow(item) } } }网格布局LazyVerticalGridOptIn(ExperimentalFoundationApi::class) Composable fun PhotoGrid(photos: ListPhoto) { LazyVerticalGrid( cells GridCells.Adaptive(minSize 128.dp) ) { items(photos) { photo - PhotoItem(photo) } } }自定义布局通过重组基础布局实现CanvasCanvas(modifier Modifier.fillMaxSize()) { val canvasWidth size.width val canvasHeight size.height drawCircle( color Color.Blue, center Offset(x canvasWidth / 2, y canvasHeight / 2), radius size.minDimension / 4 ) } //drawCircle 画圆 //drawRectangle 画矩形 //drawLine //画线动画动画Api 选择其他库支持导航栏implementation(androidx.navigation:navigation-compose:2.4.0-alpha05)总结Compose总体来说对于Android-Native布局实现上更加简单高效值得大家一学Compose 写法与Flutter-Dart 有高度类似的情况后面我们可以做一篇与Flutter-Dart 语音写布局的一些对比引用developer.android.com/jetpack/com…接下来我将会给大家介绍一份谷歌大佬强势分享《Jetpack Compose 权威指南》手把手教大家Jetpack Compose从入门到精通。这份资料旨在给希望了解、学习、应用Android Jetpack Compose的小伙伴一个参考资料。资料详情第一章 初识 Jetpack Compose1. 为什么我们需要一个新的UI 工具2. Jetpack Compose的着重点加速开发强大的UI工具直观的Kotlin API3. API 设计4. Compose API 的原则一切都是函数顶层函数Top-level function组合优于继承信任单一来源5. 深入了解ComposeCoreFoundationMaterial6. 插槽API第二章 Jetpack Compose构建Android UI1. Android Jetpack Compose 最全上手指南Jetpack Compose 环境准备和Hello World布局使用Material design 设计Compose 布局实时预览……2. 深入详解 Jetpack Compose | 优化 UI 构建Compose 所解决的问题Composable 函数剖析声明式 UI组合 vs 继承封装重组……3. 深入详解 Jetpack Compose | 实现原理Composable 注解意味着什么执行模式Positional Memoization (位置记忆化)存储参数重组……第三章 Jetpack Compose 项目实战演练附Demo1. Jetpack Compose应用1开始前的准备创建DEMO遇到的问题2. Jetpack Compose应用23. Jetpack Compose应用做一个倒计时器数据结构倒计时功能状态模式Compose 布局绘制时钟4. 用Jetpack Compose写一个玩安卓App准备工作引入依赖新建 Activity创建 ComposePlayTheme画页面底部导航栏管理状态添加页面5. 用Compose Android 写一个天气应用开篇画页面画背景画内容……6. 用Compose快速打造一个“电影App”成品实现方案实战不足……因为篇幅原因只展示部分内容截图有需要完整版的扫码可以【免费】获取全部内容。视频【Android开发教程】Jetpack架构之Compose函数式编程交流【Android开发教程】Compose的绘制原理讲解