Android Compose 一:基础控件

Flutter 与 Compose 组件辣么像,难道是同一个google团队整的;也未深究,只是猜测。

创建项目

需要使用新版本Android studio,忽略步骤...

项目目录

MainActivity说明
1 系统默认页面

@Preview 修饰的方法,只用来供开发者预览使用,删除不影响运行

@Composable 修饰的方法 只能被@Composable修饰的方法调用

预览效果

2 MyApplicationTheme 说明

MyApplicationTheme 对应的时 ui.theme 中的Theme.kt中的 MyApplicationTheme ; ctrl+左键点过去

下面看代码

复制代码
@Composable
fun MyApplicationTheme(
    darkTheme: Boolean = isSystemInDarkTheme(),
    // Dynamic color is available on Android 12+
    dynamicColor: Boolean = true,
    content: @Composable () -> Unit
) {

咋看这这么像flutter 万物皆组件嘞;咱也不懂,咱也不敢吭;

  • 同样MyApplicationTheme 是被@Composable注解修饰
darkTheme: Boolean = isSystemInDarkTheme(), //判断是否是暗黑主题

那么我们把它写死成ture;

预览结果 变黑啦

dynamicColor: Boolean = false, //动态颜色

暂未发现有啥变化

代码里判断了支持动态颜色,调用了

复制代码
/**
 * Creates a light dynamic color scheme.
 *
 * Use this function to create a color scheme based off the system wallpaper. If the developer
 * changes the wallpaper this color scheme will change accordingly. This dynamic scheme is a
 * light theme variant.
 *
 * @param context The context required to get system resource data.
 */
@RequiresApi(Build.VERSION_CODES.S)
fun dynamicLightColorScheme(context: Context): ColorScheme {
    val tonalPalette = dynamicTonalPalette(context)
    return lightColorScheme(
        primary = tonalPalette.primary40,
        onPrimary = tonalPalette.primary100,
        primaryContainer = tonalPalette.primary90,
        onPrimaryContainer = tonalPalette.primary10,
        inversePrimary = tonalPalette.primary80,
        secondary = tonalPalette.secondary40,
        onSecondary = tonalPalette.secondary100,
        secondaryContainer = tonalPalette.secondary90,
        onSecondaryContainer = tonalPalette.secondary10,
        tertiary = tonalPalette.tertiary40,
        onTertiary = tonalPalette.tertiary100,
        tertiaryContainer = tonalPalette.tertiary90,
        onTertiaryContainer = tonalPalette.tertiary10,
        background = tonalPalette.neutral99,
        onBackground = tonalPalette.neutral10,
        surface = tonalPalette.neutral99,
        onSurface = tonalPalette.neutral10,
        surfaceVariant = tonalPalette.neutralVariant90,
        onSurfaceVariant = tonalPalette.neutralVariant30,
        inverseSurface = tonalPalette.neutral20,
        inverseOnSurface = tonalPalette.neutral95,
        outline = tonalPalette.neutralVariant50,
    )
}

百度翻译

content: @Composable () -> Unit 页面布局内容@Composable修饰的组件

content 应该就是Surface,kotlin 最后一个参数如果是lambda表达式,那么lambda表达式可以放在外边

复制代码
@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
    MyApplicationTheme(
        content = {
            Surface(
                modifier = Modifier.fillMaxSize(),
                color = MaterialTheme.colorScheme.background
            ) {
                Greeting("Android")
            }
        }
    )
}

复制代码
@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
    MyApplicationTheme(){
        Surface(
            modifier = Modifier.fillMaxSize(),
            color = MaterialTheme.colorScheme.background
        ) {
            Greeting("Android")
        }
    }
}
MyApplicationTheme 方法的实现代码分析
复制代码
 val colorScheme = when {
        dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> {     //这就是动态颜色
            val context = LocalContext.current
            if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
        }

        darkTheme -> DarkColorScheme
        else -> LightColorScheme
    }
    val view = LocalView.current    
    if (!view.isInEditMode) {     //这个就是判断 是否在编辑模式  然后设置了状态栏的颜色
        SideEffect {
            val window = (view.context as Activity).window
            window.statusBarColor = colorScheme.primary.toArgb()
            WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = darkTheme  //这一样也是设置状态栏的颜色  大概意思就是看翻译
        }
    }

    MaterialTheme(
        colorScheme = colorScheme,    //设置主题颜色   ui.theme.Color
        typography = Typography,   // ui.theme.Type
        content = content
    )

view.isInEditMode 注释的翻译

WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = darkTheme

