瀑布流容器,由“行”和“列”分割的单元格所组成,通过容器自身的排列规则,将不同大小的“项目”自上而下,如瀑布般紧密布局。
说明:
该组件从API Version 9 开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。
子组件
包含FlowItem子组件。
说明:
WaterFlow子组件的visibility属性设置为None时不显示,但该子组件周围的columnsGap、rowsGap、margin仍会生效。
接口
WaterFlow(options?: WaterFlowOptions)
参数:
参数名 | 参数类型 | 必填 | 参数描述 |
---|---|---|---|
options | WaterFlowOptions | 是 | 瀑布流组件参数。 |
WaterFlowOptions对象说明
参数名 | 参数类型 | 必填 | 参数描述 |
---|---|---|---|
footer | CustomBuilder | 否 | 设置WaterFlow尾部组件。 |
scroller | Scroller | 否 | 可滚动组件的控制器,与可滚动组件绑定。 说明: 不允许和其他滚动类组件,如:List、Grid、Scroll等绑定同一个滚动控制对象。 |
属性
除支持通用属性外,还支持以下属性:
名称 | 参数类型 | 描述 |
---|---|---|
columnsTemplate | string | 设置当前瀑布流组件布局列的数量,不设置时默认1列。 例如, '1fr 1fr 2fr' 是将父组件分3列,将父组件允许的宽分为4等份,第一列占1份,第二列占1份,第三列占2份。 可使用columnsTemplate('repeat(auto-fill,track-size)')根据给定的列宽track-size自动计算列数,其中repeat、auto-fill为关键字,track-size为可设置的宽度,支持的单位包括px、vp、%或有效数字,默认单位为vp,使用方法参见示例2。 默认值:'1fr' |
rowsTemplate | string | 设置当前瀑布流组件布局行的数量,不设置时默认1行。 例如, '1fr 1fr 2fr'是将父组件分三行,将父组件允许的高分为4等份,第一行占1份,第二行占一份,第三行占2份。 可使用rowsTemplate('repeat(auto-fill,track-size)')根据给定的行高track-size自动计算行数,其中repeat、auto-fill为关键字,track-size为可设置的高度,支持的单位包括px、vp、%或有效数字,默认单位为vp。 默认值:'1fr' |
itemConstraintSize | ConstraintSizeOptions | 设置约束尺寸,子组件布局时,进行尺寸范围限制。 |
columnsGap | Length | 设置列与列的间距。 默认值:0 |
rowsGap | Length | 设置行与行的间距。 默认值:0 |
layoutDirection | FlexDirection | 设置布局的主轴方向。 默认值:FlexDirection.Column |
enableScrollInteraction10+ | boolean | 设置是否支持滚动手势,当设置为false时,无法通过手指或者鼠标滚动,但不影响控制器的滚动接口。 默认值:true |
nestedScroll10+ | NestedScrollOptions | 嵌套滚动选项。设置向前向后两个方向上的嵌套滚动模式,实现与父组件的滚动联动。 |
friction10+ | number | Resource | 设置摩擦系数,手动划动滚动区域时生效,只对惯性滚动过程有影响,对惯性滚动过程中的链式效果有间接影响。 默认值:非可穿戴设备为0.6,可穿戴设备为0.9 说明: 设置为小于等于0的值时,按默认值处理 |
cachedCount11+ | number | 设置预加载的FlowItem的数量,只在LazyForEach中生效。 默认值:1 说明: 设置该属性后会缓存cachedCount个FlowItem。 LazyForEach超出显示和缓存范围的FlowItem会被释放。 设置为小于0的值时,按默认值显示。 |
scrollBar11+ | BarState | 设置滚动条状态。 默认值:BarState.Off 说明: 滚动条位置和长度以已布局过的总高度和当前偏移为准,在瀑布流布局全部子节点之前随着滑动持续变化。 |
scrollBarWidth11+ | string | number | 设置滚动条的宽度,不支持百分比设置。 默认值:4 单位:vp 说明: 如果滚动条的宽度超过其高度,则滚动条的宽度会变为默认值。 |
scrollBarColor11+ | string | number | Color | 设置滚动条的颜色。 |
edgeEffect11+ | value:EdgeEffect, options?:EdgeEffectOptions11+ | 设置边缘滑动效果。 - value:设置瀑布流组件的边缘滑动效果,支持弹簧效果和阴影效果。 默认值:EdgeEffect.None - options:设置组件内容大小小于组件自身时,是否开启滑动效果。 默认值:false |
layoutDirection优先级高于rowsTemplate和columnsTemplate。根据layoutDirection设置情况,分为以下三种设置模式:
-
layoutDirection设置纵向布局(FlexDirection.Column 或 FlexDirection.ColumnReverse)
此时columnsTemplate有效(如果未设置,取默认值)。例如columnsTemplate设置为"1fr 1fr"、rowsTemplate设置为"1fr 1fr 1fr"时,瀑布流组件纵向布局,辅轴均分成横向2列。
-
layoutDirection设置横向布局(FlexDirection.Row 或 FlexDirection.RowReverse)
此时rowsTemplate有效(如果未设置,取默认值)。例如columnsTemplate设置为"1fr 1fr"、rowsTemplate设置为"1fr 1fr 1fr"时,瀑布流组件横向布局,辅轴均分成纵向3列。
-
layoutDirection未设置布局方向
布局方向为layoutDirection的默认值:FlexDirection.Column,此时columnsTemplate有效。例如columnsTemplate设置为"1fr 1fr"、rowsTemplate设置为"1fr 1fr 1fr"时,瀑布流组件纵向布局,辅轴均分成横向2列。
事件
除支持通用事件外,还支持以下事件:
名称 | 功能描述 |
---|---|
onReachStart(event: () => void) | 瀑布流组件到达起始位置时触发。 |
onReachEnd(event: () => void) | 瀑布流组件到底末尾位置时触发。 |
onScrollFrameBegin10+(event: (offset: number, state: ScrollState => { offsetRemain: number }) | 瀑布流开始滑动时触发,事件参数传入即将发生的滑动量,事件处理函数中可根据应用场景计算实际需要的滑动量并作为事件处理函数的返回值返回,瀑布流将按照返回值的实际滑动量进行滑动。 - offset:即将发生的滑动量,单位vp。 - state:当前滑动状态。 - offsetRemain:实际滑动量,单位vp。 触发该事件的条件:手指拖动WaterFlow、WaterFlow惯性划动时每帧开始时触发;WaterFlow超出边缘回弹、使用滚动控制器和拖动滚动条的滚动不会触发。 |
onScroll11+(event: (scrollOffset: number, scrollState: ScrollState) => void) | 瀑布流滑动时触发。 - scrollOffset: 每帧滚动的偏移量,瀑布流的内容向上滚动时偏移量为正,向下滚动时偏移量为负,单位vp。 - scrollState: 当前滑动状态。 |
onScrollIndex11+(event: (first: number, last: number) => void) | 当前瀑布流显示的起始位置/终止位置的子组件发生变化时触发。瀑布流初始化时会触发一次。 - first: 当前显示的WaterFlow起始位置的索引值。 - last: 当前显示的瀑布流终止位置的索引值。 瀑布流显示区域上第一个子组件/最后一个组件的索引值有变化就会触发。 |
onScrollStart11+(event: () => void) | 瀑布流滑动开始时触发。手指拖动瀑布流或瀑布流的滚动条触发的滑动开始时,会触发该事件。使用Scroller滑动控制器触发的带动画的滑动,动画开始时会触发该事件。 |
onScrollStop11+(event: () => void) | 瀑布流滑动停止时触发。手指拖动瀑布流或瀑布流的滚动条触发的滑动,手指离开屏幕并且滑动停止时会触发该事件;使用Scroller滑动控制器触发的带动画的滑动,动画停止会触发该事件。 |
示例
示例1
WaterFlow的基本使用。
// WaterFlowDataSource.ets// 实现IDataSource接口的对象,用于瀑布流组件加载数据
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.onDataAdd(index)})}// 通知控制器数据变化notifyDataChange(index: number): void {this.listeners.forEach(listener => {listener.onDataChange(index)})}// 通知控制器数据删除notifyDataDelete(index: number): void {this.listeners.forEach(listener => {listener.onDataDelete(index)})}// 通知控制器数据位置变化notifyDataMove(from: number, to: number): void {this.listeners.forEach(listener => {listener.onDataMove(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()}
}
// Index.ets
import { WaterFlowDataSource } from './WaterFlowDataSource'@Entry
@Component
struct WaterFlowDemo {@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[] = []// 计算FlowItem宽/高getSize() {let ret = Math.floor(Math.random() * this.maxSize)return (ret > this.minSize ? ret : this.minSize)}// 设置FlowItem的宽/高数组setItemSizeArray() {for (let i = 0; i < 100; i++) {this.itemWidthArray.push(this.getSize())this.itemHeightArray.push(this.getSize())}}aboutToAppear() {this.setItemSizeArray()}@BuilderitemFoot() {Column() {Text(`Footer`).fontSize(10).backgroundColor(Color.Red).width(50).height(50).align(Alignment.Center).margin({ top: 2 })}}build() {Column({ space: 2 }) {WaterFlow() {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('100%').height('100%')}}
}
示例2
auto-fill的使用。
//index.ets
import { WaterFlowDataSource } from './WaterFlowDataSource'@Entry
@Component
struct WaterFlowDemo {@State minSize: number = 80@State maxSize: number = 180@State colors: number[] = [0xFFC0CB, 0xDA70D6, 0x6B8E23, 0x6A5ACD, 0x00FFFF, 0x00FF7F]dataSource: WaterFlowDataSource = new WaterFlowDataSource()private itemWidthArray: number[] = []private itemHeightArray: number[] = []// 计算FlowItem宽/高getSize() {let ret = Math.floor(Math.random() * this.maxSize)return (ret > this.minSize ? ret : this.minSize)}// 设置FlowItem宽/高数组setItemSizeArray() {for (let i = 0; i < 100; i++) {this.itemWidthArray.push(this.getSize())this.itemHeightArray.push(this.getSize())}}aboutToAppear() {this.setItemSizeArray()}build() {Column({ space: 2 }) {WaterFlow() {LazyForEach(this.dataSource, (item: number) => {FlowItem() {Column() {Text("N" + item).fontSize(12).height('16')}}.width('100%').height(this.itemHeightArray[item % 100]).backgroundColor(this.colors[item % 5])}, (item: string) => item)}.columnsTemplate('repeat(auto-fill,80)').columnsGap(10).rowsGap(5).padding({left:5}).backgroundColor(0xFAEEE0).width('100%').height('100%')}}
}
最后,有很多小伙伴不知道学习哪些鸿蒙开发技术?不知道需要重点掌握哪些鸿蒙应用开发知识点?而且学习时频繁踩坑,最终浪费大量时间。所以有一份实用的鸿蒙(HarmonyOS NEXT)资料用来跟着学习是非常有必要的。
这份鸿蒙(HarmonyOS NEXT)资料包含了鸿蒙开发必掌握的核心知识要点,内容包含了(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、Harmony南向开发、鸿蒙项目实战等等)鸿蒙(HarmonyOS NEXT)技术知识点。
希望这一份鸿蒙学习资料能够给大家带来帮助,有需要的小伙伴自行领取,限时开源,先到先得~无套路领取!!
获取这份完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习资料
鸿蒙(HarmonyOS NEXT)最新学习路线
-
HarmonOS基础技能
- HarmonOS就业必备技能
- HarmonOS多媒体技术
- 鸿蒙NaPi组件进阶
- HarmonOS高级技能
- 初识HarmonOS内核
- 实战就业级设备开发
有了路线图,怎么能没有学习资料呢,小编也准备了一份联合鸿蒙官方发布笔记整理收纳的一套系统性的鸿蒙(OpenHarmony )学习手册(共计1236页)与鸿蒙(OpenHarmony )开发入门教学视频,内容包含:ArkTS、ArkUI、Web开发、应用模型、资源分类…等知识点。
获取以上完整版高清学习路线,请点击→纯血版全套鸿蒙HarmonyOS学习资料
《鸿蒙 (OpenHarmony)开发入门教学视频》
《鸿蒙生态应用开发V2.0白皮书》
《鸿蒙 (OpenHarmony)开发基础到实战手册》
OpenHarmony北向、南向开发环境搭建
《鸿蒙开发基础》
- ArkTS语言
- 安装DevEco Studio
- 运用你的第一个ArkTS应用
- ArkUI声明式UI开发
- .……
《鸿蒙开发进阶》
- Stage模型入门
- 网络管理
- 数据管理
- 电话服务
- 分布式应用开发
- 通知与窗口管理
- 多媒体技术
- 安全技能
- 任务管理
- WebGL
- 国际化开发
- 应用测试
- DFX面向未来设计
- 鸿蒙系统移植和裁剪定制
- ……
《鸿蒙进阶实战》
- ArkTS实践
- UIAbility应用
- 网络案例
- ……
获取以上完整鸿蒙HarmonyOS学习资料,请点击→纯血版全套鸿蒙HarmonyOS学习资料
总结
总的来说,华为鸿蒙不再兼容安卓,对中年程序员来说是一个挑战,也是一个机会。只有积极应对变化,不断学习和提升自己,他们才能在这个变革的时代中立于不败之地。