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


    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()  
            }  
        }  
    }
    
  • 相关阅读:
    Python读取CSV文件,数值精度丢失
    如何进行数据库备份
    Chapter9.4:线性系统的状态空间分析与综合(下)
    SpringBoot 刷新上下文2--执行BeanDefinitionRegistryPostProcessor
    [附源码]java毕业设计“佳倍清家政”服务管理系统
    论文写作从 1 到 N
    css学习心得
    Java:继承和多态
    MAC M1大数据0-1成神篇-25 hadoop高可用搭建
    电子学会2022年6月青少年软件编程(图形化)等级考试试卷(三级)答案解析
  • 原文地址:https://www.cnblogs.com/laomuji666/p/18126525