HarmonyOS 鸿蒙Next List列表中的item宽高改变后造成了item重叠

发布于 1周前 作者 ionicwang 最后一次编辑是 5天前 来自 鸿蒙OS

目前通过List+LazyForEach的方式做了一个即时通讯的收发消息列表,其中用了ImageKnifeComponent来加载网络图片,当图片加载完成后修改List中item的宽高以保持图片原本的宽高比,但是改变宽高后会引起List中的item堆叠在一起,请问应该怎么解决?

目前在图像加载完成后调用this.dataSource.notifyDataChange(index)仍然无法解决问题。

ImageKnifeComponent({

  imageKnifeOption: {

    loadSrc: this.imageUrl,

    placeholderSrc: $r("app.media.im_pic_msg_holder"),

    errorholderSrc: $r("app.media.im_pic_msg_holder"),

    objectFit: ImageFit.Auto,

    border: { radius: 5 },

    onLoadListener: {

      onLoadSuccess: (data: PixelMap) => {

        data.getImageInfo().then((value: image.ImageInfo) => {

          if (value.size.width > value.size.height && value.size.width > 160) {

            let scale: number = 160 / value.size.width;

            this.imageWidth = 160;

            this.imageHeight = value.size.height * scale;

          } else if (value.size.width > value.size.height && value.size.width <= 160) {

            this.imageWidth = value.size.width;

            this.imageHeight = value.size.height;

          } else if (value.size.width < value.size.height && value.size.height > 130) {

            let scale: number = 130 / value.size.height;

            this.imageWidth = scale * value.size.width;

            this.imageHeight = 130;

          } else if (value.size.width < value.size.height && value.size.height <= 130) {

            this.imageWidth = value.size.width;

            this.imageHeight = value.size.height;

          }

          let eventData: emitter.EventData = {

            data: { 'index': this.index }

          }

          emitter.emit(EventUtils.getInstance().eventImgLoaded,eventData)

        })

      }

    }

  }

}).width(this.imageWidth).height(this.imageHeight)

更多关于HarmonyOS 鸿蒙Next List列表中的item宽高改变后造成了item重叠的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html

2 回复

可以在循环中添加 keyGenerator 。

参考:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V13/arkts-rendering-control-lazyforeach-V13#键值生成规则

import {ImageKnifeComponent , RequestOption,

  ImageKnifeData,

  ImageKnife,

  ImageKnifeGlobal} from '@ohos/imageknife'

import { BusinessError } from '@kit.BasicServicesKit';

import LazyDataSource from './LazyDataSource';

@Component

struct MessageViewItem {

  @ObjectLink item: MOAMessageModel;

  aboutToAppear(): void {

    let imageKnifeOption: RequestOption = new RequestOption();

    imageKnifeOption.load(this.item.imageUrl)

      .addListener({callback:(err:BusinessError|string, data:ImageKnifeData) => {

        if (data.isPixelMap()) {

          console.log("TEST== data: " + JSON.stringify(data))

          if (data.drawPixelMap) {

            let pixelmap = data.drawPixelMap.imagePixelMap;

            if (pixelmap) {

              console.log("TEST== pixelmap: " + JSON.stringify(pixelmap))

              pixelmap.getImageInfo((error, imageInfo) => {

                if(error) {

                  console.log("");

                } else {

                  let value = imageInfo

                  if (value.size.width > value.size.height && value.size.width > 160) {

                    let scale: number = 160 / value.size.width;

                    this.item.imageWidth = 160;

                    this.item.imageHeight = value.size.height * scale;

                  } else if (value.size.width > value.size.height && value.size.width <= 160) {

                    this.item.imageWidth = value.size.width;

                    this.item.imageHeight = value.size.height;

                  } else if (value.size.width < value.size.height && value.size.height > 160) {

                    let scale: number = 160 / value.size.height;

                    this.item.imageWidth = scale * value.size.width;

                    this.item.imageHeight = 160;

                  } else if (value.size.width < value.size.height && value.size.height <= 160) {

                    this.item.imageWidth = value.size.width;

                    this.item.imageHeight = value.size.height;

                  }

                  this.item.imgResized = true;

                }

              })

            }

          }

        }

        return false;

      }})

    let imageKnife:ImageKnife|undefined = ImageKnifeGlobal.getInstance().getImageKnife();

    if(imageKnife != undefined){

      imageKnife.call(imageKnifeOption)

    }

  }

  build() {

    Column() {

      Text("测试")

        .fontSize(18)

        .backgroundColor(Color.Red)

      ImageKnifeComponent({

        imageKnifeOption: {

          loadSrc: this.item.imageUrl,

        }

      }).width(this.item.imageWidth).height(this.item.imageHeight)

        .backgroundColor(Color.Red)

    }

    .margin({

      top:20

    })

  }

}


@Observed

export class MOAMessageModel{

  imageHeight: number = 160;

  imageWidth: number = 160;

  imageUrl: string = "";

  imgResized: boolean = false;

  constructor(imageHeight_:number,imageWidth_:number,imageUrl_:string,imgResized_:boolean) {

    this.imageHeight = imageHeight_

    this.imageWidth = imageWidth_

    this.imageUrl = imageUrl_

    this.imgResized = imgResized_

  }

}

@Entry

