在鸿蒙系统的应用开发过程中,我们经常需要处理图像显示和交互功能。本文将介绍两个重要的特性:如何解决 Image 组件的拖拽问题以及如何消除 ForEach 更新时的闪烁现象。

API 10 开始的 Image 拖拽问题

问题描述

image.png

在 API 10 及更高版本中,Image 组件默认具有拖拽效果,这可能导致长按事件失效。当尝试为 Image 添加长按监听时,可能会遇到问题。

解决方案

为了解决这个问题,我们需要禁用 Image 组件的默认拖拽行为。可以在 Image 组件上添加 .draggable(false) 属性来关闭此功能。

示例代码

@Entry
@Component
struct Page55 {
  build() {
    Column() {
      Column() {
        Image('https://img0.baidu.com/it/u=2947691987,1330241285&fm=253&fmt=auto&app=138&f=JPEG?w=400&h=400')
          .width('72lpx')
          .height('72lpx')
          .draggable(false)//关闭默认图片拖拽后,长按监听就好了。
        Text('文字描述').fontColor(Color.Red).fontSize('20lpx')
      }
      .gesture(
        LongPressGesture({ repeat: false })// 由于repeat设置为true,长按动作存在时会连续触发,触发间隔为duration(默认值500ms)
          .onAction((event: GestureEvent) => {
            console.info('====event.repeat', event.repeat)
          })// 长按动作一结束触发
          .onActionEnd(() => {
            console.info('====event onActionEnd')
          })
      )
    }
    .width('100%')
    .height('100%')
  }
}

结论

在 API 10 及更高版本中,务必记得在 Image 组件上添加 .draggable(false),以便正确处理长按事件。

API 11 开始的同步加载优化

问题描述

【未添加.syncLoad(true)前效果】

【使用.syncLoad(true)后效果】

在 API 11 及更高版本中,使用 ForEach 进行动态渲染时,可能会出现图像闪烁的问题。

解决方案

为了解决这个问题,我们可以利用 Image 组件的 .syncLoad(true) 属性进行同步加载。这将确保在 ForEach 循环中更新图像时不会出现闪烁现象。

示例

注意,用到了网络图片加载,需要添加权限

src/main/module.json5

