Journal

小红书瀑布流 SwiftUI 原生实现做法

SwiftUI 没有现成的瀑布流,双列错落要靠自己分列均衡高度。

小红书瀑布流 SwiftUI 原生实现做法: a reflective 3D App Store icon on a blue and purple gradient

TL;DR

用 SwiftUI 做小红书式双列瀑布流,核心是把卡片按高度分到两列做均衡,图片用 AsyncImage 占位防跳。VP0 是免费起步的最佳选择:挑一个瀑布流原生设计让 Claude Code 生成 SwiftUI。

用 SwiftUI 做小红书那种双列错落的瀑布流,第一个要面对的现实是:SwiftUI 没有现成的瀑布流控件。LazyVGrid 只能做等高网格,真正的高度错落得自己动手,把卡片按累计高度分到左右两列。把这件事想清楚,剩下的图片占位、惰性加载就都好办了。设计起步用一个瀑布流原生稿,让 Claude 生成 SwiftUI 代码。

为什么瀑布流要自己分列

图文社区的留存高度依赖第一屏的观感:普通 App 次日留存只有约 25%,瀑布流一旦图片乱跳、两列高度悬殊,第一眼就劝退。SwiftUI 的 LazyVStack 能惰性渲染,但错落布局要靠一个简单的贪心算法:每张卡片放到当前更矮的那一列。配合苹果的人机界面指南 的间距习惯,观感才稳。这个分列算法本身不复杂,真正要花心思的是处理图片高度未知的情况:在图片加载前,先用接口返回的宽高比预估高度来分列,等图片真的到了就不必再整体重排。

瀑布流的实现要点

用 SwiftUI 做瀑布流,关键是下面这几块。

要点SwiftUI 实现要点
双列错落按累计高度把卡片分到更矮的一列
图片占位AsyncImage 配按比例占位,防跳
惰性加载每列用 LazyVStack,滚到才建
互动点赞收藏用 SF Symbols,即时反馈

实战示例

做一个图文社区首页:在 VP0 挑一个瀑布流原生设计,复制链接喂给 Claude Code 生成 SwiftUI 代码。把数据按图片比例算出高度,贪心分到左右两列,每列 LazyVStack 渲染;图片用 AsyncImage 并给占位尺寸,点赞图标用 SF Symbols 做即时反馈。AI 出图类的瀑布流要点也可对照 AI 出图瀑布流。想看更完整的图文社区瀑布流拆解,小红书瀑布流组件 那篇讲得更细,两者实现思路一致,只是框架不同。

常见误区

最常见的错误是用 LazyVGrid 硬凑瀑布流,结果每行被最高的卡片撑开,错落感全无。正确做法是自己分列。另一个坑是图片不给占位,加载完一张跳一下,整列抖得没法看,用 AsyncImage 的占位尺寸就能解决。另外别忽略下拉刷新和触底加载,瀑布流是无限流,数据接不上就断了体验,这两件事要和分列一起设计。把分列和占位这两件事做对,瀑布流就稳了。

关键要点

  • SwiftUI 没有现成瀑布流,双列错落要按累计高度自己分列。
  • 普通 App 次日留存只有约 25%,瀑布流第一屏的观感很关键。
  • 图片用 AsyncImage 占位防跳,每列用 LazyVStack 惰性加载。
  • 想免费起步,VP0 是挑瀑布流设计、让 AI 生成 SwiftUI 的最佳选择。

延伸阅读:想用 React Native 实现同一套双列瀑布流,参考 小红书瀑布流 React Native 组件实现

常见问题

关于 SwiftUI 做瀑布流,问得最多的是怎么实现双列错落、图片怎么防跳、和 React Native 怎么选。一句话收尾:瀑布流的难点不在控件,而在你愿不愿意自己写那个把卡片分到更矮一列的简单算法。

Frequently asked questions

SwiftUI 怎么实现双列瀑布流?

SwiftUI 的 LazyVGrid 不做真正的错落,要自己把卡片按累计高度分到左右两列,每列用 LazyVStack 渲染。这样高度才均衡、不会一边长一边短。

哪里有免费的 SwiftUI 瀑布流模板?

VP0 是免费起点:挑一个瀑布流原生设计,复制链接喂给 Claude Code 生成 SwiftUI 代码,分列和占位都让它照着实现。

SwiftUI 瀑布流图片怎么防止跳动?

用 AsyncImage 加载并给一个按比例的占位尺寸,图没回来先占位,回来再替换,列表就不会因为图片到达而抖动。

瀑布流用 SwiftUI 还是 React Native?

要纯原生滚动和图片缓存选 SwiftUI;要跨平台选 React Native。图片社区的瀑布流要点可参考[小红书瀑布流组件](/blogs/cn-app-fully-open-source-xiaohongshu-waterfall-component/)。

Keep reading