Google I/O: as últimas alterações no Android Jetpack (4) Compose

prefácio

Esta série de artigos leva você a entender o conteúdo mais recente do Jetpack nesta E/S nas quatro direções de Arquitetura, IU, Desempenho e Composição.

Este artigo é o último: Compose.

O compartilhamento de tópicos sobre o Compose na conferência I/O deste ano aumentou significativamente, o que também mostra que o Google atribui grande importância à promoção do Compose. Atualmente, existem mais de 100 aplicativos usando o Compose no Google Play Top 1000 aplicativos, incluindo alguns aplicativos líderes na área. A estabilidade e maturidade do Compose também foram verificadas por esta oportunidade.

Vamos ver o que há de novo na versão 1.2 Beta mais recente do Compose.

1. Matéria 3

A biblioteca Compose.M3 recém-adicionada pode nos ajudar a desenvolver interfaces de interface do usuário que estejam em conformidade com as especificações de design do Material You.

implementation "androidx.compose.material3:material3:1.0.0-alpha10"
implementation "androidx.compose.material3:material3-window-size-class:1.0.0-alpha10"
复制代码

O Material3 enfatiza a personalização e a troca dinâmica de cores, e o Compose.M3 apresenta a classe ColorScheme para personalizar o esquema de cores:

val AppLightColorScheme = lightColorScheme (
    primary = Color(...),
    // secondary、tertiary 等等
    // 具有浅色基准值的 ColorScheme 实例
)
 
