介绍
- 当下的大多数产品中瀑布流是一种非常常见的组件,本文将介绍关于waterflow的图片浏览
功能介绍
- 使用瀑布流实现图片展示
- 如下图是利用瀑布流做的一个唐朝诡事录人物简介
代码结构
├──entry/src/main/ets // 代码区
│ ├──common
│ ├──entryability
│ │ └──EntryAbility.ets // 程序入口类
│ ├──pages
│ │ └──Index.ets // 主界面
│ ├──view
│ │ ├──FlowItemComponent.ets // 瀑布流Item组件类
│ │ └──WaterFlowComponent.ets // 自定义组件类
│ └──viewmodel
│ ├──HomeViewModel.ets // 瀑布流数据类
│ ├──ProductItem.ets // 数据结构类
│ └──WaterFlowDataSource.ets // 瀑布流数据类
页面布局
@Entry
@Component
struct Index {
build() {
Column() {
WaterFlowComponent();
}
}
}
整体结构非常简单就只有一个瀑布流组件。
由于数据量较多,所以我们这里采用懒加载(LazyForEach)方式。
使用LazyForEach进行数据懒加载,要求数据源实现IDataSource接口及成员方法。使用常量waterFlowData完成瀑布流数据项配置,包含图片资源。
数据结构类
首先根据自己的需求定义一个人物信息类和和其接口
export interface IProductItem{
image_url:Resource;
name:string;
introduce:string;
}
export default class ProductItem implements IProductItem{
image_url: Resource; //人物图片
name: string;//人物姓名
introduce: string;//人物简介
constructor(props:ProductItem) {
this.image_url = props.image_url;
this.name = props.name;
this.introduce = props.introduce;
}
}
瀑布流数据数组
export class WaterFlowDataSource implements IDataSource{
private dataArray:ProductItem[] = [];
private listeners:DataChangeListener[]=[];
//设置瀑布流数据数组
public setDataArray(productDataArray:ProductItem[]):void{
this.dataArray = productDataArray;
}
//数据的总数
public totalCount(): number {
return this.dataArray.length;
}
public getData(index: number): ProductItem {
return this.dataArray[index];
}
//注册数据改变的监听器
registerDataChangeListener(listener: DataChangeListener): void {
if(this.listeners.indexOf(listener)<0){
this.listeners.push(listener);
}
}
//注销数据改变的监听器
unregisterDataChangeListener(listener: DataChangeListener): void {
let pos =this.listeners.indexOf(listener);
if(pos>=0){
this.listeners.splice(pos,1);
}
}
}
瀑布流数据资源
资源图片均存放在resource中的media目录中,下面直接代码中直接引用即可
const waterFlowData:IProductItem[]=[
{
image_url:$r('app.media.suwuming'),
name:'苏无名',
introduce:'狄公弟子'
},
{
image_url:$r('app.media.lulingfeng'),
name:'卢凌风',
introduce:'前金吾卫中郎将'
},
{
image_url:$r('app.media.feijishi'),
name:'费鸡师',
introduce:'神医'
},
{
image_url:$r('app.media.xijun'),
name:'裴喜君',
introduce:'擅长丹青'
},
{
image_url:$r('app.media.yingtao'),
name:'樱桃',
introduce:'侠女'
},
{
image_url:$r('app.media.taizi'),
name:'太子李隆基',
introduce:'唐玄宗'
},
{
image_url:$r('app.media.gongzhu'),
name:'公主',
introduce:'太平公主'
},
{
image_url:$r('app.media.qinxiaobai'),
name:'秦孝白',
introduce:'大唐第一画师'
},
{
image_url:$r('app.media.liushiba'),
name:'刘十八',
introduce:'甘棠驿'
},
{
image_url:$r('app.media.dugu'),
name:'独孤遐叔',
introduce:'爱做梦'
},
{
image_url:$r('app.media.qinghong'),
name:'轻红',
introduce:'独孤遐叔之妻'
},
]
export {waterFlowData};
瀑布流组件中子组件的构建
@Component
export default struct FlowItemComponent {
item: ProductItem = waterFlowData[0];
build() {
//这个子组件采用Column布局
Column(){
//图片的相关设置
Image(this.item?.image_url)
.width(400)
.height(100)
.objectFit(ImageFit.Contain)
.margin({
top:12,
bottom:12
})
//姓名的相关设置
Text(this.item?.name)
.fontSize(24)
.fontWeight(FontWeight.Bold)
.alignSelf(ItemAlign.Start)
.fontColor(Color.Black)
//简介的相关设置
Text(this.item?.introduce)
.fontSize(24)
.fontWeight(FontWeight.Bold)
.alignSelf(ItemAlign.Start)
.fontColor(Color.Black)
}
.borderRadius(10)
.backgroundColor(Color.White)
.padding({
left:5,
right:5,
bottom:5
})
}
}
瀑布流效果的实现
瀑布流效果实现步骤如下:
- 在生命周期函数aboutToAppear()中初始化瀑布流数据。
- WaterFlow容器添加参数footer设置瀑布流滑动至尾部时展示的内容,提示已滑动到底部。
- LazyForEach()从数据源中按需迭代数据,在瀑布流容器子组件FlowItem内展示数据项。
- 使用瀑布流属性layoutDirection设置主轴方向为FlexDirection.Column列方向,columnsTemplate设置布局列数为两列,columnsGap列间距及rowsGaph行间距
@Component
export default struct WaterFlowComponent{
private datasource:WaterFlowDataSource = new WaterFlowDataSource();
aboutToAppear(): void {
//初始化瀑布流数据
this.datasource.setDataArray(waterFlowData);
}
build() {
WaterFlow({footer:():void => this.itemFoot()}){
LazyForEach(this.datasource,(item1:ProductItem)=>{
//瀑布流容器子组件
FlowItem(){
//展示数据项
FlowItemComponent({item:item1})
}
},(item:ProductItem,index:number)=>JSON.stringify(item)+index.toString())//将对象转换为字符串
}
//对子组件重新布局
.layoutWeight(1)
//布局的主轴方向为列方向
.layoutDirection(FlexDirection.Column)
//列布局设置为两列
.columnsTemplate('1fr 1fr')
//设置列间距
.columnsGap(1)
//设置行间距
.rowsGap(1)
}
//瀑布流尾部显示内容
@Builder
itemFoot() {
Column() {
Text('已经到底了')
.fontColor(Color.Gray)
.fontSize(15)
.width('100%')
.height(20)
.textAlign(TextAlign.Center)
}
}
}