HarmonyOS鸿蒙Next中的waterflow

HarmonyOS鸿蒙Next中的waterflow waterflow 为啥只有增加 footer 的方法而没有 header ?

或者把 header 当做 item 加在 flowitem 里面,但是当多列的时候,flowitem 如何设置独占一行?

3 回复

目前暂时不支持设置WaterFlow头部组件,可以使用规避方案,外层用Scroller,内部嵌套WaterFlow。参考如下代码:

@Entry
@Component
struct Index {
  @State Number: String[] = ['0', '1', '2', '3', '4']
  @State minSize: number = 80
  @State maxSize: number = 180
  @State fontSize: number = 24
  @State colors: number[] = [0xFFC0CB, 0xDA70D6, 0x6B8E23, 0x6A5ACD, 0x00FFFF, 0x00FF7F]
  scroller: Scroller = new Scroller()
  dataSource: WaterFlowDataSource = new WaterFlowDataSource()
  private itemWidthArray: number[] = []
  private itemHeightArray: number[] = []

  // 计算flow item宽/高
  getSize() {
    let ret = Math.floor(Math.random() * this.maxSize)
    return (ret > this.minSize ? ret : this.minSize)
  }

  // 保存flow item宽/高
  getItemSizeArray() {
    for (let i = 0; i < 100; i++) {
      this.itemWidthArray.push(this.getSize())
      this.itemHeightArray.push(this.getSize())
    }
  }

  aboutToAppear() {
    this.getItemSizeArray()
  }

  @Builder
  itemFoot() {
    Column() {
      Text(`Footer`)
        .fontSize(10)
        .backgroundColor(Color.Red)
        .width(50)
        .height(50)
        .align(Alignment.Center)
        .margin({ top: 2 })
    }
  }

  build() {
    Column() {
      Scroll(this.scroller) {
        Column({space:10}) {
          Grid() {
            ForEach(this.Number, (day: string) => {
              ForEach(this.Number, (day: string) => {
                GridItem() {
                  Text(day)
                    .fontSize(16)
                    .backgroundColor(0xF9CF93)
                    .width('100%')
                    .height('100%')
                    .textAlign(TextAlign.Center)
                }
              })
            })
          }
          .columnsTemplate('1fr 1fr 1fr 1fr')
          .rowsTemplate('1fr 1fr')
          .columnsGap(10)
          .rowsGap(10)
          .width('90%')
          .backgroundColor(0xFAEEE0)
          .height(140)

          Swiper(new SwiperController()) {
            ForEach(["测试1", "测试2", "测试3", "测试4", "测试5", "测试6"], (item: string) => {
              Text(item).fontSize(20)
            })
          }
          .autoPlay(true)
          .vertical(false)
          .indicator(false)
          .loop(true)
          .width('90%')
          .backgroundColor(Color.Pink)
          .height(100)

          WaterFlow({scroller:this.scroller}) {
            LazyForEach(this.dataSource, (item: number) => {
              FlowItem() {
                Column() {
                  Text("N" + item).fontSize(12).height('16')
                  Image('res/waterFlowTest(' + item % 5 + ').jpg')
                    .objectFit(ImageFit.Fill)
                    .width('100%')
                    .layoutWeight(1)
                }
              }
              .onAppear(() => {
                // 即将触底时提前增加数据
                if (item + 20 == this.dataSource.totalCount()) {
                  for (let i = 0; i < 100; i++) {
                    this.dataSource.addLastItem()
                  }
                }
              })
              .width('100%')
              .height(this.itemHeightArray[item % 100])
              .backgroundColor(this.colors[item % 5])
            }, (item: string) => item)
          }
          .columnsTemplate("1fr 1fr")
          .columnsGap(10)
          .rowsGap(5)
          .backgroundColor(0xFAEEE0)
          .width('90%')
          .height('100%')
          .nestedScroll({
            scrollForward: NestedScrollMode.PARENT_FIRST,
            scrollBackward: NestedScrollMode.SELF_FIRST
          })
        }
        .width('100%')
        .backgroundColor(0xDCDCDC)
      }
      .backgroundColor(Color.Yellow)
      .height('100%')
      .edgeEffect(EdgeEffect.Spring)
    }
  }
}

export class WaterFlowDataSource implements IDataSource {
  private dataArray: number[] = []
  private listeners: DataChangeListener[] = []

  constructor() {
    for (let i = 0; i < 100; i++) {
      this.dataArray.push(i)
    }
  }

