在鸿蒙系统的应用开发过程中,我们经常需要处理图像显示和交互功能。本文将介绍两个重要的特性:如何解决 Image 组件的拖拽问题以及如何消除 ForEach 更新时的闪烁现象。
API 10 开始的 Image 拖拽问题
问题描述
在 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 版本是非常必要的。通过本文提供的解决方案,您可以更好地应对这些问题,从而提升应用的性能和用户体验。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。