ArkUI 组合手势:一个动作不够时,再考虑组合
【摘要】 今天我们用 GestureGroup 做两个轻量例子:顺序组合和并行组合。 组合手势不是越多越专业。它只是告诉系统:这些手势之间到底是先后关系,还是可以一起参与识别。能用一个手势解决,就不要硬组合。 参考文档: https://developer.huawei.com/consumer/cn/doc/harmonyos
ArkUI 组合手势:一个动作不够时,再考虑组合
今天我们用 GestureGroup 做两个轻量例子:顺序组合和并行组合。
组合手势不是越多越专业。它只是告诉系统:这些手势之间到底是先后关系,还是可以一起参与识别。能用一个手势解决,就不要硬组合。
参考文档:
- https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/arkts-interaction-development-guide-overview
Sequence:先后顺序很重要
GestureGroup(
GestureMode.Sequence,
LongPressGesture({ repeat: false, duration: 500 }),
PanGesture({ fingers: 1, distance: 5 })
)
这个例子要求先长按,再拖动。它适合“先激活,再移动”的场景,比如长按后移动一个卡片。
Parallel:两个手势都能参与
GestureGroup(
GestureMode.Parallel,
TapGesture({ count: 1 }),
PanGesture({ fingers: 1, distance: 5 })
)
并行组合适合点击和拖动都可能有效的区域。Demo 里点击会记录一次点击,拖动会记录位移。
先别急着处理冲突
这篇只讲组合思路,不讲父子组件争抢手势,也不讲滚动列表里的拖动冲突。那些问题更接近真实业务,但放在下一轮更合适。
你有没有写过“长按后才能拖动”的交互?如果写过,最容易卡的是手势顺序,还是拖动后的落点处理?
完整示例代码
文件位置:entry/src/main/ets/pages/arkUI/interaction/ArkUICombinedGestureDemo.ets
@Entry
@Component
struct ArkUICombinedGestureDemo {
@State sequenceText: string = '先长按,再拖动'
@State parallelText: string = '点击或拖动都可以试试'
@State sequenceX: number = 0
@State parallelX: number = 0
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)
}
@Builder
gestureBox(title: string, desc: string, color: string) {
Column({ space: 10 }) {
Text(title)
.fontSize(18)
.fontWeight(FontWeight.Bold)
.fontColor('#FFFFFF')
Text(desc)
.fontSize(13)
.fontColor('#E5E7EB')
.lineHeight(20)
}
.width('100%')
.padding(16)
.borderRadius(14)
.backgroundColor(color)
.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('组合手势不是越多越好。只有当一个动作需要前置条件,或者多个动作需要一起识别时,再把它们组合起来。')
.fontSize(14)
.fontColor('#6B7280')
.lineHeight(22)
}
.width('100%')
.alignItems(HorizontalAlign.Start)
this.sectionTitle('Sequence:先后顺序很重要', '这里要求先长按,再拖动。适合“先激活,再移动”的交互。')
Column() {
this.gestureBox('顺序组合', '长按卡片后继续拖动,松手后回到原位。', '#7C3AED')
Text(this.sequenceText)
.fontSize(13)
.fontColor('#FFFFFF')
.lineHeight(20)
.padding(10)
.borderRadius(10)
.backgroundColor('#00000033')
.width('100%')
}
.width('100%')
.translate({ x: this.sequenceX, y: 0 })
.gesture(
GestureGroup(
GestureMode.Sequence,
LongPressGesture({ repeat: false, duration: 500 })
.onAction(() => {
this.sequenceText = '长按已激活,现在可以拖动'
this.showTip('顺序手势已激活')
}),
PanGesture({ fingers: 1, distance: 5 })
.onActionUpdate((event: GestureEvent) => {
this.sequenceX = event.offsetX
this.sequenceText = `顺序拖动中:x ${Math.round(event.offsetX)}`
})
.onActionEnd(() => {
this.sequenceX = 0
this.sequenceText = '顺序组合结束:先长按再拖动'
this.showTip('顺序组合结束')
})
)
)
this.sectionTitle('Parallel:两个手势都能参与', '并行组合适合点击和拖动都可能有效的轻量场景。')
Column() {
this.gestureBox('并行组合', '点一下会记录点击,拖动会记录位移。', '#0F766E')
Text(this.parallelText)
.fontSize(13)
.fontColor('#FFFFFF')
.lineHeight(20)
.padding(10)
.borderRadius(10)
.backgroundColor('#00000033')
.width('100%')
}
.width('100%')
.translate({ x: this.parallelX, y: 0 })
.gesture(
GestureGroup(
GestureMode.Parallel,
TapGesture({ count: 1 })
.onAction(() => {
this.parallelText = '并行组合里触发了一次点击'
this.showTip('并行点击触发')
}),
PanGesture({ fingers: 1, distance: 5 })
.onActionUpdate((event: GestureEvent) => {
this.parallelX = event.offsetX
this.parallelText = `并行拖动中:x ${Math.round(event.offsetX)}`
})
.onActionEnd(() => {
this.parallelX = 0
this.parallelText = '并行组合里的拖动结束'
this.showTip('并行拖动结束')
})
)
)
this.sectionTitle('先克制一点', '这一页只讲组合思路。手势冲突、多层级事件和统一拖拽放到下一轮。')
Text('如果一个普通点击就能解决,就不要一上来组合三四个手势。组合越多,用户越难猜页面到底想让他做什么。')
.fontSize(14)
.fontColor('#4B5563')
.lineHeight(22)
.padding(16)
.borderRadius(14)
.backgroundColor('#FFFFFF')
.border({ width: 1, color: '#E5E7EB' })
.width('100%')
}
.width('100%')
.padding(24)
.alignItems(HorizontalAlign.Start)
}
.width('100%')
.height('100%')
.backgroundColor('#F8FAFC')
}
}
【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)