Android Compose 入门,深入底层源码分析

我是跟着AS官网学习的,但是官方的教程写的不是很详细.官网链接

首先创建一个Compose项目,目录结构是这样:

ui

-> theme

-> -> Color.kt

-> -> Theme.kt

-> -> Type.kt

MainActivity.kt

通过阅读源码,发现实际上还少了一个Shapes.kt,我手动添加了.

Type.kt

/**
* 存放组件的Style
* Typography全部是文字的属性
* 点开Typography的代码,结构很简单.
* 存了一些TextStyle,提供以下功能:
* 主构造函数: 使用一些默认参数初始化各个TextStyle
* copy: 复制一份
* equals: 比较每一个TextStyle
* hashCode: 计算hash,把每个TextStyle都计算进去.
* fromToken: internal修饰,为Typography类增加拓展函数,根据传进来的enum,确认获取哪个TextStyle.
* 在class外部还有一个对象:
* LocalTypography: internal修饰,被MaterialTheme作为默认参数使用
*/
val Typography = Typography(
bodyLarge = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Normal,
fontSize = 16.sp,
lineHeight = 24.sp,
letterSpacing = 0.5.sp
)
)

Color.kt

/**
* 存放颜色值
* darkColorScheme和lightColorScheme都属于ColorScheme
* 点开ColorScheme的代码,结构很简单.
* 存了一些Color,提供以下功能:
* 主构造函数: 颜色委托给mutableStateOf,使颜色值的变化可以被Compose观察.
* copy: 复制一份
* 剩下的是一些函数:
* lightColorScheme: 提供默认的白天模式颜色
* darkColorScheme: 提供默认的夜间模式颜色
* ColorScheme.contentColorFor: 为ColorScheme类增加拓展函数,根据背景色使用对应的前景色,如果颜色不匹配,返回透明色.
* contentColorFor: 提供一个函数,import这个函数来使用,如果颜色不匹配,返回黑色.
* applyTonalElevation: internal修饰,为ColorScheme类增加拓展函数,返回新背景色,传入的背景色加上高度.
* surfaceColorAtElevation: 为ColorScheme类增加拓展函数,计算不同高度的surface表面色调.
* updateColorSchemeFrom: internal修饰,为ColorScheme类增加拓展函数,更新颜色,成本很高,但颜色委托给了mutableStateOf,忽略不变化的颜色值,提高运行效率.
* fromToken: internal修饰,为ColorScheme类增加拓展函数,根据传进来的enum,确认获取哪个Color.
* toColor: internal修饰,为ColorSchemeKeyTokens类增加拓展函数,将enum转换为对应的颜色,调用fromToken.
* 在class外部还有两个对象:
* LocalColorScheme: internal修饰,被MaterialTheme作为默认参数使用,默认使用lightColorScheme.
* DisabledAlpha: internal修饰,禁用状态的前景色.比如禁用按钮的文字颜色.
*/
val Purple80 = Color(0xFFD0BCFF)
val PurpleGrey80 = Color(0xFFCCC2DC)
val Pink80 = Color(0xFFEFB8C8) val Purple40 = Color(0xFF6650a4)
val PurpleGrey40 = Color(0xFF625b71)
val Pink40 = Color(0xFF7D5260) //深色模式
val DarkColorScheme = darkColorScheme(
primary = Purple80,
secondary = PurpleGrey80,
tertiary = Pink80
) //浅色模式
val LightColorScheme = lightColorScheme(
primary = Purple40,
secondary = PurpleGrey40,
tertiary = Pink40,
)

Shapes.kt

/**
* 默认创建的项目里没有创建Shapes
* 这里也简单介绍一下
* 点开Shapes代码,结构很简单.
* 存放了一些形状,提供以下功能:
* 主构造函数: 存放一些CornerBasedShape
* CornerBasedShape基于角的形状,子类有: AbsoluteCutCornerShape,AbsoluteRoundedCornerShape,CutCornerShape,RoundedCornerShape.
* https://developer.android.com/reference/kotlin/androidx/compose/foundation/shape/CornerBasedShape * copy: 复制一份
* equals: 比较每个shape
* hashCode: 计算hash,把每个shape都计算进去.
* 类外部:
* ShapeDefaults: 提供CornerBasedShape的默认参数
* top,bottom,start,end: internal修饰,帮助组件获取Shape.
* fromToken: internal修饰,根据传入的enum,返回对应的Shape.
* toShape: internal修饰,为ShapeKeyTokens增加扩展函数,把enum转为Shape,调用fromToken.
* LocalShapes: internal修饰,被MaterialTheme作为默认参数使用,默认使用ShapeDefaults.
*/val shapes = Shapes(
extraSmall = ShapeDefaults.ExtraSmall
)

Theme.kt

