Giter VIP home page Giter VIP logo

composedouban's Introduction

前言

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

效果图

首先看下最终的效果图

特性

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

  1. 支持设置沉浸式状态栏及状态栏颜色
  2. 支持水平方向滚动,竖直方向滚动等多种UI效果
  3. 支持给Image设置渐变滤镜,以美化显示效果
  4. 支持标题与列表页联动
  5. 通过Paging支持了分页加载

主要实现

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

沉浸式状态栏设置

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

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

  1. 设置沉浸时状态栏
  2. 获取状态栏高度
  3. 设置状态栏颜色
override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // 1. 设置状态栏沉浸式
        WindowCompat.setDecorFitsSystemWindows(window, false)

        setContent {
            BD_ToolTheme {
            	// 加入ProvideWindowInsets
                ProvideWindowInsets {
                    // 2. 设置状态栏颜色
                    rememberSystemUiController().setStatusBarColor(
                        Color.Transparent, darkIcons = MaterialTheme.colors.isLight)
                    Column {
                    	// 3. 获取状态栏高度并设置占位
                        Spacer(modifier = Modifier
                            .statusBarsHeight()
                            .fillMaxWidth())
                        Text(text = "首页\r\n首页1\r\n首页2\r\n首页3")
                    }
                }
            }
        }
    }

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

Image设置渐变滤镜

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

@Composable
fun TopRankItem(item: HomeTopRank) {
    Box(
        modifier = Modifier
            .size(180.dp, 220.dp)
            .padding(8.dp)
            .clip(RoundedCornerShape(10.dp))
    ) {
    	// 1. 图片
        Image(
            painter = rememberCoilPainter(request = item.imgUrl),
            contentDescription = null,
            contentScale = ContentScale.Crop,
            modifier = Modifier.fillMaxSize()
        )
        Column(
            modifier = Modifier
                .fillMaxSize()
                // 渐变滤镜
                .background(
                    brush = Brush.linearGradient(
                        colors = listOf(Color(item.startColor), Color(item.endColor)),
                        start = Offset(0f, Float.POSITIVE_INFINITY),
                        end = Offset(Float.POSITIVE_INFINITY, 0f)
                    )
                )
                .padding(8.dp)

        ) {
            //内容
        }
    }
}

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

标题与列表联动

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

  1. 监听列表滚动,获取列表滚动offset
  2. 根据列表滚动offset设置Header效果,如背景或者高度变化等
@Composable
fun RankScreen(viewModel: RankViewModel = RankViewModel()) {
    val scrollState = rememberLazyListState()
    Box {
    	// 1. 监听列表
        LazyColumn(state = scrollState) {
            //列表内容
        }
        RankHeader(scrollState)
    }
}

@Composable
fun RankHeader(scrollState: LazyListState) {
    val target = LocalDensity.current.run {
        200.dp.toPx()
    }
    // 2. 根据列表偏移量计算比例
    val scrollPercent: Float = if (scrollState.firstVisibleItemIndex > 0) {
        1f
    } else {
        scrollState.firstVisibleItemScrollOffset / target
    }
    val activity = LocalContext.current as Activity
    val backgroundColor = Color(0xFF7F6351)
    Column() {
        Spacer(
            modifier = Modifier
                .fillMaxWidth()
                .statusBarsHeight()
                // 3. 根据比例设置Header的alpha,以实现渐变效果
                .alpha(scrollPercent)
                .background(backgroundColor)
        )
        //....
    }
}

如上所示,主要有三步:

  1. 监听列表
  2. 根据列表偏移量计算比例
  3. 根据比例设置Headeralpha,以实现渐变效果

利用Paging实现分页

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

  1. ViewModel中设置数据源
  2. 在页面中监听Paging数据
  3. 根据加载状态设置加载更多footr状态
//1. 设置数据源
class RankViewModel : ViewModel() {
    val rankItems: Flow<PagingData<RankDetail>> =
        Pager(PagingConfig(pageSize = 10, prefetchDistance = 1)) {
            MovieSource()
        }.flow
}

@Composable
fun RankScreen(viewModel: RankViewModel = RankViewModel()) {
    val lazyMovieItems = viewModel.rankItems.collectAsLazyPagingItems()
    Box {
        LazyColumn(state = scrollState) {
            // 2. 在页面中监听paging
            items(lazyMovieItems) {
                it?.let {
                    RankListItem(it)
                }
            }
            // 3. 根据paging状态设置加载更多footer状态等
            lazyMovieItems.apply {
                when (loadState.append) {
                    is LoadState.Loading -> {
                        item { LoadingItem() }
                    }
                }
            }
        }
    }
}

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

总结

项目地址

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

参考资料

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

composedouban's People

Contributors

ricardojiang avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

composedouban's Issues

滑动后状态问题

选择2016年,然后连续上下滑动一下,年份又回到第一个2020年了

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.