val AppDarkColorScheme = darkColorScheme(
    // primary、secondary、tertiary 等等
    // 具有深色基准值的 ColorScheme 实例val dark = isSystemInDarkTheme()
val colorScheme = if (dark) AppDarkColorScheme else AppLightColorScheme
 
// 将 colorScheme 作为参数传递给 MaterialTheme。
MaterialTheme (
    colorScheme = colorScheme,
    // 字型
) {
    // 应用内容
}
复制代码

O exemplo acima é um exemplo de MaterialTheme configurando diferentes cores de tema através do ColorScheme. Você pode ver que isso não é muito diferente do uso de Colors no Compose.M2, mas o ColorScheme pode definir mais slots de cores (Primary, Secondary, Error e outras cores MD constantes) e a correspondência dinâmica de cores DynamicColor também pode ser suportada.

DynamicColor é um recurso importante do Material 3. Em dispositivos Android12 e superiores, a cor do aplicativo pode ser alterada com o papel de parede. Este efeito agora também pode ser alcançado em Compose

// Dynamic color is available on Android 12+
val dynamicColor = Build.VERSION.SDK_INT >= Build.VERSION_CODES.S
val colorScheme = when {
    dynamicColor && darkTheme -> dynamicDarkColorScheme(LocalContext.current)
    dynamicColor && !darkTheme -> dynamicLightColorScheme(LocalContext.current)    
    darkTheme -> DarkColorScheme    
    else -> LightColorScheme
}
复制代码

如上,Compose 通过 dynamicXXXColorScheme 设置的颜色,无论是亮色还是暗色主题,都可以跟随用户设置的壁纸而变化:

更多参考:juejin.cn/post/706441…

2. Nested Scrolling Interop

Compose 支持与传统视图控件进行互操作,便于我们阶段性的引入 Compose 到项目中。但是在涉及到带有 Nested Scrolling 事件分发的场景中(例如 CoordinatorLayout ),会发生事件无法正常传递的兼容性问题,在 1.2 中对于此类问题进行了修复,无论是 CoordinatorLayout 内嵌 Composable , 或者在 Composable 中使用 Scrolling View 控件,事件传递都会更加平顺:

android-review.googlesource.com/c/platform/…
android-review.googlesource.com/c/platform/…

3. Downloadable Fonts

Android 8.0(API level 26)起支持了对可下载的谷歌字体的使用,允许通过代码动态请求一个非内置字体文件。在 Compose 1.2 对此功能也进行了支持,注意这个功能需要基于 GMS 服务。

implementation "androidx.compose.ui:ui-text-google-fonts:1.1.1"
复制代码

使用时,首先使用 FontProvider 定义字体请求信息

@OptIn(ExperimentalTextApi::class)
val provider = GoogleFont.Provider(
   providerAuthority = "com.google.android.gms.fonts",
   providerPackage = "com.google.android.gms",
   certificates = R.array.com_google_android_gms_fonts_certs
)
然后,使用此 Provider 定义 FontFamily,接着在 Composable 应用即可,
val fontName = GoogleFont(“Lobster Two”)

val fontFamily = FontFamily(
   Font(googleFont = GoogleFont(name), fontProvider = provider)
)

Text(
    fontFamily = fontFamily,
    text = "Hello World!"
)
复制代码

4. Lazy Grid

Compose 1.2 中进一步优化了 LazyRow 和 LazyColumn 的性能,并在此基础上新增了 LazyGrid 用来实现需求中常见的网格布局效果。Lazy Grid 在 1.0.2 就已经引入,如今 1.2 中对 API 进行调整并使之达到稳定。

image.png

以 LazyVerticalGrid 为例,我们可以通过 GridCells.Fixed 设置每行单元格的数量:

val data = listOf("Item 1", "Item 2", "Item 3", "Item 4", "Item 5")

LazyVerticalGrid(
    columns = GridCells.Fixed(3),
    contentPadding = PaddingValues(8.dp)
) {//this: LazyGridScope
    items(data.size) { index ->
        Card(
            modifier = Modifier.padding(4.dp),
            backgroundColor = Color.LightGray
        ) {
            Text(
                text = data[index],
                textAlign = TextAlign.Center
            )
        }
    }
}
复制代码

此外,也可以通过 GridCells.Adaptive() 通过制定单元格大小决定每行的数量。此时,所有单元格都会以 Adaptive 中的值设置统一的 width。

LazyGridScope 像 LazyListScope 一样也提供了 item, items, itemsIndexed 等方法布局子项。另外 LazyGridState 中的方法也基本上对齐了 LazyListState。

5. Tools

在工具方面,Android Studio 为 Compose 的开发调试提供了更多实用功能。

@Preview & Live Edit

1.2.0 中的 @Preview 可以作为元注解使用,修饰其他自定义注解

@Preview(showBackground = true)
@Preview(showBackground = true, uiMode = UI_MODE_NIGHT_YES)
annotation class MyDevices()

@MyDevices
@Composable
fun Greeting() {
    ...
}
复制代码

如上,我们可以通过自定义注解可以复用 @Preview 中的各种配置,减少为了预览而写的模板代码。

说到预览,Android Studio 一直致力于提升预览效率,Android Studio Arctic Fox 曾引入 Live literals 功能,对于代码中 Int,String,Color,Dp,Boolean 等常见类型的字面值的修改,无需编译即可在预览画面中实时更新。本次大会上带来了升级版的 Live Edit,它需要使用最新的 Android Studio Electric Eel 中开启。不仅仅是字面值,它可以让任意代码的修改(函数签名变动之类的修改不行),在预览窗口或者你的设备上立即生效,几乎实现了前端一般的开发体验,是本次大会令我惊喜的功能,它将大幅提高 Compose 的开发和调试效率。

ezgif.com-gif-maker (19).gif

Layout Inspector & Recomposition Counts

我们在传统视图开发中经常使用 Layout Inspector 观察视图结构, Compose 虽然基于 Composable 函数构建 UI ,但同样也得到了 layout Inspector 的支持,它可以帮助我们查看 Composition 视图树的布局。

此外,本次 I/O 还介绍了 Layout Inspector 的一个新功能 Recomposition Counts,我们知道不必要的重组会拖慢 Compose UI 的刷新性能,借助这个新工具,我们可以在 IDE 中调试和观察 Composable 重组次数,帮助我们及时发现和优化不符合预期的多余重组。

Animation Preview

Android Studio 增加了对 Compose 动画效果实时预览。在动画预览窗口中,每个动画的状态值会以多轨道的形式呈现,我们可以查看特定时间点下的每个动画值的确切值,并且可以暂停、循环播放动画、快进或放慢动画,以便在动画过渡过程中调试动画。

Compose 的动画 API 数量众多,目前并非所有的 API 都支持预览,IDE 会自动检查代码中可以进行预览的动画,并添加 Start Animation Inspection 图标,便于开发者发现和使用

6. 适应多种屏幕尺寸

Compose 正逐渐成为 Android 的首选 UI 开发方案,所以为了覆盖尽可能多的使用场景,Compose 第一时间对各种屏幕尺寸下(手机,平板,电脑,折叠屏)的 UI 开发进行了支持。 在具体开发中,我们需要先定义 WindowSizeClass 对各种屏幕类型分类,推荐分为三类:

当屏幕尺寸因为设备折叠等发生变化时,Compose 会自动响应 onConfigurationChanged 触发重组,重组中我们根据当前屏幕尺寸转换为对应的 WindowSizeClass

@Composable
fun Activity.rememberWindowSizeClass(): Pair<WindowWidthSizeClass, WindowHeightSizeClass> {
    val configuration = LocalConfiguration.current
    val windowMetrics = remember(configuration) {
        WindowMetricsCalculator.getOrCreate()
            .computeCurrentWindowMetrics(this)
    }
    val windowDpSize = with(LocalDensity.current) {
        windowMetrics.bounds.toComposeRect().size.toDpSize()
    }
    val widthWindowSizeClass = when {
        windowDpSize.width < 600.dp -> WindowWidthSizeClass.Compact
        windowDpSize.width < 840.dp -> WindowWidthSizeClass.Medium
        else -> WindowWidthSizeClass.Expanded
    }

    val heightWindowSizeClass = when {
        windowDpSize.height < 480.dp -> WindowHeightSizeClass.Compact
        windowDpSize.height < 900.dp -> WindowHeightSizeClass.Medium
        else -> WindowHeightSizeClass.Expanded
    }

    return widthWindowSizeClass to heightWindowSizeClass
}
复制代码

接下来,我们就可以面向 WindowSizeClass 进行 Composable 布局了,这样做的好处是,无需关心具体的 width/height 数值,更不需要关心当前设备类型是平板还是手机,因为未来,硬件种类的界限将越来越模糊,所以最合理的分类方式是 WindowSizeClass。

@Composable
fun MyApp(widthSizeClass: WindowWidthSizeClass) {
    // 非 Compact 类型屏幕时,不显示 AppBar
    val showTopAppBar = widthSizeClass != WindowWidthSizeClass.Compact

    // MyScreen 不依赖 WindowSizeClass,只需要知道是否显示 showTopAppBar,关注点分离
    MyScreen(
        showTopAppBar = showTopAppBar,
        /* ... */
    )
}
复制代码

当然我们可以使用 Android Studio 便利的预览功能,同时查看多种屏幕尺寸下的显示效果

Práticas recomendadas: agora no Android

Por fim, recomendo o Now In Android, um novo projeto que o Google acabou de abrir. Now in Android é o blog técnico oficial do Android, compartilhando artigos e vídeos técnicos. Agora este blog tem seu próprio cliente e é open source no Github, github.com/android/now…

Os desenvolvedores podem acompanhar melhor as últimas tendências técnicas do Android por meio do aplicativo e, mais importante, é uma prática recomendada do Android Jetpack. Tecnicamente, ele possui as seguintes características:

  • Implementar a interface do usuário com base no Jetpack Compose
  • Estilos e temas visuais baseados em Material3
  • Suporte para telas de diferentes tamanhos, podendo se adaptar ao layout
  • A arquitetura geral segue o paradigma UDF do documento oficial
  • Implemente o modelo de programação reativa baseado no Kotlin Flow
  • Seguindo o primeiro princípio de design Offline, a fonte de dados local é implementada com base em Room e Proto DataSotre.
  • Sincronização entre fontes de dados remotas/locais com base no WorkManager

Além disso, o GIthub também anexa um documento de design de arquitetura para ajudar você a entender suas ideias de desenvolvimento. Agora no Android foi programado para ser listado no GooglePlay. Comparado com outras demos do Jetpack, é mais realista e perfeito, e vale muito a pena para todos estudar e aprender. .

Acho que você gosta

Origin juejin.im/post/7098146948254793735
Recomendado
Clasificación