前言
本节课学习 LazyRow 横向懒加载滚动列表;并且结合TextField输入框实现列表搜索过滤实战。复习Lazy系列懒加载DSL、remember状态,练习数据源过滤。
知识点清单
- LazyRow横向懒加载滚动列表(对比LazyColumn纵向列表)
- item{}、items{}、itemsIndexed{} 在LazyRow中的用法
- TextField文本输入维护搜索关键字状态
- Kotlin集合filter()过滤数据源,实现实时搜索
- 过滤之后渲染懒加载列表,状态驱动页面更新
完整示例源码
@ComposablefunLazyRowSearchDemoPage(){//原始完整数据源valoriginData=listOf("Java","Kotlin","Dart","Rust","Go","C++","C#","Swift","Cangjie","Python")//保存搜索框输入文本varsearchKeywordbyremember{mutableStateOf("")}// 根据关键字实时过滤数据源valfilterResult=remember(searchKeyword){originData.filter{item->item.contains(searchKeyword,ignoreCase=true)}}Column(modifier=Modifier.fillMaxSize().padding(20.dp),verticalArrangement=Arrangement.spacedBy(16.dp)){TextField(value=searchKeyword,onValueChange={searchKeyword=it},placeholder={Text("请输入搜索语言名称")},modifier=Modifier.fillMaxWidth())Text(text="横向热门语言(LazyRow)",fontSize=18.sp,fontWeight=FontWeight.Medium)LazyRow(horizontalArrangement=Arrangement.spacedBy(12.dp)){items(filterResult){name->Card(modifier=Modifier.height(80.dp),elevation=CardDefaults.cardElevation(4.dp)){Text(text=name,modifier=Modifier.padding(horizontal=16.dp).wrapContentHeight(Alignment.CenterVertically),fontSize=17.sp)}}}Text(text="纵向过滤结果(LazyColumn)",fontSize=18.sp,fontWeight=FontWeight.Medium)LazyColumn(modifier=Modifier.weight(1f).fillMaxWidth(),verticalArrangement=Arrangement.spacedBy(10.dp)){items(filterResult){name->Card(modifier=Modifier.fillMaxWidth()){Text(text=name,modifier=Modifier.padding(14.dp),fontSize=17.sp)}}}}}逐行解读
- LazyRow横向懒加载
- LazyRow:水平方向滚动的懒加载容器;对应LazyColumn垂直滚动。
- DSL语法和LazyColumn完全一样,支持 item{} 、 items{} 、 itemsIndexed{} 。
- horizontalArrangement.spacedBy(12.dp) 设置横向条目之间的间距。
- remember(key){ } 带依赖key的记忆
remember(searchKeyword) :当searchKeyword发生变化的时候,会重新执行大括号内的过滤逻辑;
searchKeyword不变的时候直接复用上一次过滤结果,避免不必要重复计算。 - filter集合过滤 + ignoreCase = true
contains(searchKeyword, ignoreCase = true) ,忽略大小写匹配;输入小写也可以匹配大写的文本。 - Modifier.weight(1f)
LazyColumn设置weight(1f),在Column垂直布局里面占掉剩余屏幕高度,防止列表挤压上面搜索框与横向LazyRow。
容易踩坑
- ❌ LazyRow内部同样必须使用item / items DSL,不可以直接写组件。
- ❌ 过滤数据源一定要写remember(依赖关键字),否则每次重组都会反复执行filter,造成不必要计算。
- ❌ 在Column里面直接给LazyColumn写fillMaxSize会布局异常;使用 weight(1f) 分配剩余高度。
- ✅ 搜索过滤:不要修改原始集合!基于原始数据源filter得到新的过滤后集合。
多元化习题(每道题后紧跟答案+解读)
习题1【基础‑改错题】
题目:找出下面LazyRow代码错误并修复
LazyRow(){Card(){Text("测试1")}Card(){Text("测试2")}}答案:
LazyRow(){items(listOf("测试1","测试2")){str->Card(){Text(str)}}}解读:
LazyRow属于懒加载DSL域,不能直接放置Card;UI条目必须包裹在item{}或者items{}内部,语法规则与LazyColumn完全一致。
习题2【基础‑代码修改题】
题目:在示例横向LazyRow的最前面增加一个头部卡片文本【🔥热门】,只显示一次。
答案:
LazyRow(horizontalArrangement=Arrangement.spacedBy(12.dp)){item{Card(elevation=CardDefaults.cardElevation(4.dp)){Text("🔥热门",modifier=Modifier.padding(16.dp).wrapContentHeight(Alignment.CenterVertically),fontSize=17.sp)}}items(filterResult){name->Card(modifier=Modifier.height(80.dp),elevation=CardDefaults.cardElevation(4.dp)){Text(text=name,modifier=Modifier.padding(horizontal=16.dp).wrapContentHeight(Alignment.CenterVertically),fontSize=17.sp)}}}解读:
横向列表的头部依然使用 item{} 单独渲染;item块渲染单个元素,不参与循环,放在items前面。LazyRow和LazyColumn的DSL接口完全统一。
习题3【进阶‑补充代码题】
题目:当filterResult过滤之后结果为空(没有搜索匹配项),纵向LazyColumn上方显示提示文本:“未查询到匹配数据”。写出该item片段。
答案:
LazyColumn(modifier=Modifier.weight(1f).fillMaxWidth(),verticalArrangement=Arrangement.spacedBy(10.dp)){if(filterResult.isEmpty()){item{Text("未查询到匹配数据",modifier=Modifier.padding(20.dp),fontSize=18.sp,color=Color.Gray)}}items(filterResult){name->Card(modifier=Modifier.fillMaxWidth()){Text(text=name,modifier=Modifier.padding(14.dp),fontSize=17.sp)}}}解读:
可以直接在Lazy的DSL里面写if分支;当过滤后的集合为空的时候渲染提示item;有数据就直接渲染items条目,实现空状态提示。
习题4【综合‑逻辑应用题】
题目:改造搜索逻辑,要求搜索的时候区分大小写(不再忽略大小写);同时如果搜索关键字为空字符串,纵向列表只展示前5条数据。书写remember过滤块代码。
答案:
valfilterResult=remember(searchKeyword){if(searchKeyword.isEmpty()){originData.take(5)}else{originData.filter{item->item.contains(searchKeyword)}}}解读:
去掉 ignoreCase=true 之后contains就严格区分大小写;take(5)截取集合前5个元素;利用remember(searchKeyword)绑定关键字作为依赖,关键字变化重新执行筛选逻辑。
习题5【概念简答题】
题目:LazyRow与LazyColumn异同是什么?
答案:
相同点:都属于懒加载组件,拥有视图复用;DSL语法item、items、itemsIndexed完全一致。
不同点:LazyRow是水平方向滚动;LazyColumn是垂直方向滚动;布局方向不一样,间距属性一个horizontalArrangement,一个verticalArrangement。
解读:
LazyRow适合横向滑动的标签、分类;LazyColumn适合长垂直数据列表;开发的时候根据产品UI滚动方向选型。
本节课知识点总结
- LazyRow横向懒加载滚动列表;和LazyColumn一样具备条目复用,适合横向滑动展示标签、分类。
- LazyRow与LazyColumn共享同一套DSL语法:item{}单独条目,items{}循环渲染。
- remember(key){ } 可以添加状态依赖;当key对应的值改变,块内逻辑重新运算;用于数据源过滤。
- 搜索过滤业务原则:保留原始数据源,基于原始集合filter生成过滤结果集合,不要修改原集合。
- 在Column嵌套LazyColumn的时候,LazyColumn优先使用 Modifier.weight(1f) 来分配剩余可用高度,避免布局报错。
下一课预告:第16课 Scaffold脚手架、TopAppBar顶部导航栏实战