/**
* 构建一个Theme用来使用
* 如果不用自己构建的theme,会使用默认的theme.
* Theme很简单,分为两部分.
* 由Compose托管的:
* 使用colorScheme,shapes,typography,content创建一个MaterialTheme.
* content使用这个MaterialTheme,并且这个MaterialTheme会递归传递给content内的@Composable修饰的函数.
* 非Compose托管的:
* 一些不属于View的,属于window的.如状态栏颜色,导航栏是否显示等.
* 然后是MaterialTheme的源码
* MaterialTheme是一个@Composable修饰的函数,按照顺序拆解:
* rememberedColorScheme,用来更新颜色.调用updateColorSchemeFrom.使用remember让currentComposer缓存colorScheme.copy()返回的对象,下次重组时继续使用该值,涉及的内容太多,这里不再深入.
* rippleIndication,波纹动画,默认使用透明色,也就是没有波纹动画.
* selectionColors,文字选中颜色,默认使用:rememberedColorScheme.primary
* CompositionLocalProvider,一个@Composable修饰的函数,使用上面的参数构建一个ProvidedValue对象,调用currentComposer.startProviders保存这些对象,然后调用content绘制,绘制时会使用这些ProvidedValue对象,然后调用currentComposer.endProviders()终止记录.
*/
/**
* @param darkTheme 是否是深色模式
* @param dynamicColor 动态颜色 安卓12(api31) 新增,会基于系统壁纸的颜色使用对应的颜色,https://developer.android.com/develop/ui/views/theming/dynamic-colors
* @param content Composable代码块,使用colorScheme作为主题色
*/
@Composable
fun Study1Theme(
darkTheme: Boolean = isSystemInDarkTheme(),
dynamicColor: Boolean = true,
content: @Composable () -> Unit
) {
//Material Design 需要的颜色
val colorScheme = when {
//使用动态颜色,跟随壁纸,只有大于api31才能使用
dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {
val context = LocalContext.current
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
} darkTheme -> DarkColorScheme
else -> LightColorScheme
} //获取View,@Composable的组合函数实际上是一个View
val view = LocalView.current
//不是编辑模式的情况下,设置一些参数
if (!view.isInEditMode) {
//window不是Compose管理的对象,需要用SideEffect来共享Compose状态,SideEffect保证每次重组后都会执行
SideEffect {
//设置status bar 颜色
val window = (view.context as Activity).window
window.statusBarColor = colorScheme.primary.toArgb()
WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = darkTheme
}
} //颜色,字体,代码块构建一个MaterialTheme对象,代码块的MaterialTheme对象会使用这个构建的对象
MaterialTheme(
colorScheme = colorScheme,
typography = typography,
shapes = shapes,
content = content
)
}

MainActivity.kt

这个没什么好说的,官方的教程说的很明白了.这里简单贴一下代码.

class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//setContent是Kotlin的扩展函数,使用Compose创建窗口
setContent {
//Study1Theme在theme/Theme.kt里,生成MaterialTheme给整个代码块用
Study1Theme(dynamicColor = false) {
//使用一个@Composable函数来作为界面的入口
MyApp(Modifier.fillMaxSize())
}
} } //界面入口,用来复用函数
@Composable
fun MyApp(modifier: Modifier = Modifier){
//Surface,一般显示组件的颜色,如卡片,表格,菜单的背景色
Surface(
//Modifier.fillMaxSize() 铺满父组件
modifier = modifier,
//使用Study1Theme里创建的MaterialTheme的colorScheme
//colorScheme现在有深色浅色两种模式,也可以添加更多风格.
color = MaterialTheme.colorScheme.primary
) {
//Surface函数的最后一个参数是content: @Composable () -> Unit
//@Composable注解修饰的函数只能被同样@Composable修饰的函数调用
SayHello("Android")
}
} //显示一个文本
@Composable
fun SayHello(name: String, modifier: Modifier = Modifier) {
Surface(color = MaterialTheme.colorScheme.primary) {
Text(
text = "Hello $name!",
modifier = modifier.padding(24.dp)
)
}
} //Preview可以预览无参或者有默认参数的Compose函数
@Preview(showBackground = true, name = "Say Hello Preview")
@Composable
fun SayHelloPreview(name: String = "Compose") {
Study1Theme(dynamicColor = false) {
MyApp()
}
}
}

