Android全新UI编程 - Jetpack Compose 超详细教程 第3弹

7,370 阅读6分钟

0. 注意

这篇文章是参照了比较老的API,所以不推荐大家再阅读了。
最新的文章在这里:juejin.cn/post/695495…

1. 简介

Jetpack Compose是谷歌在2019Google i/o大会上发布的新的库。可以用更少更直观的代码创建View,还有更强大的功能,以及还能提高开发速度。

之前的文章在这里:
Android全新UI编程 - Jetpack Compose 超详细教程 第2弹
Android全新UI编程 - Jetpack Compose 超详细教程 第1弹

通过前两篇的学习,大家应该会有一个发现。Jetpack Compose跟Flutter好像啊。
是的,Compose好多方面借鉴了Flutter,所以有较高的相似度。
比如ScaffoldState等概念。

这一篇打算介绍ScaffoldSurfaceFloatingActionButton以及如何实现“RecyclerView”。
这篇应该会前两篇相对有趣一点。

(此篇文章是基于Compose的1.0-alpah1版本,如果因版本更新而Api有变更时我会随时对文章进行修订)

好了、行くぞ(一库走)!

2. 教程

2.1 Surface

当想为一个我们自定义的组件添加背景颜色时,我们就需要用到Surface。需要传入的参数如下。

2.1.1 参数

  • modifier: Modifier:
    为Surface设置modifier,第一篇中有讲述,这里就略过。

  • shape: Shape:
    为Surface设置形状,默认是RectangleShape。第二篇有讲述,这里就略过。

  • color: Color:
    为Surface设置颜色,也是为这一片区域设置背景颜色,默认是MaterialTheme.colors.surface。这里的默认值是在ThemeColorPalette中设置的surface值。

  • contentColor: Color:
    为Surface中的Text设置颜色。在Text中没有设置颜色时,才会被设置成contentColor的颜色。当contentColor没有被设置任何值时,会按下列的逻辑设置。

    1. 当Surface中有设置Color时,如果Color的颜色是ColorPalette的颜色,则contentColor会设置成与其搭配的默认颜色。如果不是则设置成Theme中的onSurface的颜色。有一个特例,当设置的Color颜色和Theme中的Surface的颜色一样时,contentColor会被设置成onSurface颜色。
    2. 当Surface中没有设置Color时,则直接设置成Theme中的onSurface的颜色。
  • border: Border?:
    为Surface设置外边框,默认是是null。关于border在第二篇的Button中有讲述,所以就略过了。

  • elevation: Dp:
    为Surface设置在Z轴方向上的高度。默认是0.dp

  • content: @Composable () -> Unit:
    为Surface设置内容布局,需要传入@Compose方法。

上面有两处讲到关于Theme,虽然在第一篇中有简单的讲到,但显然还是不够的。在讲完关键组件以后我会详细介绍一下Theme。

2.1.2 示例

Surface(modifier = Modifier.padding(4.dp),color = Color.Gray) {
    Column {
        Text(modifier = Modifier.gravity(Alignment.CenterHorizontally),text = "MOON")
        Image(modifier = Modifier.size(150.dp),asset = vectorResource(id = R.drawable.ic_mllogosvg))
            }
        }

2.2 Scaffold

Scaffold翻译成中文就是脚手架的意思。熟悉Flutter的朋友应该对这个词格外的熟悉。没错,这个也是来自Flutter。
在这个之前我们一直讲述的是如何利用组件进行布局,但是当我们想要创建一个完整的一个界面比如有toolbar,bottomNavigation等等时,就会不知所措。
在这个时候我们就需要用到Scaffold

2.2.1 参数

  • scaffoldState: ScaffoldState:
    设置Scaffold的State值,默认是remember { ScaffoldState() },这里是需要使用默认值即可。对State进行简单的解释一下,State的作用是外部通过改变state的值来通知UI也进行相应的更新显示。ScaffoldState中有控制drawer的开关状态的drawerState,和drawer是否应用手势操作的isDrawerGesturesEnabled。关于drawerState的具体使用方法在Drawer组件中为大家介绍。

  • topBar: @Composable (() -> Unit)?:
    设置app bar(toolbar)的布局。

  • bottomBar: @Composable ((FabConfiguration?) -> Unit)?:
    设置bottom bar(bottom navigation)的布局。

  • floatingActionButton: @Composable (() -> Unit)?:
    设置Fab按钮的布局。

  • floatingActionButtonPosition: FabPosition:
    设置Fab按钮的位置。默认是FabPosition.End。有两个值可以设置,FabPosition.End是表示在页面的右下角,FabPosition.Center是表示在页面底部的中间位置。

  • isFloatingActionButtonDocked: Boolean:
    设置Fab按钮是否嵌入到bottomBar中。默认是false

  • drawerContent: @Composable (() -> Unit)?:
    设置抽屉界面中的布局。

  • drawerShape: Shape:
    设置抽屉界面的样子。具体就不再赘述了。默认是MaterialTheme.shapes.large

  • drawerElevation: Dp:
    设置抽屉布局在Z轴上的高度。默认是DrawerConstants.DefaultElevation

  • backgroundColor: Color:
    设置背景颜色。具体就不再赘述了。默认是MaterialTheme.colors.background

  • bodyContent: @Composable (InnerPadding) -> Unit:
    在这里传入我们要在中心区域显示的布局。传入的参数为InnerPadding

