【Jetpack Compose版】玩Android App

7,463 阅读4分钟

前言

Compose正式版发布了也有一段时间了,碰巧近期没啥事,先实战一波。

项目代码地址在这里,有兴趣的大佬们可以点个StarPlayAndroid

效果图

1.png

2.png

3.png 目前的内容大概就是以上这些,大部分页面都有适配下拉刷新头

主要内容的实现

具体的源码可以在项目地址PlayAndroid中查看到,这里介绍部分主要功能的实现

设置主题颜色

image.png

image.png

image.png 实现起来非常轻松丝滑

  1. 新建一些主题对象,每个对象里面都有darkColors和lightColors变量
  2. 用一个MaterialTheme将页面包裹起来(MaterialTheme的content)
  3. 新建一个用于管理主题颜色的mutableState单例,后续只需要改变这个mutableState的value就可以改变主题颜色

沉浸式状态栏

WindowCompat.setDecorFitsSystemWindows(window, false)

一行代码就可以搞定,但后续想设置状态栏颜色或者获取状态栏真实高度的话就需要添加下面两个依赖才行

//正确获取状态栏高度
api "com.google.accompanist:accompanist-insets-ui:0.16.1"
//控制UI栏
api "com.google.accompanist:accompanist-systemuicontroller:0.16.1"

添加完依赖后用ProvideWindowInsets方法将页面包裹起来,就可以拿到真实的状态栏/导航栏高度了

ProvideWindowInsets {
    //页面
    MainCompose()
}

//间隔控件,高度为状态栏高度 如果不设置颜色这里会自己适配,但可能产生闪烁
Spacer(modifier = Modifier.background(MaterialTheme.colors.primary).statusBarsHeight().fillMaxWidth())
//间隔控件,高度为导航栏高度 如果不设置颜色这里会自己适配,但可能产生闪烁
Spacer(modifier = Modifier.background(MaterialTheme.colors.primary).navigationBarsHeight().fillMaxWidth())

项目里,我在NavHost每个页面的content中管理状态栏

//透明/沉浸式状态栏
StatsBarUtil().StatsBarColor(true)
//系统颜色的状态栏
StatsBarUtil().StatsBarColor(false)

image.png

/**
 * 设置状态栏颜色
 */
class StatsBarUtil {

    /**
     * [isTransparent] 是否透明
     * [statusBarColor] 状态栏颜色
     * [navigationBarColor] 导航栏颜色
     * [statusBarDarkIcons] 状态栏内容是否为深色
     * [navigationBarColorDarkIcons] 导航栏内容是否为深色
     */
    @Composable
    fun StatsBarColor(
        isTransparent: Boolean = false,
        statusBarColor: Color = if (isTransparent) Color.Transparent else MaterialTheme.colors.primary,
        navigationBarColor: Color = if (isTransparent) Color.Transparent else MaterialTheme.colors.background,
        statusBarDarkIcons: Boolean = statusBarColor.luminance() > 0.5f,
        navigationBarColorDarkIcons: Boolean = navigationBarColor.luminance() > 0.5f
        //如果要求使用深色图标但没有,将调用一个lambda来转换颜色,默认情况下是应用一个黑色框框
//        transformColorForLightContent: (Color) -> Color
    ) {
        rememberSystemUiController().apply {
            setStatusBarColor(statusBarColor, statusBarDarkIcons)
            setNavigationBarColor(navigationBarColor, navigationBarColorDarkIcons)
        }
    }

}

页面导航

这块想说一下的原因是因为感觉官网上对于带参跳转说的不太清楚,对于新人可能不太友好。

就以我们这个项目的H5页面举例,假设A页面跳转到H5页面的时候要传一个“你好”,H5页面怎么拿到?

起始地

//不带参跳转到H5页面
navController.navigate(“H5”)
//带参跳转到H5页面
navController.navigate("H5?url=你好")

ps:带参的话就跟请求参数一样在后面添加 ?xxx=数据,其中这个xxx就是参数的key

目的地

//H5页面  不带参
composable(
    route = "H5",
) { backStackEntry ->
    WebViewCompose(navController)
}
//H5页面  带参
composable(
    route = "H5?url={url}",
    //默认值defaultValue
    arguments = listOf(
        navArgument("url") { defaultValue = "https://www.wanandroid.com/" })
) { backStackEntry ->
    WebViewCompose(navController, backStackEntry.arguments?.getString("url") ?: "https://www.wanandroid.com")
}

通过backStackEntry.arguments?.getString("url")就可以拿到传过来的值,然后再把数据给页面使用,这些是可选参数,如果不传的话会采用defaultValue设置的默认值或nullability = true(值为null)

可以拼接多个参数: ?url="你好"?:xxx="yyy"

也可以使用占位符(必传)

起始地
navController.navigate("h5/你好")

目的地
composable("H5/{url}"){ backStackEntry ->
    val url = backStackEntry.arguments?.getString("url")
}


封装的列表管理控件(带刷新头)

image.png

image.png content的内容是item的布局,使用的时候几行代码就搞定了一个列表,还是比较爽的,在列表子项布局不变的情况下可以使用,Paging数据和普通的List数据都有适配

遇到的问题

由于资料的欠缺其实在开发中还是遇到过不少问题,其中印象比较深刻的是下面这个

当BottomNavigation遇到NavHost

对于BottomNavigation的使用,一开始采用的是Android Developers上面的写法 image.png 写主界面的时候还没发现有问题,当需要跳转到二级页面的时候问题出现了:登录页面被嵌套在了脚手架中,TopBar和BottomNavigation没有隐藏 错误1.jpg 当时看到问题的第一反应就是,跳转到二级页面的时候不走主界面Scaffold布局代码,也就是变相隐藏掉主界面的布局。

但紧接着一想,如果是这样的话那么官方文档里的NavHost好像有些问题,那会不会是我自己不会用呢?最后哪里都去找哪里都去问也没有啥思路,目前是这样的,如果有更好的解决方案可以留言,非常感谢!

image.png

image.png

后续开发计划

  • 首页:Banner、置顶消息、文章搜索
  • 文章的点赞、收藏
  • 查看文章详情页面完善
  • 添加动画效果

另外近期打算找工作,得复习面试的东西,尽量更新,勿怪。

总结

Compose香啊,写起来有点爽!

入行并不是很久,所以可能写出任何BUG(狗头),欢迎多多提issues,也希望各位大佬们多多指导。

特别感谢

其他资源分享

apk下载链接

项目地址

欢迎Star~PlayAndroid