ArkUI 多层级手势:父子组件别互相抢动作
【摘要】 今天我们看父容器和子组件都绑定手势时,响应边界怎么判断。 新手写手势很容易把动作绑得到处都是:父容器一个 TapGesture,子卡片也一个 TapGesture。页面能跑,但一旦用户点到重叠区域,你就会开始怀疑到底谁该响应。 参考文档: https://developer.huawei.com/consumer/cn
ArkUI 多层级手势:父子组件别互相抢动作
今天我们看父容器和子组件都绑定手势时,响应边界怎么判断。
新手写手势很容易把动作绑得到处都是:父容器一个 TapGesture,子卡片也一个 TapGesture。页面能跑,但一旦用户点到重叠区域,你就会开始怀疑到底谁该响应。
参考文档:
- https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-interaction-development-guide-overview
父容器也能绑定手势
.gesture(
TapGesture({ count: 1 })
.onAction(() => {
this.parentText = '父容器响应'
}),
GestureMask.Normal
)
GestureMask.Normal 是普通识别方式。一般页面先从它开始,不要一上来就强行抢内部手势。
IgnoreInternal 会改变响应优先级
this.useIgnoreInternal ? GestureMask.IgnoreInternal : GestureMask.Normal
这个 Demo 用一个开关切换父容器的 GestureMask。打开后,父容器会更强势地处理手势。我们不是要鼓励你到处用它,而是让你知道:父子组件都有手势时,优先级是可以被显式影响的。
你写列表卡片时,有没有遇到过“点按钮却触发整张卡片点击”的情况?这种问题就适合先从绑定层级查起。
完整示例代码
文件位置:entry/src/main/ets/pages/arkUI/interaction/ArkUIMultiLevelGestureDemo.ets
@Entry
@Component
struct ArkUIMultiLevelGestureDemo {
@State useIgnoreInternal: boolean = false
@State parentText: string = '点击外层浅蓝区域,父容器会响应'
@State childText: string = '点击内层白色卡片,子组件会响应'
private showTip(message: string): void {
this.getUIContext().getPromptAction().showToast({
message: message,
duration: 1200,
bottom: 120
})
}
@Builder
sectionTitle(title: string, desc: string) {
Column({ space: 6 }) {
Text(title)
.fontSize(19)
.fontWeight(FontWeight.Bold)
.fontColor('#111827')
Text(desc)
.fontSize(13)
.fontColor('#6B7280')
.lineHeight(20)
}
.width('100%')
.alignItems(HorizontalAlign.Start)
}
build() {
Scroll() {
Column({ space: 22 }) {
Column({ space: 8 }) {
Text('ArkUI 多层级手势')
.fontSize(28)
.fontWeight(FontWeight.Bold)
.fontColor('#111827')
Text('父子组件别互相抢动作')
.fontSize(16)
.fontColor('#4B5563')
Text('多层级手势先看清楚一件事:手势到底绑在父容器,还是绑在子组件。这里用 GestureMask.Normal 和 IgnoreInternal 做最小对照。')
.fontSize(14)
.fontColor('#6B7280')
.lineHeight(22)
}
.width('100%')
.alignItems(HorizontalAlign.Start)
this.sectionTitle('切换父容器的 GestureMask', 'Normal 会按正常规则识别;IgnoreInternal 会让父容器忽略内部手势,优先识别自己的手势。')
Toggle({ type: ToggleType.Switch, isOn: this.useIgnoreInternal })
.onChange((isOn: boolean) => {
this.useIgnoreInternal = isOn
this.parentText = isOn ? '父容器当前使用 GestureMask.IgnoreInternal' : '父容器当前使用 GestureMask.Normal'
this.showTip(isOn ? '父容器优先识别' : '恢复普通识别')
})
Column({ space: 14 }) {
Text(this.useIgnoreInternal ? '父容器:IgnoreInternal' : '父容器:Normal')
.fontSize(18)
.fontWeight(FontWeight.Bold)
.fontColor('#0F172A')
Text('点外层区域或内层卡片,观察下面两行反馈。')
.fontSize(13)
.fontColor('#475569')
Column({ space: 10 }) {
Text('子组件卡片')
.fontSize(18)
.fontWeight(FontWeight.Bold)
.fontColor('#111827')
Text('这里也绑定了 TapGesture')
.fontSize(13)
.fontColor('#64748B')
}
.width('100%')
.padding(18)
.borderRadius(16)
.backgroundColor('#FFFFFF')
.border({ width: 1, color: '#CBD5E1' })
.gesture(
TapGesture({ count: 1 })
.onAction(() => {
this.childText = '子组件响应:内层卡片 TapGesture 被触发'
this.showTip('子组件响应')
})
)
}
.width('100%')
.padding(18)
.borderRadius(18)
.backgroundColor('#DBEAFE')
.border({ width: 1, color: '#93C5FD' })
.gesture(
TapGesture({ count: 1 })
.onAction(() => {
this.parentText = this.useIgnoreInternal ? '父容器响应:IgnoreInternal 模式下优先识别' : '父容器响应:外层区域被点击'
this.showTip('父容器响应')
}),
this.useIgnoreInternal ? GestureMask.IgnoreInternal : GestureMask.Normal
)
Column({ space: 8 }) {
Text(this.parentText)
.fontSize(14)
.fontColor('#111827')
.lineHeight(22)
Text(this.childText)
.fontSize(14)
.fontColor('#111827')
.lineHeight(22)
}
.width('100%')
.padding(16)
.borderRadius(14)
.backgroundColor('#FFFFFF')
.border({ width: 1, color: '#E5E7EB' })
}
.width('100%')
.padding(24)
.alignItems(HorizontalAlign.Start)
}
.width('100%')
.height('100%')
.backgroundColor('#F8FAFC')
}
}
【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)