
前言在内容型应用中视图切换是提升用户体验的重要功能。用户可以根据自己的偏好选择网格浏览或列表浏览。“海风日记“的首页支持双栏网格Grid和单栏列表List两种视图模式通过右上角的切换按钮实现一键切换。本文将从HomeTab.ets源码出发深入讲解 Grid 和 List 组件的完整配置、视图切换的实现机制以及数据驱动渲染的最佳实践。一、Grid 与 List 组件概述1.1 Grid 组件Grid 用于实现网格布局支持自定义列数、行数和间距Grid() { ForEach(this.diaryList, (item: DiaryEntry) { GridItem() { DiaryCard({ ... }) } }) } .columnsTemplate(1fr 1fr) // 双栏 .columnsGap(10) // 列间距 .rowsGap(10) // 行间距 .padding({ left: 12, right: 12 }) .layoutWeight(1)1.2 List 组件List 用于实现列表布局支持垂直或水平滚动List({ space: 12 }) { ForEach(this.diaryList, (item: DiaryEntry) { ListItem() { DiaryCard({ ... }) } }) } .padding({ left: 14, right: 14 }) .layoutWeight(1) .scrollBar(BarState.Off)1.3 Grid 与 List 的对比对比维度GridList布局方式网格单列显示密度高一屏可展示更多内容低适用场景图片为主、快速浏览文字为主、详细阅读内容展示单行显示更多信息信息更完整二、视图切换的实现2.1 状态变量Component export struct HomeTab { State isGridView: boolean true // 当前视图模式 State diaryList: DiaryEntry[] MOCK_DIARIES // 日记数据 }2.2 切换按钮Button() { SymbolGlyph( this.isGridView ? $r(sys.symbol.square_grid_2x2) // 网格图标 : $r(sys.symbol.list_bullet) // 列表图标 ) .fontSize(18) .fontColor([#C8956A]) } .width(30).height(30) .borderRadius(8) .backgroundColor(rgba(245,166,35,0.10)) .onClick(() { this.isGridView !this.isGridView })2.3 条件渲染视图if (this.isGridView) { // 双栏网格 Grid() { ForEach(this.diaryList, (item: DiaryEntry) { GridItem() { DiaryCard({ ... }) } }) } .columnsTemplate(1fr 1fr) .columnsGap(10).rowsGap(10) .padding({ left: 12, right: 12, bottom: TAB_BAR_HEIGHT 16 }) .layoutWeight(1) } else { // 单栏列表 List({ space: 12 }) { ForEach(this.diaryList, (item: DiaryEntry) { ListItem() { DiaryCard({ ... }) } }) } .padding({ left: 14, right: 14, bottom: TAB_BAR_HEIGHT 16 }) .layoutWeight(1) .scrollBar(BarState.Off) }三、Grid 组件的属性详解3.1 columnsTemplate.columnsTemplate(1fr 1fr) // 两列每列等宽columnsTemplate使用 fr 单位来分配列宽模板效果1fr 1fr两列等宽1fr 2fr第二列宽度是第一列的两倍repeat(3, 1fr)三列等宽3.2 间距控制.columnsGap(10) // 列间距 10vp .rowsGap(10) // 行间距 10vp3.3 滚动控制Grid 默认可滚动无需额外配置。如果需要禁用滚动Grid() .scrollBar(BarState.Off) // 隐藏滚动条四、List 组件的属性详解4.1 间距List({ space: 12 }) // 列表项间距 12vp4.2 滚动条List() .scrollBar(BarState.Off) // 隐藏滚动条 // 或 .scrollBar(BarState.Auto) // 自动显示 // 或 .scrollBar(BarState.On) // 始终显示4.3 列表项List() { ForEach(this.diaryList, (item: DiaryEntry) { ListItem() { DiaryCard({ ... }) } }) }五、视图切换的动画效果5.1 使用 animateTo.onClick(() { animateTo({ duration: 300 }, () { this.isGridView !this.isGridView }) })5.2 过渡动画// 视图切换时添加过渡动画 Grid() .transition({ type: TransitionType.Insert, scale: { x: 0, y: 0 } }) .transition({ type: TransitionType.Delete, scale: { x: 0, y: 0 } })六、数据驱动渲染6.1 ForEach 的使用ForEach( this.diaryList, // 数据源 (item: DiaryEntry) { // UI 构建函数 GridItem() { DiaryCard({ ... }) } }, (item: DiaryEntry) item.id // 键值生成函数 )6.2 键值的重要性键值用于标识列表项的唯一性帮助 ArkUI 高效更新列表键值必须是唯一的键值不建议使用数组索引建议使用数据 ID 作为键值七、常见问题与排查7.1 Grid 显示空白问题Grid 区域显示为空白。原因Grid 没有设置columnsTemplate或数据源为空。解决方案Grid() .columnsTemplate(1fr 1fr) // 必须设置列模板7.2 List 滚动条不消失问题设置了scrollBar(BarState.Off)但滚动条仍然显示。原因属性设置顺序错误。解决方案确保scrollBar在布局属性之后设置。总结本文通过“海风日记“首页的源码深入讲解了 Grid 和 List 组件的完整用法Grid 组件双栏网格布局的配置List 组件单栏列表布局的配置视图切换State 条件渲染实现一键切换属性详解columnsTemplate、间距、滚动条动画效果animateTo 和过渡动画数据驱动ForEach 的数据绑定和键值管理下一篇文章将深入讲解ForEach 数据驱动渲染敬请期待。如果这篇文章对你有帮助欢迎点赞、收藏⭐、关注你的支持是我持续创作的动力相关资源Grid 组件文档List 组件文档ForEach 文档海风日记项目源码[HarmonyOS 开发者官网](https://atomgit.com/openharmony/docs开源鸿蒙跨平台社区ArkUI 动画概述animateTo 动画