一、WaterFlow 组件概述

WaterFlow(瀑布流)是 ArkUI 提供的一个高性能容器组件,专门用于实现瀑布流布局效果。它在购物、资讯类应用中尤为常见,能够高效展示大小不一的图片和内容区块。

1.1 基本特性

WaterFlow 组件具有以下核心特点:

  • 动态布局:自动计算最优位置,使不同高度的项目紧密排列
  • 高性能:支持懒加载、组件复用等优化手段
  • 灵活布局:支持纵向和横向两种布局方向
  • 无限滚动:便捷实现触底加载更多数据的功能
  • 分组混合:支持不同分组使用不同列数的混合布局

1.2 核心优势

相比传统的 Grid 或 List 组件,WaterFlow 在以下方面表现更优:

  1. 不规则内容展示:完美适应高度不一的子项内容
  2. 视觉吸引力:错落有致的布局增强用户体验
  3. 内存优化:先进的回收机制降低内存消耗
  4. 开发便捷:内置复杂布局逻辑,开发者只需关注内容

二、WaterFlow 核心功能详解

2.1 基础布局方式

WaterFlow 支持两种基础布局模式:

 
// 纵向布局(默认) WaterFlow({ layoutMode: WaterFlowLayoutMode.ALWAYS_TOP_DOWN }) { // 子项 } .columnsTemplate('1fr 1fr 1fr') // 设置3列 // 横向布局 WaterFlow({ layoutMode: WaterFlowLayoutMode.ALWAYS_TOP_DOWN }) { // 子项 } .rowsTemplate('1fr 1fr') // 设置2行 .layoutDirection(FlexDirection.Row) 

布局规则

  • 纵向布局:项目从左到右排列,新项目放置在当前高度最小的列
  • 横向布局:项目从上到下排列,新项目放置在当前宽度最小的行

2.2 无限滚动实现

实现无限滚动需要结合 LazyForEach 和数据源管理:

 
@State
dataSource: WaterFlowDataSource = new WaterFlowDataSource(initialData)
build() {
  WaterFlow({ footer: this.loadingFooter() }) {
    LazyForEach(this.dataSource, (item: number) => {
      FlowItem() { // 内容项 
      }.onAppear(() => {
        // 触底预加载 
        if (item.index === this.dataSource.totalCount() - 5) {
          this.loadMoreData()
        }
      })
    })
  }.onReachEnd(() => {
    // 触底加载 
    this.loadMoreData()
  })
}

private loadMoreData() {
  // 模拟异步加载 
  setTimeout(() => {
    this.dataSource.addNewItems(10)
  }, 1000)
} 

2.3 分组混合布局

WaterFlow 支持通过 WaterFlowSections 实现分组布局:

 
@State
sections: WaterFlowSections = new WaterFlowSections()
aboutToAppear() {
  const headerSection: SectionOptions = {
    itemsCount: 1, crossCount: 1,
    // 单列
    margin: {
      top: 10,
      left: 10,
      right: 10,
      bottom: 10
    }
  }
  const contentSection: SectionOptions = {
    itemsCount: 20,
    crossCount: 2,
    // 双列 
    columnsGap: 5,
    rowsGap: 5
  }
  this.sections.splice(0, 0, [headerSection, contentSection])
}

build() {
  WaterFlow({ sections: this.sections }) {
    // 内容项 
  }
} 

三、性能优化策略

3.1 组件复用

