双联列表

  • 效果图
  • 代码
    • 解析
      • 主要矛盾
    • 性能问题:
      • 次要矛盾

效果图

!

实现宜家 双联列表

00001.jpg?auth_key=4818491540-0-0-c8bbe27fc97f582aa0dd1b29a371a81f)(title-实现宜家 双联列表)]

代码


/*** 双联动列表* @param leftList List<String> 左侧条目* @param scrollToItem Function1<Int, Int> 右侧滑动影响左侧位置* @param itemToScroll Function1<Int, Int> 左侧滑动影响右侧位置,与上者互为反函数* @param content [@kotlin.ExtensionFunctionType] Function1<LazyListScope, Unit> 右侧内容填充物*/
@Composable
fun PartList(leftList : List<String>,scrollToItem : (Int) -> Int,itemToScroll : (Int) -> Int,content: LazyListScope.() -> Unit
)
{// 滑动状态val leftScrollState = rememberLazyListState()val rightScrollState = rememberLazyListState()// Remember a CoroutineScope to be able to launchval coroutineScope = rememberCoroutineScope()// 点击左侧的位置var onClickItem by remember {mutableStateOf(-1)}// 滑动右侧条目时,左侧联动// https://blog.csdn.net/vitaviva/article/details/121583183val getFirstVisibleItemIndex by remember {derivedStateOf {rightScrollState.firstVisibleItemIndex}}LaunchedEffect(Unit) {snapshotFlow { getFirstVisibleItemIndex }.collect {onClickItem = scrollToItem(it)}}//    run {// 这里应该自行设计何处位置为标头
//      onClickItem = scrollToItem(rightScrollState.firstVisibleItemIndex)// todo positive
//      coroutineScope.launch {
//          leftScrollState.scrollToItem(onClickItem)
//      }
//  }Row(modifier = Modifier.fillMaxSize()){LazyColumn(state = leftScrollState,modifier = Modifier.fillMaxHeight().background(IKEA_GRAY_LIGHT).weight(2f)){items(leftList.size){Row(modifier = Modifier.fillMaxWidth().height(40.dp).background(if (onClickItem == it) white else IKEA_GRAY_LIGHT) // val IKEA_GRAY_LIGHT = Color(245, 245, 245).clickable {// 点击左侧时设置跳转状态onClickItem = itcoroutineScope.launch {rightScrollState.animateScrollToItem(itemToScroll(it))}},verticalAlignment = Alignment.CenterVertically,horizontalArrangement = Arrangement.Center) {Text(text = leftList[it],modifier = Modifier,color = if(onClickItem == it) Color.Blue else Color.Black,fontSize = 11.sp,)}}}Spacer(modifier = Modifier.weight(0.5f))LazyColumn(state = rightScrollState,modifier = Modifier.fillMaxHeight().weight(8f),content = content)}
}

解析

主要矛盾

联动采用将两边滑动状态上提然后根据规则变动:

  1. 状态上提方法:
    通过rememberLazyListState来获取滑动状态
@Preview(showBackground = true, backgroundColor = 0xFFFFFFFF)
@Composable
fun PartList()
{// 滑动状态val leftScrollState = rememberLazyListState()val rightScrollState = rememberLazyListState()Row {// 左侧LazyColumn(state = leftScrollState,。。。){。。。。}Spacer(modifier = Modifier.weight(0.5f))// 右侧LazyColumn(state = rightScrollState,。。。) {。。。。}}
}
  1. 点击 左侧,右侧滑动到相应位置:
    a. 点击右侧:左侧跳转到相应标头
    b. 滑动右侧到新的标头:左侧跟着跳转

a) 左侧只要监听点击事件,然后对右侧跳转即可:
我们以 左侧条目Modifier来进行点击事件监听:

.clickable {onClickItem = it // it 是思点击左侧的索引号// 点击左侧时设置跳转状态,这里跳转标头可以自己设定coroutineScope.launch {rightScrollState.animateScrollToItem(it * 3)}
}

b) 右侧滑动是实时监听的,所以只需要在函数内最上层写相关变化即可:

// 滑动右侧条目时,左侧联动run {// 这里应该自行设计何处位置为标头onClickItem = (rightScrollState.firstVisibleItemIndex / 3)coroutineScope.launch {leftScrollState.animateScrollToItem(onClickItem)}}

性能问题:

上文中,直接访问rememberLazyListStatefirstVisibleItemIndex 不是一个好选择,他会造成性能问题。

在使用 LazyColumn 或者 LazyRow 时,应该避免在 LazyListScope 中访问 LazyListState,这可能会造成隐藏的性能问题

因此,我们需要改进:将判断 list 滚动的逻辑抽象为一个 getFirstVisibleItemIndex 状态,然后通过 snapshotFlow 单独定义其变化,这样避免 LazyColumncontent 的重组。

val getFirstVisibleItemIndex by remember {derivedStateOf {rightScrollState.firstVisibleItemIndex}}LaunchedEffect(Unit) {snapshotFlow { getFirstVisibleItemIndex }.collect {onClickItem = scrollToItem(it)}}

次要矛盾

