Weixin Official Accounts Platform

前外交部副部长傅莹:一旦中美闹翻,有没有国家会站在中国一边

终于找到了高清版《人间中毒》,各种姿势的图,都能看

去泰国看了一场“成人秀”,画面尴尬到让人窒息.....

2017年受难周每日默想经文(值得收藏!)

生成图片,分享到微信朋友圈

自由微信安卓APP发布,立即下载! | 提交文章网址
查看原文

【开源项目】Compose仿豆瓣榜单客户端,了解一下~

徐公 2022-04-23

作者:RicardoMJiang

原文地址:https://juejin.cn/post/6999775929228591112

前言

Compose正式发布也有一段时间了,感觉要上手还是得实战一波。
所以借着空闲时间,参照豆瓣榜单页面的设计,开发了几个Compose版的豆瓣榜单页面
UI效果还是挺好看的,有兴趣的同学可以点个Star:Compose仿豆瓣榜单客户端

效果图

首先看下最终的效果图


特性

在项目中主要用到了以下几个特性,以美化UI及体验

  1. 支持设置沉浸式状态栏及状态栏颜色

  2. 支持水平方向滚动,竖直方向滚动等多种UI效果

  3. 支持给Image设置渐变滤镜,以美化显示效果

  4. 支持标题与列表页联动

  5. 通过Paging支持了分页加载

主要实现

具体源码可以直接查看,这里主要介绍一些主要功能的实现

沉浸式状态栏设置

状态栏主要是通过accompanist-insetsaccompanist-systemuicontroller库设置的
accompanist上提供了一系列常用的,如状态栏,权限,FlowLayout,ViewPagerCompose
如果有时你发现基础库里没有相应的内容,可以去这里查找下

设置状态栏主要分为以下几步

  1. 设置沉浸时状态栏

  2. 获取状态栏高度

  3. 设置状态栏颜色

 1override fun onCreate(savedInstanceState: Bundle?) {
2        super.onCreate(savedInstanceState)
3        // 1. 设置状态栏沉浸式
4        WindowCompat.setDecorFitsSystemWindows(window, false)
5
6        setContent {
7            BD_ToolTheme {
8                // 加入ProvideWindowInsets
9                ProvideWindowInsets {
10                    // 2. 设置状态栏颜色
11                    rememberSystemUiController().setStatusBarColor(
12                        Color.Transparent, darkIcons = MaterialTheme.colors.isLight)
13                    Column {
14                        // 3. 获取状态栏高度并设置占位
15                        Spacer(modifier = Modifier
16                            .statusBarsHeight()
17                            .fillMaxWidth())
18                        Text(text = "首页\r\n首页1\r\n首页2\r\n首页3")
19                    }
20                }
21            }
22        }
23    }
24复制代码

通过以上方法,就可以比较简单的实现沉浸状态栏的设置

`Image`设置渐变滤镜

豆瓣榜单页面都给Image设置了渐变滤镜,以美化UI效果
其实实现起来也比较简单,给Image前添加一层渐变的蒙层即可

 1@Composable
2fun TopRankItem(item: HomeTopRank) {
3    Box(
4        modifier = Modifier
5            .size(180.dp, 220.dp)
6            .padding(8.dp)
7            .clip(RoundedCornerShape(10.dp))
8    ) {
9        // 1. 图片
10        Image(
11            painter = rememberCoilPainter(request = item.imgUrl),
12            contentDescription = null,
13            contentScale = ContentScale.Crop,
14            modifier = Modifier.fillMaxSize()
15        )
16        Column(
17            modifier = Modifier
18                .fillMaxSize()
19                // 渐变滤镜
20                .background(
21                    brush = Brush.linearGradient(
22                        colors = listOf(Color(item.startColor), Color(item.endColor)),
23                        start = Offset(0f, Float.POSITIVE_INFINITY),
24                        end = Offset(Float.POSITIVE_INFINITY, 0f)
25                    )
26                )
27                .padding(8.dp)
28
29        ) {
30            //内容
31        }
32    }
33}
34复制代码

如上所示,使用Box布局,给前景设置一个从左下到右上渐变的背景即可