使用 @Reusable 装饰器实现组件复用:

 
@Reusable @Component struct ReusableItem { @Prop item: ItemData aboutToReuse(params: Record<string, any>) { this.item = params.item } build() { // 组件布局 } } 

3.2 懒加载优化

结合 LazyForEach 和 NodeAdapter 实现高效懒加载:

 
// ArkTS 示例 WaterFlow() { LazyForEach(this.dataSource, (item) => { FlowItem() { ReusableItem({ item }) } }) } // NDK 示例 class FlowItemAdapter { private adapter: ArkUI_NodeAdapterHandle constructor() { this.adapter = OH_ArkUI_NodeAdapter_Create() OH_ArkUI_NodeAdapter_SetEventCallback(this.adapter, this.onAdapterEvent) } private onAdapterEvent(event: ArkUI_NodeAdapterEvent) { // 处理创建、复用、销毁逻辑 } } 

3.3 预加载机制

通过 Prefetcher 实现数据预取:

 
class MyPrefetcher implements IPrefetcher { private dataSource?: IDataSourcePrefetching setDataSource(dataSource: IDataSourcePrefetching): void { this.dataSource = dataSource } visibleAreaChanged(minVisible: number, maxVisible: number): void { this.dataSource?.prefetch(minVisible - 5, maxVisible + 5) } } // 使用 const prefetcher = new MyPrefetcher() WaterFlow() .prefetcher(prefetcher) 

四、高级功能探索

4.1 动态列数调整

 
@State columns: number = 2 build() { Column() { Button('切换列数') .onClick(() => { this.columns = this.columns === 2 ? 3 : 2 }) WaterFlow() { // 内容 } .columnsTemplate(`1fr `.repeat(this.columns)) } } 

4.2 嵌套滚动处理

 
WaterFlow() .nestedScroll({ scrollForward: NestedScrollMode.PARENT_FIRST, // 向前滚动父组件优先 scrollBackward: NestedScrollMode.SELF_FIRST // 向后滚动自身优先 }) 

4.3 自定义滚动条

 
WaterFlow() .scrollBar(BarState.On) .scrollBarWidth(10) .scrollBarColor(Color.Gray) 

五、实战案例分析

5.1 电商商品列表实现

 
@Entry
@Component
struct ShoppingPage {
  @State products: Product[] = []
  @State loading: boolean = false

  build() {
    Column() {
      WaterFlow({ footer: this.loading ? this.loadingIndicator() : null }) {
        LazyForEach(new ArrayDataSource(this.products), (product: Product) => {
          FlowItem() {
            ProductItem({ product })
          }
        })
      }.columnsTemplate('1fr 1fr').onReachEnd(() => this.loadMore())
    }
  }

  private loadMore() {
    if (this.loading) {
      return this.loading = true
    }
    fetchProducts().then(newProducts => {
      this.products.push(...newProducts)
      this.loading = false
    })
  }
} 

5.2 图片社交应用

 
@Entry
@Component
struct SocialGallery {
  @State posts: SocialPost[] = []
  @State currentIndex: number = 0

  build() {
    WaterFlow({ layoutMode: WaterFlowLayoutMode.SLIDING_WINDOW }) {
      LazyForEach(new ArrayDataSource(this.posts), (post: SocialPost) => {
        FlowItem() {
          PostCard({ post })
        }.onAppear(() => {
          // 预加载附近项 
          if (post.index - this.currentIndex < 5) {
            prefetchPost(post.id + 1)
          }
        })
      })
    }.onScrollIndex((first, last) => {
      this.currentIndex = first
    })
  }
} 

六、常见问题解决方案

6.1 白屏问题处理

问题现象:快速滑动时出现空白区域

解决方案

  1. 增加 prefetch 预加载范围
  2. 使用固定尺寸替代自适应高度
  3. 添加合适的占位组件
 
FlowItem() { Column() { // 图片加载前显示占位 if (this.imageLoaded) { Image(this.imageUrl) } else { Placeholder() .onAppear(() => loadImage()) } } } .width('100%') .height(200) // 固定高度 

6.2 内存优化

优化策略

  1. 限制缓存数量
  2. 及时释放资源
  3. 使用低分辨率预览图
 
WaterFlow() .cachedCount(10) // 限制缓存数量 

6.3 性能监测

 
WaterFlow() .onScrollIndex((first, last) => { Logger.info(`Visible items: ${first} - ${last}`) PerformanceTrace.trace('WaterFlow scrolling') }) 

----

以上

Logo

更多推荐