2.2.2 示例

    Scaffold(
        scaffoldState = scaffoldState,
        topBar = { TopAppBarLayout(scaffoldState = scaffoldState) },
        bottomBar = { BottomBar() },
        drawerContent = { DrawerLayout(scaffoldState = scaffoldState) },
        floatingActionButton = { FloatingActionButtonLayout()},
        floatingActionButtonPosition = Scaffold.FabPosition.Center,
        isFloatingActionButtonDocked = true
    )

上面的代码中会用到TopAppbar,BottomBar,Drawer,FloatingActionButton等组件。除了FloatingActionButton以外,其他的组件会在下一篇为大家继续讲解。

2.3 FloatingActionButton

简单介绍一下Fab按钮的使用方法。需要传入的参数如下。

2.3.1 参数

  • onClick: () -> Unit:
    设置Fab按钮的点击事件。

  • modifier: Modifier:
    需要传入设置好的Modifier,参照第一篇。在这里就不再赘述了。

  • shape: Shape:
    设置Fab按钮的样子,参照第二篇。在这里就不再赘述了。默认是MaterialTheme.shapes.small.copy(CornerSize(percent = 50))

  • backgroundColor: Color:
    设置Fab按钮的背景颜色。默认是MaterialTheme.colors.secondary

  • contentColor: Color:
    设置Fab按钮中内容的颜色。默认是contentColorFor(backgroundColor)

  • elevation: Dp:
    设置Fab按钮在Z轴上的高度,默认是6.dp

  • icon: @Composable () -> Unit:
    设置Fab按钮中icon的布局。需要传入@Compose方法。

2.3.2 示例

FloatingActionButton(
        onClick = {},
        backgroundColor = Color.LightGray,
        contentColor = Color.Red,
        elevation = 10.dp
    ) {
        Icon(asset = Icons.Default.Star)
    }

2.4 LazyColumnFor, LazyRowFor

从名字就可以知道一个是横向显示,一个是纵向显示的组件。这个组件类似于我们经常使用的RecyclerView
在最开始的版本中是没有关于"RecyclerView"的组件,所以官方Sample(JetNews)中是用了在ScrollableColumn组件中手动加入了每一个view的方法,所以不能复用View,最终导致性能低下,有严重的卡顿感。
所以在之后的Compose版本中推出了AdapterList的组件,之后又改成LazyItems,但是在最新的版本中被废弃,启用了现在在讲述的LazyFor组件。

2.4.1 参数

  • items: List<T>:
    传入需要显示的数据。

  • modifier: Modifier:
    设置modifier,第一篇中有讲述,这里就略过。

  • itemContent: @Composable (T) -> Unit:
    传入每一项数据需要显示的布局。不要忘了需要是@Compose方法。其中方法的传参为items中的数据,可以利用它在布局中显示数据。

2.4.2 示例

LazyColumnFor(items = createData()) {
    Card(
        elevation = 3.dp,
        modifier = Modifier.padding(10.dp).fillMaxSize().heightIn(40.dp),
        border = Border(2.dp, Color.LightGray)
        ) {
            Column(
                horizontalGravity = Alignment.CenterHorizontally, 
                verticalArrangement = Arrangement.Center
                ) {
                    Text(text = it.toString(), modifier = Modifier.padding(10.dp,5.dp))
                }
            }
        }

3. 其他

好多人都在说Jetpack ComposeFlutter的用法很相似。因为Compose借鉴了不少Flutter的东西,所以用法相似在所难免。因此我非常推荐边学习Compose,又学习Flutter。能学到更多的知识的同时,也能学到Compose和Flutter相似和不同之处,加深理解。  

下一篇想讲一下,TopAppbar,BottomBar,Drawer组件和关于State
学习尚未成功,同志仍需努力!

Jetpack Compose官网
JetpackComposeDemo Github

Android全新UI编程 - Jetpack Compose 超详细教程:
第一弹
第二弹
第三弹

其他教程:
神一样的存在,Dagger Hilt !!
Android10的分区存储机制(Scoped Storage)适配教程
Android Jetpack Room的详细教程
Android的属性动画(Property Animation)详细教程
Android ConstraintLayout的易懂教程
Google的MergeAdapter的使用
Paging在Android中的应用
Android UI测试之Espresso
Android WorkManager的使用