  // 获取索引对应的数据
  public getData(index: number): number {
    return this.dataArray[index]
  }

  // 通知控制器数据重新加载
  notifyDataReload(): void {
    this.listeners.forEach(listener => {
      listener.onDataReloaded()
    })
  }

  // 通知控制器数据增加
  notifyDataAdd(index: number): void {
    this.listeners.forEach(listener => {
      listener.onDataAdded(index)
    })
  }

  // 通知控制器数据变化
  notifyDataChange(index: number): void {
    this.listeners.forEach(listener => {
      listener.onDataChanged(index)
    })
  }

  // 通知控制器数据删除
  notifyDataDelete(index: number): void {
    this.listeners.forEach(listener => {
      listener.onDataDeleted(index)
    })
  }

  // 通知控制器数据位置变化
  notifyDataMove(from: number, to: number): void {
    this.listeners.forEach(listener => {
      listener.onDataMoved(from, to)
    })
  }

  // 获取数据总数
  public totalCount(): number {
    return this.dataArray.length
  }

  // 注册改变数据的控制器
  registerDataChangeListener(listener: DataChangeListener): void {
    if (this.listeners.indexOf(listener) < 0) {
      this.listeners.push(listener)
    }
  }

  // 注销改变数据的控制器
  unregisterDataChangeListener(listener: DataChangeListener): void {
    const pos = this.listeners.indexOf(listener)
    if (pos >= 0) {
      this.listeners.splice(pos, 1)
    }
  }

  // 增加数据
  public add1stItem(): void {
    this.dataArray.splice(0, 0, this.dataArray.length)
    this.notifyDataAdd(0)
  }

  // 在数据尾部增加一个元素
  public addLastItem(): void {
    this.dataArray.splice(this.dataArray.length, 0, this.dataArray.length)
    this.notifyDataAdd(this.dataArray.length - 1)
  }

  // 在指定索引位置增加一个元素
  public addItem(index: number): void {
    this.dataArray.splice(index, 0, this.dataArray.length)
    this.notifyDataAdd(index)
  }

  // 删除第一个元素
  public delete1stItem(): void {
    this.dataArray.splice(0, 1)
    this.notifyDataDelete(0)
  }

  // 删除第二个元素
  public delete2ndItem(): void {
    this.dataArray.splice(1, 1)
    this.notifyDataDelete(1)
  }

  // 删除最后一个元素
  public deleteLastItem(): void {
    this.dataArray.splice(-1, 1)
    this.notifyDataDelete(this.dataArray.length)
  }

  // 重新加载数据
  public reload(): void {
    this.dataArray.splice(1, 1)
    this.dataArray.splice(3, 2)
    this.notifyDataReload()
  }
}

更多关于HarmonyOS鸿蒙Next中的waterflow的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


HarmonyOS鸿蒙Next中的WaterFlow是一种用于布局的组件,主要用于实现瀑布流效果。它允许开发者以灵活的方式排列子组件,适用于展示图片、卡片等不规则内容。WaterFlow通过自适应布局,能够根据子组件的大小自动调整排列顺序,确保内容的自然展示。

在HarmonyOS中,WaterFlow组件通过WaterFlow类实现,开发者可以通过设置WaterFlow的属性来控制布局行为。例如,columnsTemplate属性用于定义列的宽度,rowsTemplate属性用于定义行的高度。此外,WaterFlow还支持通过layoutDirection属性设置布局方向,可以是水平或垂直。

WaterFlow组件与ForEach结合使用,可以动态生成子组件。每个子组件可以设置不同的宽度和高度,从而实现瀑布流的效果。WaterFlow还支持通过onScroll事件监听滚动行为,开发者可以根据需要处理滚动事件。

在HarmonyOS Next中,WaterFlow组件经过优化,提升了性能,特别是在处理大量子组件时,能够保持流畅的滚动体验。开发者可以通过HarmonyOS的API文档获取更详细的使用方法和示例代码。

在HarmonyOS(鸿蒙)中,WaterFlow是一种用于展示瀑布流布局的组件,适用于需要动态排列内容的场景,如图片、卡片等。它能够根据内容的大小自动调整布局,确保每个元素以最优的方式排列。开发者可以通过设置列数、间距等属性来定制布局效果,同时支持数据的动态加载和更新,提升用户体验。WaterFlow组件在鸿蒙Next中进一步优化了性能,提供了更流畅的滚动体验和更高的渲染效率。

回到顶部