For循环结束后才会执行onAreaChange组件区域变化事件??

发布时间 2024-01-04 17:32:43作者: 鹿lu

一开始利用WaterFlow容器写了个瀑布流,无奈瀑布流的滚动条和页面Scroll滚动冲突,于是乎想自己是实现一个瀑布流效果

思路大致如下:

1,分成两列,(两个Column),不给固定高度,让子元素自行把父容器撑大

2,每次添加数据时,找到相比较当前的2个容器高度‘矮’的那一个,(Height小的),往里塞数据

3,每次添加5条数据,那就进行了5次比大小,每次都找到小的那一个,理想情况就是左边aClomun添加一条,右边bCloumn添加一条,如此反复进行5次

说干就干,先整两个并排的Column出来,分别绑定空数组arr1和arr2,arr1添加数据,则左边的Cloumn添加数据,反则右边添加,

利用onAreaChange组件区域变化事件,来找出他们变化后的高度,进行比较

大致逻辑如下:

每点击一次按钮,就进行一次判断大小,并在小的里添加一条数据

Button('+++++ 添加数据 +++++').onClick(()=>{

          // for(let i=0;i<5;i++){
            if(Number(this.aa)<Number(this.bb)){
              this.arr1.push(
                {
                  key:(this.arr1.length+1),
                  img: $r('app.media.ic_drive_1'),
                  title:"测试文字测试文字测试文字测试文字测试文字测试文字测试文字测试文字测试文字测试文字测试文字",
                  price:'39.9',
                  sold:'1万'
                }
              )
            }else {
              this.arr2.push(
                {
                  key:(this.arr2.length+1),
                  img: $r('app.media.ic_drive_2'),
                  title:"海狸先生黄鱼酥即食香酥小黄花鱼零食即食鱼仔小鱼干",
                  price:'39.9',
                  sold:'1万'
                }
              )
            // }
          }

        }).margin({top:80})

 

初始情况:(给左边a默认塞一条数据,让他俩初始就不一高,方便用于比较)

 

点击第一次效果:(左右a有数据,右边b没数据,a高度肯定大于b,所以往右边添加数据)

 

点击第二次效果:(因为右边还比左边的高度小,所以依然在右边添加数据,没毛病)

 

点击第三次效果:(这时右边的2条加起来高度比左边1条要高,所以第三次往左边添加)

 

以上看似已经实现想要的效果了,只需要每次添加添加N条数据即可(循环添加,每次添加前都会比较大小)

这时我们给他加个for循环,让他一次添加5条数据进来,(把上面代码的for循环注释 // 去掉即可)

但这时候问题就出现了,点击后,视图直接在右边加了5条,左边还是初始那1条,相当于每次比较大小,都是fasle(右边高度小)

 

然后得出问题,onAreaChange事件似乎只有在for循环全部走完后,才会更新视图并出发onAreaChange改变,之后试了async awite ,定时器异步来操作也是不行

有没有大佬告诉我,想要完整实现我这个Demo,在一次添加5条数据时,让他每次都正确判断当前column高度后再添加数据,应该怎么搞啊???

 

下面是完整代码:

interface imgItem{
  key:number
  img:Resource
  title:string
  price:string
  sold:string
}



@Entry
@Component
export default struct FlexContent{
  scroller: Scroller = new Scroller()

  // 定义两个变量用于存储他们当前的高度
  @State aa:number = 0
  @State bb:number = 0
  // 定义两个数组arr1和arr2,首先给arr1塞条数据,让aColumn初始就比b高,好用于比较
  @State arr1:Array<imgItem> = [
    {
      key:1,
      img: $r('app.media.ic_drive_1'),
      title:"测试文字测试文字测试文字测试文字测试文字测试文字测试文字测试文字测试文字测试文字测试文字",
      price:'198',
      sold:'3000'
    }
  ]
  @State arr2:Array<imgItem> = []


  // RecommendItem为自定义的图文组件,为了实现瀑布流效果,每条数据的图片高度不一样,文字多少也不一样
  @Builder RecommendItem(img:Resource,title,price,sold){
    Column(){
      Image(img).width('100%').objectFit(ImageFit.Contain).objectRepeat(ImageRepeat.NoRepeat).borderRadius(10)
      Text(title).width('100%').padding(10).fontWeight(FontWeight.Bold)
      // .maxLines(2).textOverflow({overflow:TextOverflow.Ellipsis})s
      Row(){
        Text('¥').fontSize(14).fontColor('red').fontWeight(FontWeight.Bold)
        Text(price).fontSize(18).fontColor('red').fontWeight(FontWeight.Bold)
      }.width('100%').padding({left:10}).justifyContent(FlexAlign.Start).alignItems(VerticalAlign.Bottom)
      Text('已售 '+sold + '+').fontSize(12).fontColor('#999').padding({top:10,left:10}).width('100%').textAlign(TextAlign.Start)
    }.backgroundColor('#fff').padding({bottom:10})
  }


  build(){

    Scroll(){
      Stack({alignContent: Alignment.Top}){
        Column(){
          Text(this.aa.toString()).fontSize(30).backgroundColor('red').fontColor('#fff')
          Text(this.bb.toString()).fontSize(30).backgroundColor('blue').fontColor('#fff')
        }

        Row(){
          Column(){
            ForEach(this.arr1,(item:imgItem)=>{
              this.RecommendItem(item.img,item.title,item.price,item.sold)
            },(item:imgItem)=>JSON.stringify(item))
          }.onAreaChange((oldValue: Area, newValue: Area)=>{

            this.aa = parseInt(newValue.height.toString())

          }).width('48%').border({width:1,color:'red'})
          Column(){
            ForEach(this.arr2,(item:imgItem)=>{
              this.RecommendItem(item.img,item.title,item.price,item.sold)
            },(item:imgItem)=>JSON.stringify(item))
          }.onAreaChange((oldValue: Area, newValue: Area)=>{

            this.bb = parseInt(newValue.height.toString())

          }).width('50%').border({width:1,color:'blue'})
        }.margin({top:100}).alignItems(VerticalAlign.Top)

        Button('+++++ 添加数据 +++++').onClick(()=>{

          for(let i=0;i<5;i++){
            if(Number(this.aa)<Number(this.bb)){
              this.arr1.push(
                {
                  key:(this.arr1.length+1),
                  img: $r('app.media.ic_drive_1'),
                  title:"测试文字测试文字测试文字测试文字测试文字测试文字测试文字测试文字测试文字测试文字测试文字",
                  price:'39.9',
                  sold:'1万'
                }
              )
            }else {
              this.arr2.push(
                {
                  key:(this.arr2.length+1),
                  img: $r('app.media.ic_drive_2'),
                  title:"海狸先生黄鱼酥即食香酥小黄花鱼零食即食鱼仔小鱼干",
                  price:'39.9',
                  sold:'1万'
                }
              )
            }
          }

        }).margin({top:80})
      }
    }
  }
}