{
  "module": {
    "requestPermissions": [
      {
        "name": "ohos.permission.INTERNET"
      }
    ],

代码

class textAndImageModel {
  icon?: Resource|string = $r('app.media.startIcon')
  id?: number = 0
  title?: string | undefined = ""
  url?: string | undefined = ""
  array?: textAndImageModel[] | undefined = []
}

class GridItemBean {
  icon?: Resource|string = $r('app.media.startIcon')
  id?: number = 0
  title?: string | undefined = ""
  url?: string | undefined = ""

  buttonListTop: textAndImageModel[] = []
  bottonListBottom: textAndImageModel[] = []
  expand: boolean = false;

  constructor(item: textAndImageModel) {
    //设置组标题等信息
    this.icon = item.icon
    this.id = item.id
    this.title = item.title
    this.url = item.url
    //设置组内的列表
    let count = item.array?.length
    count = count ? count : 0
    if (count <= 5) {
      for (let i = 0; i < count; i++) {
        if (item.array && item.array[i]) {
          this.buttonListTop.push(item.array[i])
        }
      }
    } else {
      for (let i = 0; i < 4; i++) {
        if (item.array && item.array[i]) {
          this.buttonListTop.push(item.array[i])
        }
      }
      //添加展示或收起
      let mButtonItem = new textAndImageModel()
      mButtonItem.title = `展开`
      this.buttonListTop.push(mButtonItem)

      for (let i = 4; i < count; i++) {
        if (item.array && item.array[i]) {
          this.bottonListBottom.push(item.array[i])
        }
      }
    }

  }

}

@Component
struct MyGridCol {
  @Prop logo: Resource|string = $r('app.media.app_icon')
  @Prop title: string = '更多'

  build() {
    Column() {
      Image(this.logo).width(30).height(30).syncLoad(true)
      Text(this.title)
    }.width('144lpx')
  }
}

@Entry
@Component
struct Page016 {
  //接口数据源
  activityTitle: textAndImageModel[] = [
    {
      icon: $r('app.media.app_icon'),
      id: 1,
      title: "哈哈哈哈",
      url: '',
      array: [
        {
          icon:"https://img0.baidu.com/it/u=3129379276,3231297819&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=500",
          id: 1,
          title: "哈哈哈哈",
          url: '',
          array: [],
        },
        {
          icon: "https://img0.baidu.com/it/u=3129379276,3231297819&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=500",
          id: 2,
          title: "哈哈哈哈哈",
          url: '',
          array: [],
        },
        {
          icon: $r('app.media.app_icon'),
          id: 3,
          title: "哈哈哈哈哈",
          url: '',
          array: [],
        },
        {
          icon: $r('app.media.app_icon'),
          id: 4,
          title: "哈哈哈哈哈",
          url: '',
          array: [],
        },
        {
          icon: "https://img1.baidu.com/it/u=2448491964,1913920781&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=500",
          id: 5,
          title: "哈哈哈哈哈",
          url: '',
          array: [],
        },
        {
          icon:"https://img0.baidu.com/it/u=3129379276,3231297819&fm=253&fmt=auto&app=120&f=JPEG?w=500&h=500",
          id: 6,
          title: "哈哈哈哈哈",
          url: '',
        },
      ]
    },
    {
      icon: $r('app.media.app_icon'),
      id: 2,
      title: "哈哈哈哈哈",
      url: '',
      array: [],
    },
    {
      icon: $r('app.media.app_icon'),
      id: 3,
      title: "培训会议",
      url: '',
      array: [],
    },
  ]
  @State array: Array<GridItemBean> = []

  aboutToAppear(): void {


    this.activityTitle.forEach((item: textAndImageModel, index: number) => {
      //添加到ui展示的数据组
      this.array.push(new GridItemBean(item))
    })
  }

  build() {
    Scroll() {
      Column({ space: 5 }) {
        ForEach(this.array, (item: GridItemBean, index: number) => {
          Column() {
            Text(`组信息:${item.title}`)
            //组内列表信息
            Row() {
              Flex({ direction: FlexDirection.Row, wrap: FlexWrap.Wrap }) {
                ForEach(item.buttonListTop, (item_2: textAndImageModel, index_2: number) => {
                  MyGridCol({
                    logo: item_2.icon,
                    title: item_2.title
                  })
                    .onClick(() => {
                      if (item_2.title == '展开') {
                        item_2.title = '收起'
                        item.expand = true
                        this.array.splice(index, 1, item)
                      } else if (item_2.title == '收起') {
                        item_2.title = '展开'
                        item.expand = false
                        this.array.splice(index, 1, item)
                      }
                    })
                })
                ForEach(item.bottonListBottom, (item_2: textAndImageModel, index_2: number) => {
                  MyGridCol({ logo: item_2.icon, title: item_2.title })
                    .visibility(item.expand ? Visibility.Visible : Visibility.None)
                })
              }.layoutWeight(1)
            }.width('100%').justifyContent(FlexAlign.Start).alignItems(VerticalAlign.Top)
          }.width('100%')
          .backgroundColor(Color.Orange)
        })
      }
    }
    .align(Alignment.Top)
    .width('100%')
    .height('100%')

  }
}

结论

在 API 11 及更高版本中,使用 .syncLoad(true) 属性可以有效改善 ForEach 动态渲染时的图像闪烁问题。

小结

随着鸿蒙系统的不断升级,开发者需要注意新特性的引入和旧问题的修复。在处理图像显示和交互时,及时调整代码以适应最新的 API 版本是非常必要的。通过本文提供的解决方案,您可以更好地应对这些问题,从而提升应用的性能和用户体验。


zhongcx
1 声望3 粉丝