@Component

struct Index {

  private dataSource: LazyDataSource<MOAMessageModel> = new LazyDataSource();

  aboutToAppear() {

    for (let i = 0; i <= 20; i++) {

      this.dataSource.pushData( new MOAMessageModel(15,15,"xxx",false))

    }

  }

  build() {

    Column(){

      //聊天消息列表
      List() {
        LazyForEach(this.dataSource, (item: MOAMessageModel, index: number) => {
          ListItem() {
            MessageViewItem({
              item: item,
            })
          }
        }, (item: MOAMessageModel, index: number) => (item.imageWidth.toString() + item.imageHeight.toString() + index.toString()))
      }
      .edgeEffect(EdgeEffect.None)
      .layoutWeight(1)
      .padding({ bottom: 10 })

    }

  }

}
import { ObservedArray } from './ObservedArray';

class BasicDataSource <T> implements IDataSource {

  private listeners: DataChangeListener[] = [];

  public totalCount(): number {

    return 0;

  }

  public getData(index: number): T | undefined {

    return undefined;

  }

  // 该方法为框架侧调用,为LazyForEach组件向其数据源处添加listener监听

  registerDataChangeListener(listener: DataChangeListener): void {

    if (this.listeners.indexOf(listener) < 0) {

      this.listeners.push(listener);

    }

  }

  // 该方法为框架侧调用,为LazyForEach组件向其数据源处添加listener监听

  unregisterDataChangeListener(listener: DataChangeListener): void {

    const pos = this.listeners.indexOf(listener);

    if (pos >= 0) {

      this.listeners.splice(pos, 1);

    }

  }

  // 通知LazyForEach组件需要重载所有子组件

  notifyDataReload(): void {

    this.listeners.forEach(listener => {

      listener.onDataReloaded();

    })

  }

  // 通知LazyForEach组件需要在index对应索引处添加子组件

  notifyDataAdd(index: number): void {

    this.listeners.forEach(listener => {

      listener.onDataAdd(index);

    })

  }

  // 通知LazyForEach组件在index对应索引处数据有变化,需要重建该子组件

  notifyDataChange(index: number): void {

    this.listeners.forEach(listener => {

      listener.onDataChange(index);

    })

  }

  // 通知LazyForEach组件需要在index对应索引处删除该子组件

  notifyDataDelete(index: number): void {

    this.listeners.forEach(listener => {

      listener.onDataDelete(index);

    })

  }

  // 通知LazyForEach组件将from索引和to索引处的子组件进行交换

  notifyDataMove(from: number, to: number): void {

    this.listeners.forEach(listener => {

      listener.onDataMove(from, to);

    })

  }

}

@Observed

export default class LazyDataSource<T> extends BasicDataSource<T> {

  dataArray: T[] = [];

  public totalCount(): number {

    return this.dataArray.length;

  }

  public getData(index: number): T {

    return this.dataArray[index];

  }

  public addData(index: number, data: T): void {

    this.dataArray.splice(index, 0, data);

    this.notifyDataAdd(index);

  }

  public pushData(data: T): void {

    this.dataArray.push(data);

    this.notifyDataAdd(this.dataArray.length - 1);

  }

  public pushArrayData(newData: ObservedArray<T>): void {

    this.clear();

    this.dataArray.push(...newData);

    this.notifyDataReload();

  }

  public appendArrayData(addData: ObservedArray<T>): void {

    this.dataArray.push(...addData);

    this.notifyDataReload()

  }

  public deleteData(index: number): void {

    this.dataArray.splice(index, 1);

    this.notifyDataDelete(index);

  }

  public getDataList(): ObservedArray<T> {

    return this.dataArray;

  }

  public clear(): void {

    this.dataArray.splice(0, this.dataArray?.length)

  }

  public isEmpty(): boolean {

    return this.dataArray.length === 0;

  }

}
@Observed

export class ObservedArray<T> extends Array<T> {

  constructor(args?: T[]) {

    if (args instanceof Array) {

      super(...args);

    } else {

      super();

    }

  }

}

更多关于HarmonyOS 鸿蒙Next List列表中的item宽高改变后造成了item重叠的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS鸿蒙系统中,Next List列表的item宽高改变后造成重叠的问题,通常是由于布局管理未正确响应尺寸变化所导致的。以下是可能的原因及直接解决方法:

  1. 布局容器属性:检查item的布局容器(如DirectionalLayout, GridLayout等)是否设置了正确的对齐和填充属性。确保在调整item尺寸时,容器能够自动调整以容纳新的尺寸。

  2. Item的Margin和Padding:确认item的内外边距(margin和padding)设置是否合理,避免由于边距重叠导致的视觉问题。

  3. 布局约束:使用布局约束(如constraint layout)时,确保所有约束条件正确无误,并且能够在item尺寸变化时保持预期的布局效果。

  4. 动画与过渡效果:如果item的尺寸变化伴随动画或过渡效果,检查这些效果是否可能干扰了布局的重绘过程。

  5. 组件刷新:在动态修改item尺寸后,确保调用了适当的刷新或重绘方法,如invalidate()或requestLayout(),以通知系统重新计算布局。

如果问题依旧没法解决请联系官网客服,官网地址是:https://www.itying.com/category-93-b0.html

回到顶部