通过以上的分析,我们或许可以实现 多主题的功能 用来更改app的主题颜色 字体显示大小(比如老年模式)等功能 //TODO 后续尝试

基础组件

组件一般都包含Modifier的参数

复制代码
@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
    Text(
        text = "Hello $name!",
        modifier = Modifier.padding()
    )
}

方法参数有个 modifier: Modifier = Modifier ctrl+左键 点

发现是Modifier.kt 的对象

复制代码
 // The companion object implements `Modifier` so that it may be used as the start of a
    // modifier extension factory expression.
    companion object : Modifier {
        override fun <R> foldIn(initial: R, operation: (R, Element) -> R): R = initial
        override fun <R> foldOut(initial: R, operation: (Element, R) -> R): R = initial
        override fun any(predicate: (Element) -> Boolean): Boolean = false
        override fun all(predicate: (Element) -> Boolean): Boolean = true
        override infix fun then(other: Modifier): Modifier = other
        override fun toString() = "Modifier"
    }

使用Modifier都是使用 此伴生对象;是所有链式调用的起点

打个断点看看

例如我们写了如下代码

复制代码
Text(
        text = "Hello $name!",
        modifier = Modifier.padding(20.dp)
    )

调用的是Padding.kt的 其实使用的是 PaddingModifier

复制代码
@Stable
fun Modifier.padding(all: Dp) =
    this.then(
        PaddingModifier(
            start = all,
            top = all,
            end = all,
            bottom = all,
            rtlAware = true,
            inspectorInfo = debugInspectorInfo {
                name = "padding"
                value = all
            }
        )
    )

PaddingModifier 其实实现LayoutModifier

复制代码
private class PaddingModifier(
    val start: Dp = 0.dp,
    val top: Dp = 0.dp,
    val end: Dp = 0.dp,
    val bottom: Dp = 0.dp,
    val rtlAware: Boolean,
    inspectorInfo: InspectorInfo.() -> Unit
) : LayoutModifier, InspectorValueInfo(inspectorInfo) {

LayoutModifier

复制代码
@JvmDefaultWithCompatibility
interface LayoutModifier : Modifier.Element {

Modifier.Element

复制代码
  @JvmDefaultWithCompatibility
   interface Element : Modifier {
       override fun <R> foldIn(initial: R, operation: (R, Element) -> R): R =
           operation(initial, this)

       override fun <R> foldOut(initial: R, operation: (Element, R) -> R): R =
           operation(this, initial)

       override fun any(predicate: (Element) -> Boolean): Boolean = predicate(this)

       override fun all(predicate: (Element) -> Boolean): Boolean = predicate(this)
   }

Modifier 是个接口 实现如下

Modifier 可用来设置形状,大小,位置,边距,透明度,点击 等

例如 Text的modifier可以设置如下

modifier = Modifier.padding()

Padding.kt Modifer的扩展方法

Text 文本
复制代码
@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
    Text(
        text = "Hello $name!",
        modifier = modifier
    )
}
Image 图片
复制代码
 Image(
            painter = painterResource(id = R.drawable.img_lufei),  //资源
            contentDescription = "",   //描述
           modifier = Modifier.size(80.dp).clip(CircleShape),  //大小 形状
            contentScale = ContentScale.Crop  //渲染方式
        )
Spacer 空白
复制代码
 Text(text = "Hello $name!")
            Spacer(modifier = Modifier.padding(20.dp))
            Text(text = "Hello llo lo $name!")
Column 横布局
复制代码
 Column(
            modifier = Modifier.padding(10.dp)
        ) {
            Text(text = "Hello $name!")
            Spacer(modifier = Modifier.padding(20.dp))
            Text(text = "Hello llo lo $name!")
        }
Row 竖布局
复制代码
Row(
        modifier = Modifier.wrapContentHeight(align = Alignment.CenterVertically)
    ) {
        Image(
            painter = painterResource(id = R.drawable.img_lufei),
            contentDescription = "",
            modifier = Modifier.size(80.dp).clip(CircleShape),
            contentScale = ContentScale.Crop
        )

        Column(
            modifier = Modifier.padding(10.dp)
        ) {
            Text(text = "Hello $name!")
            Spacer(modifier = Modifier.padding(20.dp))
            Text(text = "Hello llo lo $name!")
        }
    }
效果
其他布局用到时详解
接下来的问题
  • 布局的对齐方式 在父布局中的位置 父布局控制子布局的位置
相关推荐
千里马学框架1 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台1 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone1 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc1 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo1 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077001 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼1 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone1 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen1 天前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone1 天前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui