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

在 API 10 及更高版本中,Image 组件默认具有拖拽效果,这可能导致长按事件失效。当尝试为 Image 添加长按监听时,可能会遇到问题。
解决方案
为了解决这个问题,我们需要禁用 Image 组件的默认拖拽行为。可以在 Image 组件上添加 .draggable(false) 属性来关闭此功能。
示例代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | @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 })
.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
代码
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) => {
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 版本是非常必要的。通过本文提供的解决方案,您可以更好地应对这些问题,从而提升应用的性能和用户体验。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了