Jetpack compose 康奈尔笔记
快速上手
条目 | 内容 |
---|---|
是什么 | 原生Android界面构建工具包 |
优势 |
-更少的代码 -直观(状态变化,自动更新界面) -可以预览 -Material design |
什么是可组合函数 |
-用函数描述外观和数据依赖 -不关注构建过程 |
预览 | @Preview 函数不能带参数 |
布局 |
-Row水平排列 -Column垂直排列 ![]() |
修饰器 |
大小,外观,高级互动(例如使元素可以点击) 深色浅色主题切换 ![]() |
Material design |
颜色,排版,形状![]() ![]() ![]() |
列表和状态,动画 |
![]() ![]() 状态 ![]() ![]() ![]() ![]() 动画 ![]() ![]() ![]() |
深入详解Compose优化UI构建 -Compose解决的问题 -Compose函数剖析 -声明式UI -组合VS继承 -重组 |
解决的问题: 减少耦合增加内聚 .将界面和数据用相同的语言来编写,一些隐式的依赖就会更加明显.![]() ![]() 命令式需要自己更新UI, 声明式是数据绑定,当数据发生变化,自动更新UI. 组合VS继承 重组,将界面发生变化时,只进行部分重绘 ![]() ![]() 状态改变时,自动重绘. 没有回调函数了,也不需要订阅了. |
总结: |
布局
条目 | 内容 |
---|---|
标准布局组件 |
Column(垂直) Row(水平) Box(层叠) |
修饰符 |
类似CSS 大小,布局,行为,外观 添加信息,例如无障碍标签 处理用户输入 高级互动,例如可点击,可滚动,可拖动,或可缩放 ![]() ![]() 点击时显示黑色背景波纹(clickable的作用) ![]() clickable修饰组件内部,padding修饰组件外部. ![]() |
Slots(卡槽) API |
TopAppBar Scaffold 提供topAppBar,bottomAppBar,FloatingActionButton,Drawer的槽位 ![]() ![]() ![]() ![]() |
使用列表 |
Column Row LazyColumn lazyRow![]() 默认是不支持滚动的,需要支持滚动(状态变化才会重绘,也叫重组,没有状态是不能滑动的) ![]() ![]() 让jetpack compose支持从网络加载图片(需要添加网络访问权限) coil ![]() ScrollToTop ScrollToBottom ![]() |
自定义布局 |
自定义修饰符 案例:firstBaseline ToTop 文字底部到父元素的距离![]() ![]() ![]() ![]() ![]() ![]() layout 修饰符来修改元素的测量和布局方式 ![]() MyOwnColumn (这个应该叫,自定义容器) ![]() ![]() ![]() StaggeredGrid(交错网格-棋盘) ![]() ![]() ![]() |
约束布局 |
引用-createRefsor createRefFor parent是一个现有的引用 约束条件 constrainAs linkto ![]() ![]() ![]() ![]() ![]() ![]() 解耦API - 将布局和约束分离,根据屏幕修改约束条件.两个约束集之间可以添加动画效果. ![]() ![]() BoxWithConstraints 可以获取父容器的大小,比如例子中的maxWidth 和 maxHeight. |
Intrinsics(内部函数) |
Compose只测量子元素一次,测试两次会引发运行时异常.但是,有时在测量子元素之前,我们需要一些有关元素的信息. Intrinsic允许在实际测量之前查询子项 (min,max)intrinsicWidth:鉴于此高度,您可以正确绘制内容的最小和最大宽度是多少 (min,max)intrinsicHeight:鉴于此高度,您可以正确绘制内容的最小和最大高度是多少 ![]() ![]() ![]() |
隐式传参 CompositionLocal
A()
{var i =45B(i)
}
拿出中等透明度这个值. CompositionLocalProvider中的所有元素,都会使用相同的透明度.
状态
条目 | 内容 |
---|---|
无状态组件 |
![]() ![]() ![]() ![]()
|
非结构化状态 (传统view) |
![]() ![]() 缺点 - 测试: UI和代码混在一起,需要手动操作软件来测试,而不是通过函数调用测试 - 部分状态更新: 屏幕有很多事件时,可能忘记部分状态 - 部分UI更新: 每次状态改变后要手动更新UI,可能忘记更新某些控件的显示 - 代码复杂性: 代码难以阅读 |
单向数据流(传统view 的解决方式) |
为了解决非结构化状态的问题,引入了ViewModel和LiveData. 将状态从Activity移动到了ViewModel,在Viewmodel中,状态用LiveData 表示. LiveData是一种可观察的容器,在界面中使用observe方法,可以在状态变化时更新界面. ![]() LiveData的set方法是protected,所以name是只读的. 不能通过name修改_name;写操作必须通过指定的函数来做;这就是单向数据流 ![]() ![]() ![]() 事件向上流动,状态向下流动 - 分离状态和UI, 测试容易,直接调用onNameChanged函数就可以测试. - 状态封装 ,状态只能在viewmodel中更新,随着UI增长,不容易引入部分状态更新问题. - UI一致性,所有的状态更新都通过使用可观察状态持有者立即反映在UI中 |
Compose的状态管理 |
![]() ![]() ![]() ![]() 把状态放到viewModel里面(放到父函数里面也行),这种操作叫做状态提升,将状态转移给调用Compose的调用方.而组合本身是无状态的. compose函数有两个输入参数:1. 数据2. 对数据的操作函数. |
重组和remember |
![]() 每次添加新元素,现有的透明度也会跟着改变,以为发生了重组.所以需要引入remember. 系统会将由remember计算的值存储在组合树种,只有当remember的键发生变化时才会重新计算. ![]() ![]() 使用remember会是的该可组合项有状态; 调用方不需要控制状态,而且不需要管理状态时,"有状态"非常有用,但有内部状态的可组合项往往不易重复使用,更难测试 将由状态的可组合项改成无状态,一种简单的做法是使用状态提升. |
MutableState |
![]() ![]() ![]() |
总结 |
* 先做了一个静态界面 * 状态 * 传统view的更新方法 - 单向数据流(ViewModel和LiveData),单向数据流指的是事件向上流动和状态(数据)向下流动 - 将状态管理放到ViewModel也叫状态提升(函数需要两个输入参数:value和onValueChange函数) * Compose的remember * MutableState 状态变化时重组 |
xx | yy |
TodoList的案例
条目 | 内容 |
---|---|
弹出菜单-动画效果的实现 |
![]() |
配置软键盘 |
![]() TextField(keyboardOptions = KeyboardOptions.Default.copy(imeAction = ImeAction.Done))//将Enter替换为完成按钮 ImeAction.Done;类似的还有ImeAction.Go
|
添加带动画阴影和内容动画 |
![]() ![]() ![]() |
编辑模式 |
![]() ![]() ![]() |
保存和恢复状态 |
在重新创建Activity或者进程(被杀死)后,可以使用rememberSaveable恢复界面状态. 存储格式 * Bundle * Parcelize ![]() ![]() ![]() * mapSaver ![]() * ListSaver ![]() |
总结 |
Run 标准函数
data class Person(var name: String, var age: Int)val person = Person("John", 30)val result = with(person) {name = "Jane"age = 28"New name: $name, new age: $age"
}.let { it }
在这个例子中,我们首先使用 with 函数在 person 对象的上下文中执行一段代码块。然后,我们将 with 的返回值传递给 let 函数。由于 let 函数返回其代码块的最后一个表达式,我们可以将其简化为 it。这样,我们就实现了类似 run 的功能。
CompositionLocal
条目 | 内容 |
---|---|
简介 |
显示传参和隐式传参![]() ![]() ![]() 显示传参 1. 繁琐 2. 隔离较好 隐式传参 1. 方便 2. 一改全改(解决思路:提供provider,修改全局变量,并在函数末尾将数值改回来) ![]() 对于广泛使用的常用数据这样传参很麻烦.Compose 提供了CompositionLocal来隐式传递参数.创建以树为作用域的具名对象,让数据流经界面树. ![]() MaterialTheme是一个单例. |
主题 |
![]() ![]() 这个函数修改的是LocalContentAlpha.current,修改为ContentAlpha.medium. |
FruitText(理解current,当前上下文) |
![]() 为了访问strings.xml,需要resource,访问resource需要上下文 ![]() |
创建自己的CompositionLocal |
Elevation(海拔,海拔越高,阴影越大)![]() ![]() ![]() ![]() ![]() 提供一些默认值 ![]() ![]() 动态创建和静态创建的区别 compositionLocalOf ,如果修改提供的值,会引起读取该current值的组件重绘. staticCompositionLocalOf ,更改绘导致提供CompositionLocal的整个content lambda被重组,而不仅仅是读取current值的组件. ![]() |
主题
条目 | 内容 |
---|---|
是什么 |
1. 定了了很多Color: Primary,secondary,surface - Color.kt 2. 定义了文本样式:h1 h2 h3 Subtitle1 body1 Type.kt 3. 形状:定义了3种类别:小型,中型和大型;每个都可以定义要使用的形状,自定义样式(切割和圆角)和大小-Shape.kt |
定义主题 | 参考创建项目时自动生成的主题 |
使用颜色 |
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() |
处理文本 |
Button的默认样式![]() ![]() ![]() ![]() 一行文字使用不同的样式. ![]() |
处理形状 |
举例:Button的形状:大中小; 有些组件会根据主题修改适应上下文,默认情况下TextFiled使用小型形状主题,但它对底角应用零边角大小(就是直角).![]() ![]() |
动画和手势
条目 | 内容 |
---|---|
简单值动画 |
将背景色从粉色改成绿色 直接改变背景色也可以,但是没有一个渐变的效果. 任务目标:给颜色改变添加渐变动画 ![]() ![]() 动画对于compose来说,就是一个不断变化的state,连续的重组. 内部是一个协程. 可以打animate看看Android studio 提示,看看还有哪些简单值动画. |
可见性动画 |
可见<->不可见 之间的动画,举例:向上滚动式显示FloatingButton的文字. ![]() ![]() ![]() 另一个案例:消息从顶部滑入滑出 ![]() ![]() ![]() ![]() |
内容大小动画 |
![]() ![]() |
多值动画 |
![]() ![]() 实现弹性动画 ![]() |
重复动画 |
![]() |
手势动画 |
实现滑动删除 第一步: 元素跟随手指滑动 第二步: 手指松开,元素由于惯性,继续滑动(根据滑动速度,手指滑动结束位置,最终决定是否要删除 ) ![]() ![]() 这是一个单行函数的写法,返回值类型为Modifier,这是一个扩展函数. composed是一个高阶函数,它的作用是组合多个 Modifier,并将它们应用于当前的 Modifier。 ![]() ![]() ![]() ![]() 处理元素滑动 ![]() ![]() ![]() ![]() ![]() 记录滑动速度 ![]() 记录滑动位置和时间,就可以计算得到速度. ![]() 计算投掷速度 ![]() 由于摩擦力的原因,速度会逐渐衰减. 样条衰减 指数衰减 ![]() ![]() ![]() 设置滑动边界 ![]() ![]() |
手势
条目 | 内容 |
---|---|
点击 |
clickable![]() ![]() ![]() |
滚动 |
![]() ![]() 可滚动修饰符,scrol lable,可以检测滚动手势,但是不会偏移其内容,需要ScrollableController 才能正常运行. ![]() 嵌套滚动,简单的嵌套滚动无需执行任何操作,启动滚动操作的手势会自动从子元素到父元素,子元素无法进一步滚动时,就会由父元素处理. ![]() ![]() |
拖动 |
![]() ![]() |
滑动 |
滚动,拖动,滑动的区别 - 滚动,子元素大小超过父容器,只能一部分一部分的看,需要滚动. - 拖动,给元素换坐标 - 滑动 获得推进力后,自动惯性跑一段. ![]() ![]() ![]() |
多点触控 |
平移,缩放,旋转使用transformable修饰符,不会转换元素,只会检测手势. ![]() ![]() |
和传统view集成
从XML 创建可组合 |
基于SunFlower项目(官方案例) 把植物详情改成Compose ![]() ![]() 我们使用了Databinding,所以可以在代码中直接通过ID访问元素. ![]() ![]() ![]() ![]() ![]() dimen是在values文件夹中中定义的尺寸信息dimens.xml .获取单复数形式. ![]() |
在Compose中使用View |
![]() ![]() |
共用主题 |
使用传统view 的styles.xml ![]() |
导航
条目 | 内容 |
---|---|
集成导航 | Overview ,Count,bills |
传统的navigation |
- 一定要有一个navigation graph 导航图 - 要有一个NavHostFragment,指定navGraph - 在navigation标签中指定startDestination - 跳转通过findNavController.navigate |
Compose 中的导航 |
这里写的是导航对应的目标页![]() ![]() ![]() 设置导航部件 ![]() ![]() 支持跳转 ![]() |
参数传递 |
案例: 有多个账户,可以跳转到对应账户的页面![]() ![]() |
深层链接 |
在一个应用中打开第三方应用的指定页面 . ![]() ![]() ![]() |
Compose和View 的关系 |
传统view 调用的是SetContentView compose 调用的是 SetContent,内部实际调用的还是SetContentView,传入参数为ComposeView,它集成自ViewGroup,内部东西怎么画的,dispatchDraw->Canvas. jetpack compose的组件没有继承原来view 的那套体系,是通过画布配置的. |
附带效应(副作用)
条目 | 内容 |
---|---|
什么是附带效应 |
不是纯函数![]() 组合函数也分为有副作用和无副作用的. 组合函数的特点: - 执行顺序不定 - 可以并行执行 - 可能频繁的运行(状态改变,就会重组) 可组合函数是为了做声明式UI的,而我们会在UI做一些和界面描述不相关的操作. 处理副作用 * 虽然我们不希望函数执行中出现副作用,但显示是有一些逻辑只能作为副作用来处理,比如IO操作,计时,日志埋点等等,这些都是会对外界或者受到外界影响的逻辑,不能无限制的反复执行.所以compose需要能够合理的处理一些副作用: * 副作用(比如下载)的执行时机是明确的,例如在Recomposition时等 * 副作用的执行次数的可控的,不应该随着函数反复执行. * 副作用(比如组合函数从组件树移除时,如果该组件发了网络请求,应该取消接收)不会造成泄漏,例如对于注册要提供适当的时机取消注册. 危险的附带效应 * 写入共享对象的属性(写全局变量) * 更新ViewModel中的可观察项(数据在多个组件中共享) * 更改共享偏好设置 SharePerference 这些数据都是全局的,共享的 使用Effect API,可以用可预测的方式执行那些副作用.Effect API是和compose的生命周期关联的.何时执行?比如是compose加入到组件树的时候.什么时候释放资源? compose从组件树移除的时候. ![]() ![]() |
LaunchedEffect & rememberCoroutineScope |
如果要在可组合函数中进行耗时操作,就需要将耗时操作放到协程,协程需要在协程作用域中创建, 所以提供了LaunchedEffect用于创建协程. 副作用一般都是耗时操作,一般用协程来完成. 案例:带动画的消息提示窗(动画是耗时操作,一般在协程中执行) LaunchedEffect 有一个key,key变化它的代码块就会重启. |
rememberCoroutineScope | LaunchedEffect 只能在可组合函数中使用,非组合函数可以使用rememberCoroutineScope,该函数可以在可组合函数外启动协程,且需要对这个协程存在作用域限制,以便在协程退出组合后自动取消.协程作用域取消后,它内部的所有协程也会取消. |
rememberUpdatedState & DisposableEffect | |
SideEffect & produceState | |
derivedStateOf & snapshotflow |
Jetpack compose 康奈尔笔记相关推荐
- [图文]康奈尔笔记记录法
奈尔笔记记录法是于20世纪50年代由康奈尔大学的Walter Pauk教授所设计的,如今它已经被广泛的使用.康乃笔记法又叫做5R笔记法.这一方法几乎适用于一切讲授或阅读课,特别是对于听课笔记.这种方法 ...
- 《C++ Primer 第5版》-11.2关联容器概述-康奈尔笔记
引入:2018年10月看<C++ Primer 第5版>而写的简单笔记 11.2.1定义关联容器 关联容器概述 定义关联容器 初始化multimap或multiset map<str ...
- 《C++ Primer 第5版》-11.1使用关联容器-康奈尔笔记
引入:2018年10月看<C++ Primer 第5版>而写的简单笔记 使用关联容器 使用map 使用set Map set 关联容器 Map头文件 Set头文件 Multimap头文件 ...
- 《C++ Primer 第5版》-11.4无序容器-康奈尔笔记
无序容器 使用无序容器 管理桶 无序关联容器 哈希函数和关键字类型==运算符 Hash模板 1. 无序容器 1)4个无序关联容器,不是使用比较运算符来组织元素,而是一个哈希函数和关键字类型==运算符. ...
- 第15课:进步本技术:康奈尔笔记+进步本,考试通关杀器
- 用妙记多 Mojidoc 实践康奈尔笔记法
每个人都在做笔记,但并非所有笔记都是好的笔记. 一个好的笔记记录者和一个普通笔记者之间的区别通常在于他们使用的工具和使用的方法.今天,我们来看看康奈尔大学的笔记方法.这是一种简单.灵活且强大的笔记方法 ...
- 学计算机做纸质笔记,详细图文教你康奈尔大学推荐的超级笔记法,只要一张A4纸张,你也可以做学霸...
本文经"大J小D"(ID:jiayoubaobao2015)授权转载,原标题<一张A4纸,大家都能成为学霸 | 超级笔记法>,作者:大J,未经允许请勿转载. 上周在北京 ...
- 为知笔记(PC端) 康奈尔模板各栏间距调整
为知笔记(PC端) 自带康奈尔模板,但是各栏的间距也许不是你中意的,那么如何来调整呢? 解决方法: (以改变"要点"和"记录"两栏的左右间距为例说明) 1.新建 ...
- Jetpack Compose学习笔记
在前不久的 Android Dev Summit '19 上,Jetpack Compose 终于发布了一个可直接获得的预览版.现在的版本还是 0.1.0-dev02,处于非常早期的版本,官方也再三强 ...
最新文章
- php column not found,java.sql.SQLException: Column 'cloumn name' not found.
- CCD和CMOS摄像头成像原理以及其他区别
- 国企程序员是一种怎样的体验?
- java默认代码地址_Java 8默认方法可能会破坏您的(用户)代码
- oracle导入中文数据出现乱码
- Laravel 5 IDE Helper 安装
- 物理知识(量子物理)
- 百度认证(深度学习初级工程师)考试题1
- python爬虫实现贴吧表情包的爬取
- 【MySQL】SHOW ENGINE INNODB STATUS \G之Pages flushed up to的理解
- java怎么删除一行表格_Java 创建、删除Word表格
- win10 系统亮度调节
- ITIL 4Foundation题目-6
- 如何极速下载网页上的文件? 怎么批量下载文献
- 易语言取文件名和文件扩展名
- python基础-input函数
- frog——2017科技趋势预测
- python上机试题
- 在线计算机手册,[计算机]A++账务系统操作手册-单位版.doc
- 第七节:组合接口联调测试,代码实现V2变量传值