Android Compose 入门,深入底层源码分析的更多相关文章

  1. Android Small插件化框架源码分析

    Android Small插件化框架源码分析 目录 概述 Small如何使用 插件加载流程 待改进的地方 一.概述 Small是一个写得非常简洁的插件化框架,工程源码位置:https://github ...

  2. List-LinkedList、set集合基础增强底层源码分析

    List-LinkedList 作者 : Stanley 罗昊 [转载请注明出处和署名,谢谢!] 继上一章继续讲解,上章内容: List-ArreyLlist集合基础增强底层源码分析:https:// ...

  3. List-ArrayList集合基础增强底层源码分析

    List集合基础增强底层源码分析 作者:Stanley 罗昊 [转载请注明出处和署名,谢谢!] 集合分为三个系列,分别为:List.set.map List系列 特点:元素有序可重复 有序指的是元素的 ...

  4. LInkedList总结及部分底层源码分析

    LInkedList总结及部分底层源码分析 1. LinkedList的实现与继承关系 继承:AbstractSequentialList 抽象类 实现:List 接口 实现:Deque 接口 实现: ...

  5. Vector总结及部分底层源码分析

    Vector总结及部分底层源码分析 1. Vector继承的抽象类和实现的接口 Vector类实现的接口 List接口:里面定义了List集合的基本接口,Vector进行了实现 RandomAcces ...

  6. 【Android】Handler、Looper源码分析

    一.前言 源码分析使用的版本是 4.4.2_r1. Handler和Looper的入门知识以及讲解可以参考我的另外一篇博客:Android Handler机制 简单而言:Handler和Looper是 ...

  7. Android View事件分发-从源码分析

    View事件分发-从源码分析 学习自 <Android开发艺术探索> https://blog.csdn.net/qian520ao/article/details/78555397?lo ...

  8. Android线程间异步通信机制源码分析

    本文首先从整体架构分析了Android整个线程间消息传递机制,然后从源码角度介绍了各个组件的作用和完成的任务.文中并未对基础概念进行介绍,关于threadLacal和垃圾回收等等机制请自行研究. 基础 ...

  9. Android JobService的使用及源码分析

    Google在Android 5.0中引入JobScheduler来执行一些需要满足特定条件但不紧急的后台任务,APP利用JobScheduler来执行这些特殊的后台任务时来减少电量的消耗.本文首先介 ...

  10. JAVA ArrayList集合底层源码分析

    目录 ArrayList集合 一.ArrayList的注意事项 二. ArrayList 的底层操作机制源码分析(重点,难点.) 1.JDK8.0 2.JDK11.0 ArrayList集合 一.Ar ...

随机推荐

  1. Arrays.asList的坑

    Arrays.asList 方法的坑 此方法接受可变个数的参数 构建一个ArrayList 可此ArrayList 非彼ArrayList ,他返回的是 Arrays 的一个内部类,实现了Abstra ...

  2. electron暴露配置文件(用户可随时修改)

    配置文件 一般web前端项目配置文件,写死的放在src/config下,需要打包配置的放在.env文件中.但在electron项目中,如果配置数据更改,需要每次给用户打包升级肯定是行不通的.于是外部配 ...

  3. AOP+自定义注解实现权限校验-2022新项目

    一.业务场景 当前本人参与开发的是一个业务中台系统,所谓的中台简单的理解就是把相同的功能给抽取出来.比如系统A.B.C.D都需要进行用户登录操作,那么可以把用户信息管理这一块抽取出来为一个独立的系统E ...

  4. react build 后,打包后自动将index.html copy 404.html - create-react-app 创建的项目

    起因:build上传gitee,启用路由需要404.html自动跳转 当前环境 create-react-app 搭建的架子 解决方案 由于默认的时候把build.js打包,无法查看,只好eject ...

  5. 3DCAT首届行业生态交流会|爱智慧科技有限公司CEO梁新刚:工业元宇宙的”形“与”神“

    2021年12月17日下午,由深圳市瑞云科技有限公司主办,深圳市虚拟现实产业联合会协办的 云XR如何赋能元宇宙--3DCAT实时云渲染首届行业生态合作交流会 圆满落幕.此次活动围绕"云XR如 ...

  6. Linux进程管理、安全

    1.介绍 1.什么是进程 比如: 开发写的代码我们称为程序,那么将开发的代码运行起来.我们称为进程. 总结一句话就是: 当我们运行一个程序,那么我们将运行的程序叫进程. PS1: 当程序运行为进程后, ...

  7. uni-app 地图全解析+事件监听

    最近找到了一篇uni-app的地图解决方案精品文章,这里分享给大家,希望对大家有所帮助 转载地址:https://blog.csdn.net/cplvfx/article/details/111447 ...

  8. 记录--uniapp map 制作一个简单的地图导航

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 先上效果 简易map 在图一的地图中可以看到 a点 连接 到 b点, 基本信息 以及 基本的控件(放大.缩小.回到某个指定的点),接下来我 ...

  9. KingbaseES V8R3 集群运维案例 --操作系统‘soft lockup’引起的failover切换

    案例说明: 在国产中标麒麟系统生产环境中,监控发现KingbaseES V8R3集群发生了failover的主备切换,客户需要给出分析报告,说明此次集群发生failover切换的原因,本次文档通过分析 ...

  10. 索引与查询使用的 collate 不一致导致无法使用索引

    索引与表的collate 不一致的情况下,会导致表上的索引不可用,这时要想使用索引,必须在SQL 语句指定建索引所用的collate. 数据库默认collate : test=# \l List of ...