也就是尽可能符合宜家设计标准:

  1. 点击左侧,左侧跳转到指定位置,这里就引入onClickItem 和其他外观区别。
  2. 其他讨论脱离文章范畴,不赘述。

【Android Compose】实现宜家 双联列表相关推荐

  1. Android JetPack Compose初步2~实现可滚动列表的功能

    Android JetPack Compose的配置参考Android JetPack Compose初步1 在本应用中定义可滚动的列表的界面,类似RecyclerView组件的显示效果. 一.定义实 ...

  2. android自带下拉阻尼动画,android 有阻尼下拉刷新列表的实现方法

    本文将会介绍有阻尼下拉刷新列表的实现,先来看看效果预览: 这是下拉状态: 这是下拉松开手指后listView回滚到刷新状态时的样子: 1. 如何调用 虽然效果图看起来样子不太好看,主要是因为那个蓝色的 ...

  3. Android Compose——一个简单的Bilibili APP

    Bilibili移动端APP 简介 依赖 效果 登录 效果 WebView 自定义TobRow的Indicator大小 首页 推荐 LazyGridView使用Paging3 热门 排行榜 搜索 模糊 ...

  4. 用树莓派4B和宜家台灯玩转AR投影黑科技(神卓互联系列)

    这是一款用树莓派(Raspberry Pi)和宜家台灯制作的智能家具,应用 Android Things 系统来实现 AR(增强现实)投影灯. Nord Projects 表示我们已经制作了一些类似的 ...

  5. 像宜家《家居指南》那样做邮件营销

    在Econsultancy.com的一项市场调研中发现,有68 %的公司认可电子邮件渠道,尽管他们在邮件营销上的市场预算仅为16%.而61%的市场营销人员却对自己的邮件营销不满意.邮件营销才是onli ...

  6. android毕业设计——基于Android+XAMPP+MySQL的家校互动平台设计与实现(毕业论文+程序源码)——家校互动平台

    基于Android+XAMPP+MySQL的家校互动平台设计与实现(毕业论文+程序源码) 大家好,今天给大家介绍基于Android+XAMPP+MySQL的家校互动平台设计与实现,文章末尾附有本毕业设 ...

  7. Android SystemUI之Recent,近期列表(五)

    Android  SystemUI系列: 1.Android  SystemUI之启动流程(一) 2.Android SystemUI之StatusBar,状态栏(二) 3.Android Syste ...

  8. 魔改宜家灯泡当主机,玩转《毁灭战士》无压力!网友:远超我家第一台电脑...

    贾浩楠 胡子豪 发自 凹非寺 量子位 报道 | 公众号 QbitAI 这年头,"万物皆可<毁灭战士>"!(Doom) 极客们把这款猛男必玩的游戏移植到五花八门的设备上, ...

  9. 宜家如何利用低代码平台提升员工效率,提高数据价值

    低代码开发已经在全球范围内的不同行业.不同企业中得到应用,并且使用的场景.角色等也在不断拓展.本文介绍低代码在零售领域的应用:构建敏捷的客户服务管理案例.此案例中不仅介绍了明确的人物角色和场景背景,还 ...

最新文章

  1. 腾讯发布人工智能辅助翻译,致敬人工翻译
  2. lnmp中怎么运行ngin和mysql_安装LNMP(Nginx+Mysql+PHP)
  3. Leetcode 67. 二进制求和 (每日一题 20210826)
  4. 持续5个月,200+笔记,3千多人参与,邀请你来学源码~
  5. leetcode 700. 二叉搜索树中的搜索 思考分析
  6. IBM Copy Service--Flashcopy Introduction
  7. 趣头条将获得阿里1.71亿美元的可转债,为期三年
  8. 布尔型Boolean+undefined+null(JS)
  9. Win10 环境变量配置
  10. imazing iOS设备管理软件
  11. 宁要城市一张床,不要农村一栋房
  12. ORA-22835:缓冲区对于CLOB到CHAR转换而言太小
  13. Microsoft visual studio关闭安全检查的几种方法
  14. NVIDIA详细解读游戏中DX9与DX11差别
  15. BugFree使用指南
  16. Daily Growing 的歌词
  17. 程序设计思想与方法 笔记
  18. 无桥PFC的优势及解决方案
  19. JS将秒数换算成时分秒 以及转化为年月日 时分秒以及多长时间以前
  20. 计算机网络实验以太网帧分析,实验二 用Ethereal捕获并分析以太网帧格式

热门文章

  1. 最新虚拟机SAP ECC6.0 EHP7带示例数据IDES版+BW740
  2. 贪心算法--最小耗费生成树(Prim算法)
  3. Html5 学习笔记 【PC固定布局】 实战5 咨询页面 侧栏
  4. 美团运维SRE+运维开发一面面经汇总
  5. 苹果电脑和手机浏览器的区分
  6. Gym - 101653T Runes [模拟]
  7. python import random 报错_导致python中import错误的原因是什么
  8. 分布式学习(3)etcd@2@HTTP API v2
  9. LiveGBS-摄像机网页低延时无插件直播实现
  10. vrchat模型保存_轻松简单自己上传VRChat的Avatar