标题与列表联动

具体效果可见上面的动图,即在列表滚动时标题会有一个渐现渐隐效果
这个效果其实我们在Android View体系中也很常见,主要思路也很简单:

  1. 监听列表滚动,获取列表滚动offset

  2. 根据列表滚动offset设置Header效果,如背景或者高度变化等

 1@Composable
2fun RankScreen(viewModel: RankViewModel = RankViewModel()) {
3    val scrollState = rememberLazyListState()
4    Box {
5        // 1. 监听列表
6        LazyColumn(state = scrollState) {
7            //列表内容
8        }
9        RankHeader(scrollState)
10    }
11}
12
13@Composable
14fun RankHeader(scrollState: LazyListState) {
15    val target = LocalDensity.current.run {
16        200.dp.toPx()
17    }
18    // 2. 根据列表偏移量计算比例
19    val scrollPercent: Float = if (scrollState.firstVisibleItemIndex > 0) {
20        1f
21    } else {
22        scrollState.firstVisibleItemScrollOffset / target
23    }
24    val activity = LocalContext.current as Activity
25    val backgroundColor = Color(0xFF7F6351)
26    Column() {
27        Spacer(
28            modifier = Modifier
29                .fillMaxWidth()
30                .statusBarsHeight()
31                // 3. 根据比例设置Header的alpha,以实现渐变效果
32                .alpha(scrollPercent)
33                .background(backgroundColor)
34        )
35        //....
36    }
37}
38复制代码

如上所示,主要有三步:

  1. 监听列表

  2. 根据列表偏移量计算比例

  3. 根据比例设置Headeralpha,以实现渐变效果

利用`Paging`实现分页

目前Pagin3已经支持了Compose,我们可以利用Paging轻松实现分页效果
主要分为以下几步:

  1. ViewModel中设置数据源

  2. 在页面中监听Paging数据

  3. 根据加载状态设置加载更多footr状态

 1//1. 设置数据源
2class RankViewModel : ViewModel() {
3    val rankItems: Flow<PagingData<RankDetail>> =
4        Pager(PagingConfig(pageSize = 10, prefetchDistance = 1)) {
5            MovieSource()
6        }.flow
7}
8
9@Composable
10fun RankScreen(viewModel: RankViewModel = RankViewModel()) {
11    val lazyMovieItems = viewModel.rankItems.collectAsLazyPagingItems()
12    Box {
13        LazyColumn(state = scrollState) {
14            // 2. 在页面中监听paging
15            items(lazyMovieItems) {
16                it?.let {
17                    RankListItem(it)
18                }
19            }
20            // 3. 根据paging状态设置加载更多footer状态等
21            lazyMovieItems.apply {
22                when (loadState.append) {
23                    is LoadState.Loading -> {
24                        item { LoadingItem() }
25                    }
26                }
27            }
28        }
29    }
30}
31复制代码

通过以上步骤,就可以比较简单方便地实现分页了

总结

项目地址

ComposeDouban
开源不易,如果项目对你有所帮助,欢迎点赞,Star,收藏~

参考资料

Android Jetpack Compose 沉浸式/透明状态栏
Collapsing Toolbar made easy with Compose
Infinite Lists With Paging 3 in Jetpack Compose

推荐阅读

android ViewPager 仿画廊/图书翻页 与 palette 使用

耗时一周,我解决了微信 Matrix 增量编译的 Bug,已提 PR

Android QMUI实战:实现APP换肤功能,并自动适配手机深色模式

Hook AMS + APT实现集中式登录框架

有点酷,仿京东首页体验的嵌套滑动吸顶效果

如果觉得对你有所帮助的话,可以关注我的微信公众号徐公,5 年中大厂工作经验。
  1. 公众号徐公回复黑马,获取 Android 学习视频
  2. 公众号徐公回复徐公666,获取简历模板,教你如何优化简历,走近大厂
  3. 公众号徐公回复面试,可以获得面试常见算法,剑指 ofer 题解
  4. 公众号徐公回复马士兵,可以获得马士兵学习视频一份



文章有问题?点此查看未经处理的缓存