harmony 鸿蒙手势拦截增强
手势拦截增强
为组件提供手势拦截能力。开发者可根据需要,将系统内置手势和比其优先级高的手势做并行化处理,并可以动态控制手势事件的触发。
说明:
从API Version 12开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。
shouldBuiltInRecognizerParallelWith
shouldBuiltInRecognizerParallelWith(callback: ShouldBuiltInRecognizerParallelWithCallback): T
提供系统内置手势与响应链上其他组件的手势设置并行关系的回调事件。此接口对应的capi接口为setInnerGestureParallelTo。
原子化服务API: 从API version 12开始,该接口支持在原子化服务中使用。
系统能力: SystemCapability.ArkUI.ArkUI.Full
参数: |参数名 |参数类型 |必填|参数描述 | |———-|————————–|——-|—————————–| |callback |ShouldBuiltInRecognizerParallelWithCallback|是 | 提供系统内置手势与响应链上其他组件的手势设置并行关系的回调事件,当该组件进行触摸碰撞测试时,会触发用户定义的回调来形成手势并行关系。|
返回值:
类型 | 说明 |
---|---|
T | 返回当前组件。 |
ShouldBuiltInRecognizerParallelWithCallback
type ShouldBuiltInRecognizerParallelWithCallback = (current: GestureRecognizer, others: Array<GestureRecognizer>) => GestureRecognizer
提供系统内置手势与响应链上其他组件的手势设置并行关系的回调事件类型。
原子化服务API: 从API version 12开始,该接口支持在原子化服务中使用。
系统能力: SystemCapability.ArkUI.ArkUI.Full
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
current | GestureRecognizer | 是 | 当前组件的系统内置手势识别器,当前版本只提供内置的PAN_GESTURE类型的手势识别器。 |
others | Array<GestureRecognizer> | 是 | 响应链上更高优先级的其他组件相同类别的手势识别器。 |
返回值:
类型 | 说明 |
---|---|
GestureRecognizer | 与current识别器绑定并行关系的某个手势识别器。 |
TouchRecognizer20+
触摸识别器对象。
原子化服务API: 从API version 20开始,该接口支持在原子化服务中使用。
系统能力: SystemCapability.ArkUI.ArkUI.Full
getEventTargetInfo20+
getEventTargetInfo(): EventTargetInfo
返回组件的事件目标信息。
原子化服务API: 从API version 20开始,该接口支持在原子化服务中使用。
系统能力: SystemCapability.ArkUI.ArkUI.Full
返回值:
类型 | 说明 |
---|---|
EventTargetInfo | 组件的事件目标信息。 |
cancelTouch20+
cancelTouch(): void
向识别器发送触摸取消事件。
原子化服务API: 从API version 20开始,该接口支持在原子化服务中使用。
系统能力: SystemCapability.ArkUI.ArkUI.Full
GestureRecognizer
手势识别器对象。
getTag
getTag(): string
返回当前手势识别器的tag。
原子化服务API: 从API version 12开始,该接口支持在原子化服务中使用。
系统能力: SystemCapability.ArkUI.ArkUI.Full
返回值:
类型 | 说明 |
---|---|
string | 当前手势识别器的tag。 |
getType
getType(): GestureControl.GestureType
返回当前手势识别器的类型。
原子化服务API: 从API version 12开始,该接口支持在原子化服务中使用。
系统能力: SystemCapability.ArkUI.ArkUI.Full
返回值:
类型 | 说明 |
---|---|
GestureControl.GestureType | 当前手势识别器的类型。 |
isBuiltIn
isBuiltIn(): boolean
返回当前手势识别器是否为系统内置手势。
原子化服务API: 从API version 12开始,该接口支持在原子化服务中使用。
系统能力: SystemCapability.ArkUI.ArkUI.Full
返回值:
类型 | 说明 |
---|---|
boolean | 当前手势识别器是否为系统内置手势。true表示手势识别器为系统内置手势,false表示非系统内置手势。 |
setEnabled
setEnabled(isEnabled: boolean): void
设置当前手势识别器的使能状态。
原子化服务API: 从API version 12开始,该接口支持在原子化服务中使用。
系统能力: SystemCapability.ArkUI.ArkUI.Full
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
isEnabled | boolean | 是 | 手势识别器的使能状态。true表示当前手势识别器能够回调应用事件,false表示当前手势识别器不回调应用事件。 |
isEnabled
isEnabled(): boolean
返回当前手势识别器的使能状态。
原子化服务API: 从API version 12开始,该接口支持在原子化服务中使用。
系统能力: SystemCapability.ArkUI.ArkUI.Full
返回值:
类型 | 说明 |
---|---|
boolean | 当前手势识别器的使能状态。true表示当前手势识别器能够回调应用事件,false表示当前手势识别器不回调应用事件。 |
getState
getState(): GestureRecognizerState
返回当前手势识别器的状态。
原子化服务API: 从API version 12开始,该接口支持在原子化服务中使用。
系统能力: SystemCapability.ArkUI.ArkUI.Full
返回值:
类型 | 说明 |
---|---|
GestureRecognizerState | 当前手势识别器的状态。 |
getEventTargetInfo
getEventTargetInfo(): EventTargetInfo
返回当前手势识别器对应组件的信息。
原子化服务API: 从API version 12开始,该接口支持在原子化服务中使用。
系统能力: SystemCapability.ArkUI.ArkUI.Full
返回值:
类型 | 说明 |
---|---|
EventTargetInfo | 当前手势识别器对应组件的信息。 |
isValid
isValid(): boolean;
返回当前手势识别器是否有效。
原子化服务API: 从API version 12开始,该接口支持在原子化服务中使用。
系统能力: SystemCapability.ArkUI.ArkUI.Full
返回值:
类型 | 说明 |
---|---|
boolean | 当前手势识别器是否有效。当该识别器绑定的组件被析构或者该识别器不在响应链上时返回false。 |
getFingerCount18+
getFingerCount(): number
返回预设手指识别数阈值。
原子化服务API: 从API version 18开始,该接口支持在原子化服务中使用。
系统能力: SystemCapability.ArkUI.ArkUI.Full
返回值:
类型 | 说明 |
---|---|
number | 预设手指识别数阈值。 取值范围:[1, 10], 整数。 |
isFingerCountLimit18+
isFingerCountLimit(): boolean
返回预设手势是否会检测触摸屏幕上手指识别数量。
原子化服务API: 从API version 18开始,该接口支持在原子化服务中使用。
系统能力: SystemCapability.ArkUI.ArkUI.Full
返回值:
类型 | 说明 |
---|---|
boolean | 预设手势是否会检测触摸屏幕上手指识别数量。当绑定手势事件且会检测触摸屏幕上手指的数量时,返回true。当绑定手势事件且不会检测触摸屏幕上手指的数量时,返回false。 |
preventBegin20+
preventBegin(): void
阻止手势识别器参与手势处理。
原子化服务API: 从API version 20开始,该接口支持在原子化服务中使用。
系统能力: SystemCapability.ArkUI.ArkUI.Full
GestureRecognizerState
定义手势识别器状态。
原子化服务API: 从API version 12开始,该接口支持在原子化服务中使用。
系统能力: SystemCapability.ArkUI.ArkUI.Full
名称 | 值 | 描述 |
---|---|---|
READY | 0 | 准备状态。 |
DETECTING | 1 | 检测状态。 |
PENDING | 2 | 等待状态。 |
BLOCKED | 3 | 阻塞状态。 |
SUCCESSFUL | 4 | 成功状态。 |
FAILED | 5 | 失败状态。 |
EventTargetInfo
手势识别器对应组件的信息。
getId
getId(): string
返回当前组件的组件标识。
原子化服务API: 从API version 12开始,该接口支持在原子化服务中使用。
系统能力: SystemCapability.ArkUI.ArkUI.Full
返回值:
类型 | 说明 |
---|---|
string | 当前组件的组件标识。 |
ScrollableTargetInfo
手势识别器对应的滚动类容器组件的信息,继承于EventTargetInfo。
isBegin
isBegin(): boolean
返回当前滚动类容器组件是否在顶部,如果为Swiper组件且在循环模式下返回false。
原子化服务API: 从API version 12开始,该接口支持在原子化服务中使用。
系统能力: SystemCapability.ArkUI.ArkUI.Full
返回值:
类型 | 说明 |
---|---|
boolean | 当前滚动类容器组件是否在顶部。true表示组件在顶部,false表示组件不在顶部。 |
isEnd
isEnd(): boolean
返回当前滚动类容器组件是否在底部,如果为Swiper组件且在循环模式下返回false。
原子化服务API: 从API version 12开始,该接口支持在原子化服务中使用。
系统能力: SystemCapability.ArkUI.ArkUI.Full
返回值:
类型 | 说明 |
---|---|
boolean | 当前滚动类容器组件是否在底部。true表示组件在底部,false表示组件不在底部。 |
PanRecognizer
拖动手势识别器对象,继承于GestureRecognizer。
getPanGestureOptions
getPanGestureOptions(): PanGestureOptions
返回当前拖动手势识别器的属性。
原子化服务API: 从API version 12开始,该接口支持在原子化服务中使用。
系统能力: SystemCapability.ArkUI.ArkUI.Full
返回值:
类型 | 说明 |
---|---|
PanGestureOptions | 当前拖动手势识别器的属性。 |
getDirection19+
getDirection(): PanDirection
返回当前拖动手势识别器的方向。
原子化服务API: 从API version 19开始,该接口支持在原子化服务中使用。
系统能力: SystemCapability.ArkUI.ArkUI.Full
返回值:
类型 | 说明 |
---|---|
PanDirection | 当前拖动手势识别器的方向。 |
getDistance19+
getDistance(): number
返回当前拖动手势识别器触发的最小滑动距离。
原子化服务API: 从API version 19开始,该接口支持在原子化服务中使用。
系统能力: SystemCapability.ArkUI.ArkUI.Full
返回值:
类型 | 说明 |
---|---|
number | 当前拖动手势识别器触发的最小滑动距离。 |
getDistanceMap19+
getDistanceMap(): Map<SourceTool, number>
返回不同输入源的拖动手势识别器触发的最小滑动距离。
原子化服务API: 从API version 19开始,该接口支持在原子化服务中使用。
系统能力: SystemCapability.ArkUI.ArkUI.Full
返回值:
类型 | 说明 |
---|---|
Map<SourceTool, number> | 不同输入源的拖动手势识别器触发的最小滑动距离。 |
TapRecognizer18+
点击手势识别器对象,继承于GestureRecognizer。
getTapCount18+
getTapCount(): number
返回预设点击手势识别器连续点击次数阈值。
原子化服务API: 从API version 18开始,该接口支持在原子化服务中使用。
系统能力: SystemCapability.ArkUI.ArkUI.Full
返回值:
类型 | 说明 |
---|---|
number | 预设点击手势识别器连续点击次数阈值。 取值范围:[0, +∞) |
LongPressRecognizer18+
长按手势识别器对象,继承于GestureRecognizer。
isRepeat18+
isRepeat(): boolean
返回预设长按手势识别器是否连续触发事件回调。
原子化服务API: 从API version 18开始,该接口支持在原子化服务中使用。
系统能力: SystemCapability.ArkUI.ArkUI.Full
返回值:
类型 | 说明 |
---|---|
boolean | 预设长按手势识别器是否连续触发事件回调。当绑定长按手势且不会连续触发回调时,返回false。当绑定长按手势且会连续触发回调时,返回true。 |
getDuration18+
getDuration(): number
返回预设长按手势识别器触发长按最短时间阈值。
原子化服务API: 从API version 18开始,该接口支持在原子化服务中使用。
系统能力: SystemCapability.ArkUI.ArkUI.Full
返回值:
类型 | 说明 |
---|---|
number | 返回预设长按手势识别器触发长按最短时间阈值,单位为ms。 取值范围:[0, +∞) |
SwipeRecognizer18+
滑动手势识别器对象,继承于GestureRecognizer。
getVelocityThreshold18+
getVelocityThreshold(): number
返回预设滑动手势识别器识别滑动最小速度阈值。
原子化服务API: 从API version 18开始,该接口支持在原子化服务中使用。
系统能力: SystemCapability.ArkUI.ArkUI.Full
返回值:
类型 | 说明 |
---|---|
number | 预设滑动手势识别器识别滑动最小速度阈值,单位为vp/s。 取值范围:[0, +∞) |
getDirection18+
getDirection(): SwipeDirection
返回预设滑动手势识别器触发滑动手势滑动方向。
原子化服务API: 从API version 18开始,该接口支持在原子化服务中使用。
系统能力: SystemCapability.ArkUI.ArkUI.Full
返回值:
类型 | 说明 |
---|---|
SwipeDirection | 预设滑动手势识别器触发滑动手势滑动方向。 |
PinchRecognizer18+
捏合手势识别器对象,继承于GestureRecognizer。
getDistance18+
getDistance(): number
返回预设捏合手势识别器最小识别距离阈值。
原子化服务API: 从API version 18开始,该接口支持在原子化服务中使用。
系统能力: SystemCapability.ArkUI.ArkUI.Full
返回值:
类型 | 说明 |
---|---|
number | 预设捏合手势识别器最小识别距离阈值,单位为vp。 取值范围:[0, +∞) |
RotationRecognizer18+
旋转手势识别器对象,继承于GestureRecognizer。
getAngle18+
getAngle(): number
返回预设旋转手势识别器触发旋转手势最小改变度数阈值。
原子化服务API: 从API version 18开始,该接口支持在原子化服务中使用。
系统能力: SystemCapability.ArkUI.ArkUI.Full
返回值:
类型 | 说明 |
---|---|
number | 预设旋转手势识别器触发旋转手势最小改变度数阈值,单位为deg。 取值范围:[0, +∞) 说明: 当输入的改变度数的值小于等于0或大于360时,会被转化为默认值,默认值为1。 |
onGestureRecognizerJudgeBegin13+
onGestureRecognizerJudgeBegin(callback: GestureRecognizerJudgeBeginCallback, exposeInnerGesture: boolean): T
给组件绑定自定义手势识别器判定回调。
新增exposeInnerGesture参数作为是否将回调暴露给ArkUI系统组合组件的内置组件的标识。当该标识置为true时,将回调暴露给ArkUI系统组合组件的内置组件。
对于不需要将回调暴露给ArkUI系统组合组件内置组件的场景,建议采用原有onGestureRecognizerJudgeBegin接口。若要求将回调暴露给ArkUI系统组合组件的内置组件,建议使用该接口并将exposeInnerGesture设置为true。
原子化服务API: 从API version 13开始,该接口支持在原子化服务中使用。
系统能力: SystemCapability.ArkUI.ArkUI.Full
参数:
|参数名 |参数类型 |必填|参数描述 |
|———-|————————–|——-|—————————–|
|callback |GestureRecognizerJudgeBeginCallback|是 | 给组件绑定自定义手势识别器判定回调,当绑定到该组件的手势被接受时,会触发用户定义的回调来获取结果。|
|exposeInnerGesture |boolean |是 |暴露内部手势标识。
默认值:false
说明:
如果是组合组件,此参数设置true,则会在current参数回调出组合组件内部的手势识别器。
当前仅支持Tabs,其他组件请不要设置此参数。
设置为false时,功能与原接口onGestureRecognizerJudgeBegin相同。|
onGestureRecognizerJudgeBegin
onGestureRecognizerJudgeBegin(callback: GestureRecognizerJudgeBeginCallback): T
给组件绑定自定义手势识别器判定回调。
原子化服务API: 从API version 12开始,该接口支持在原子化服务中使用。
系统能力: SystemCapability.ArkUI.ArkUI.Full
参数: |参数名 |参数类型 |必填|参数描述 | |———-|————————–|——-|—————————–| |callback |GestureRecognizerJudgeBeginCallback|是 | 给组件绑定自定义手势识别器判定回调,当绑定到该组件的手势被接受时,会触发用户定义的回调来获取结果。|
返回值:
类型 | 说明 |
---|---|
T | 返回当前组件。 |
GestureRecognizerJudgeBeginCallback
type GestureRecognizerJudgeBeginCallback = (event: BaseGestureEvent, current: GestureRecognizer, recognizers: Array<GestureRecognizer>, touchRecognizers?: Array<TouchRecognizer>) => GestureJudgeResult
自定义手势识别器判定回调类型。
系统能力: SystemCapability.ArkUI.ArkUI.Full
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
event | BaseGestureEvent | 是 | 当前基础手势事件信息。 原子化服务API: 从API version 12开始,该接口支持在原子化服务中使用。 |
current | GestureRecognizer | 是 | 当前即将要响应的识别器对象。 原子化服务API: 从API version 12开始,该接口支持在原子化服务中使用。 |
others | Array<GestureRecognizer> | 是 | 响应链上的其他手势识别器对象。 原子化服务API: 从API version 12开始,该接口支持在原子化服务中使用。 |
touchRecognizers20+ | Array<TouchRecognizer> | 否 | 响应链上的Touch识别器对象。 默认值为null,表示在当前手势绑定组件及其子孙组件没有可响应的Touch识别器。 原子化服务API: 从API version 20开始,该接口支持在原子化服务中使用。 |
返回值:
类型 | 说明 |
---|---|
GestureJudgeResult | 手势是否裁决成功的判定结果。 |
onTouchTestDone20+
onTouchTestDone(callback: TouchTestDoneCallback): T
提供在触摸测试结束后,指定手势识别器是否参与后续处理的能力。
原子化服务API: 从API version 20开始,该接口支持在原子化服务中使用。
系统能力: SystemCapability.ArkUI.ArkUI.Full
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
callback | TouchTestDoneCallback | 是 | 回调函数,用于指定手势识别器是否参与后续处理。在触摸测试结束后,开始识别用户手势之前,会触发该回调来动态指定手势识别器是否参与手势处理。 |
返回值:
类型 | 说明 |
---|---|
T | 返回当前组件。 |
TouchTestDoneCallback20+
type TouchTestDoneCallback = (event: BaseGestureEvent, recognizers: Array<GestureRecognizer>) => void
动态指定手势识别器是否参与手势处理的回调事件类型。
原子化服务API: 从API version 20开始,该接口支持在原子化服务中使用。
系统能力: SystemCapability.ArkUI.ArkUI.Full
参数:
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
event | BaseGestureEvent | 是 | 当前基础手势事件信息。 |
recognizers | Array<GestureRecognizer> | 是 | 触摸测试结束后,所有手势识别器对象。 |
示例
示例1(嵌套滚动)
该示例通过shouldBuiltInrecognizerParallelWith和onGestureRecognizerJudgeBegin实现了嵌套滚动的功能。内部组件优先响应滑动手势,当内部组件滑动至顶部或底部时,外部组件能够接替滑动。
// xxx.ets
@Entry
@Component
struct FatherControlChild {
scroller: Scroller = new Scroller();
scroller2: Scroller = new Scroller()
private arr: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
private childRecognizer: GestureRecognizer = new GestureRecognizer();
private currentRecognizer: GestureRecognizer = new GestureRecognizer();
private lastOffset: number = 0;
build() {
Stack({ alignContent: Alignment.TopStart }) {
Scroll(this.scroller) { // 外部滚动容器
Column() {
Text("Scroll Area")
.width('90%')
.height(150)
.backgroundColor(0xFFFFFF)
.borderRadius(15)
.fontSize(16)
.textAlign(TextAlign.Center)
.margin({ top: 10 })
Scroll(this.scroller2) { // 内部滚动容器
Column() {
Text("Scroll Area2")
.width('90%')
.height(150)
.backgroundColor(0xFFFFFF)
.borderRadius(15)
.fontSize(16)
.textAlign(TextAlign.Center)
.margin({ top: 10 })
Column() {
ForEach(this.arr, (item: number) => {
Text(item.toString())
.width('90%')
.height(150)
.backgroundColor(0xFFFFFF)
.borderRadius(15)
.fontSize(16)
.textAlign(TextAlign.Center)
.margin({ top: 10 })
}, (item: string) => item)
}.width('100%')
}
}
.id("inner")
.width('100%')
.height(800)
}.width('100%')
}
.id("outer")
.height(600)
.scrollable(ScrollDirection.Vertical) // 滚动方向纵向
.scrollBar(BarState.On) // 滚动条常驻显示
.scrollBarColor(Color.Gray) // 滚动条颜色
.scrollBarWidth(10) // 滚动条宽度
.edgeEffect(EdgeEffect.None)
.shouldBuiltInRecognizerParallelWith((current: GestureRecognizer, others: Array<GestureRecognizer>) => {
for (let i = 0; i < others.length; i++) {
let target = others[i].getEventTargetInfo();
if (target) {
if (target.getId() == "inner" && others[i].isBuiltIn() &&
others[i].getType() == GestureControl.GestureType.PAN_GESTURE) { // 找到将要组成并行手势的识别器
this.currentRecognizer = current; // 保存当前组件的识别器
this.childRecognizer = others[i]; // 保存将要组成并行手势的识别器
return others[i]; // 返回将要组成并行手势的识别器
}
}
}
return undefined;
})
.onGestureRecognizerJudgeBegin((event: BaseGestureEvent, current: GestureRecognizer,
others: Array<GestureRecognizer>) => { // 在识别器即将要成功时,根据当前组件状态,设置识别器使能状态
if (current) {
let target = current.getEventTargetInfo();
if (target) {
if (target.getId() == "outer" && current.isBuiltIn() &&
current.getType() == GestureControl.GestureType.PAN_GESTURE) {
if (others) {
for (let i = 0; i < others.length; i++) {
let target = others[i].getEventTargetInfo() as ScrollableTargetInfo;
if (target instanceof ScrollableTargetInfo && target.getId() == "inner") { // 找到响应链上对应并行的识别器
let panEvent = event as PanGestureEvent;
if (target.isEnd()) { // 根据当前组件状态以及移动方向动态控制识别器使能状态
if (panEvent && panEvent.offsetY < 0) {
this.childRecognizer.setEnabled(false)
this.currentRecognizer.setEnabled(true)
} else {
this.childRecognizer.setEnabled(true)
this.currentRecognizer.setEnabled(false)
}
} else if (target.isBegin()) {
if (panEvent.offsetY > 0) {
this.childRecognizer.setEnabled(false)
this.currentRecognizer.setEnabled(true)
} else {
this.childRecognizer.setEnabled(true)
this.currentRecognizer.setEnabled(false)
}
} else {
this.childRecognizer.setEnabled(true)
this.currentRecognizer.setEnabled(false)
}
}
}
}
}
}
}
return GestureJudgeResult.CONTINUE;
})
.parallelGesture( // 绑定一个Pan手势作为动态控制器
PanGesture()
.onActionUpdate((event: GestureEvent) => {
if (this.childRecognizer.getState() != GestureRecognizerState.SUCCESSFUL||
this.currentRecognizer.getState() != GestureRecognizerState.SUCCESSFUL) { // 如果识别器状态不是SUCCESSFUL,则不做控制
return;
}
let target = this.childRecognizer.getEventTargetInfo() as ScrollableTargetInfo;
let currentTarget = this.currentRecognizer.getEventTargetInfo() as ScrollableTargetInfo;
if (target instanceof ScrollableTargetInfo && currentTarget instanceof ScrollableTargetInfo) {
if (target.isEnd()) { // 在移动过程中实时根据当前组件状态,控制识别器的开闭状态
if ((event.offsetY - this.lastOffset) < 0) {
this.childRecognizer.setEnabled(false)
if (currentTarget.isEnd()) {
this.currentRecognizer.setEnabled(false)
} else {
this.currentRecognizer.setEnabled(true)
}
} else {
this.childRecognizer.setEnabled(true)
this.currentRecognizer.setEnabled(false)
}
} else if (target.isBegin()) {
if ((event.offsetY - this.lastOffset) > 0) {
this.childRecognizer.setEnabled(false)
if (currentTarget.isBegin()) {
this.currentRecognizer.setEnabled(false)
} else {
this.currentRecognizer.setEnabled(true)
}
} else {
this.childRecognizer.setEnabled(true)
this.currentRecognizer.setEnabled(false)
}
} else {
this.childRecognizer.setEnabled(true)
this.currentRecognizer.setEnabled(false)
}
}
this.lastOffset = event.offsetY
})
)
}.width('100%').height('100%').backgroundColor(0xDCDCDC)
}
}
示例2(嵌套场景下拦截内部容器手势)
本示例通过将参数exposeInnerGesture设置为true,实现了一级Tabs容器在嵌套二级Tabs的场景下,能够屏蔽二级Tabs内置Swiper的滑动手势,从而触发一级Tabs内置Swiper滑动手势的功能。 开发者自行定义变量来记录内层Tabs的索引值,通过该索引值判断当滑动达到内层Tabs的边界处时,触发回调返回屏蔽使外层Tabs产生滑动手势。
// xxx.ets
@Entry
@Component
struct Index {
@State currentIndex: number = 0;
@State selectedIndex: number = 0;
@State fontColor: string = '#182431';
@State selectedFontColor: string = '#007DFF';
innerSelectedIndex: number = 0; // 记录内层Tabs的索引
controller?: TabsController = new TabsController();
@Builder
tabBuilder(index: number, name: string) {
Column() {
Text(name)
.fontColor(this.selectedIndex === index ? this.selectedFontColor : this.fontColor)
.fontSize(16)
.fontWeight(this.selectedIndex === index ? 500 : 400)
.lineHeight(22)
.margin({ top: 17, bottom: 7 })
Divider()
.strokeWidth(2)
.color('#007DFF')
.opacity(this.selectedIndex === index ? 1 : 0)
}.width('100%')
}
build() {
Column() {
Tabs({ barPosition: BarPosition.Start, index: this.currentIndex, controller: this.controller }) {
TabContent() {
Column().width('100%').height('100%').backgroundColor(Color.Green)
}.tabBar(this.tabBuilder(0, 'green'))
TabContent() {
Tabs() {
TabContent() {
Column().width('100%').height('100%').backgroundColor(Color.Blue)
}.tabBar(new SubTabBarStyle('blue'))
TabContent() {
Column().width('100%').height('100%').backgroundColor(Color.Pink)
}.tabBar(new SubTabBarStyle('pink'))
}
.onAnimationStart((index: number, targetIndex: number) => {
console.info('ets onGestureRecognizerJudgeBegin child:' + targetIndex)
this.innerSelectedIndex = targetIndex
})
.onGestureRecognizerJudgeBegin((event: BaseGestureEvent, current: GestureRecognizer,
others: Array<GestureRecognizer>): GestureJudgeResult => { // 在识别器即将要成功时,根据当前组件状态,设置识别器使能状态
console.info('ets onGestureRecognizerJudgeBegin child')
if (current) {
let target = current.getEventTargetInfo();
if (target && current.isBuiltIn() && current.getType() == GestureControl.GestureType.PAN_GESTURE) {
console.info('ets onGestureRecognizerJudgeBegin child PAN_GESTURE')
let panEvent = event as PanGestureEvent;
if (panEvent && panEvent.velocityX < 0 && this.innerSelectedIndex === 1) { // 内层Tabs滑动到尽头
console.info('ets onGestureRecognizerJudgeBegin child reject end')
return GestureJudgeResult.REJECT;
}
if (panEvent && panEvent.velocityX > 0 && this.innerSelectedIndex === 0) { // 内层Tabs滑动到开头
console.info('ets onGestureRecognizerJudgeBegin child reject begin')
return GestureJudgeResult.REJECT;
}
}
}
return GestureJudgeResult.CONTINUE;
}, true)
}.tabBar(this.tabBuilder(1, 'blue and pink'))
TabContent() {
Column().width('100%').height('100%').backgroundColor(Color.Brown)
}.tabBar(this.tabBuilder(2, 'brown'))
}
.onAnimationStart((index: number, targetIndex: number, event: TabsAnimationEvent) => {
// 切换动画开始时触发该回调。目标页签显示下划线。
this.selectedIndex = targetIndex
})
}
}
}
示例3(拦截手势获取属性)
该示例通过配置onGestureRecognizerJudgeBegin判定手势,获取相应属性参数。
// xxx.ets
@Entry
@Component
struct Index {
@State message: string = 'Gesture';
build() {
Column() {
Row({ space: 20 }) {
Text(this.message)
.width(400)
.height(80)
.fontSize(23)
}.margin(25)
}
.margin(50)
.width(400)
.height(200)
.borderWidth(2)
.gesture(TapGesture())
.gesture(LongPressGesture())
.gesture(PanGesture({ direction: PanDirection.Vertical }))
.gesture(PinchGesture())
.gesture(RotationGesture())
.gesture(SwipeGesture({ direction: SwipeDirection.Horizontal }))
//通过给组件绑定自定义手势识别器判定回调
.onGestureRecognizerJudgeBegin((event: BaseGestureEvent, current: GestureRecognizer,
others: Array<GestureRecognizer>) => {
if (current) {
//判断是否为拖动手势
if (current.getType() == GestureControl.GestureType.PAN_GESTURE) {
let target = current as PanRecognizer;
this.message = 'PanGesture\ndistance:' + target.getPanGestureOptions().getDistance() + '\nfingers:' +
target.getFingerCount() + '\nisFingerCountLimited:' + target.isFingerCountLimit();
}
//判断是否为长按手势
if (current.getType() == GestureControl.GestureType.LONG_PRESS_GESTURE) {
let target = current as LongPressRecognizer;
this.message = 'LongPressGesture\nfingers:' + target.getFingerCount() + '\nisFingerCountLimited:' +
target.isFingerCountLimit() + '\nrepeat:' + target.isRepeat() + '\nduration:' + target.getDuration();
}
//判断是否为捏合手势
if (current.getType() == GestureControl.GestureType.PINCH_GESTURE) {
let target = current as PinchRecognizer;
this.message = 'PinchGesture\ndistance:' + target.getDistance() + '\nfingers:' +
target.getFingerCount() + '\nisFingerCountLimited:' + target.isFingerCountLimit();
}
//判断是否为点击手势
if (current.getType() == GestureControl.GestureType.TAP_GESTURE) {
let target = current as TapRecognizer;
this.message = 'TapGesture\ncount:' + target.getTapCount() + '\nfingers:' +
target.getFingerCount() + '\nisFingerCountLimited:' + target.isFingerCountLimit();
}
//判断是否为旋转手势
if (current.getType() == GestureControl.GestureType.ROTATION_GESTURE) {
let target = current as RotationRecognizer;
this.message = 'RotationGesture\nangle:' + target.getAngle() + '\nfingers:' +
target.getFingerCount() + '\nisFingerCountLimited:' + target.isFingerCountLimit();
}
//判断是否为滑动手势
if (current.getType() == GestureControl.GestureType.SWIPE_GESTURE) {
let target = current as SwipeRecognizer;
this.message = 'SwipeGesture\ndirection:' + target.getDirection() + '\nfingers:' +
target.getFingerCount() + '\nisFingerCountLimited:' + target.isFingerCountLimit() + '\nspeed:' +
target.getVelocityThreshold();
}
}
return GestureJudgeResult.CONTINUE;
})
}
}
### 示例4(手势触发成功时取消子组件上的Touch事件)
该示例通过配置onGestureRecognizerJudgeBegin判定手势,在父容器手势触发成功时,调用cancelTouch()强制取消子组件上的Touch事件,实现父子组件手势控制的精准切换。
// xxx.ets
@Entry
@Component
struct FatherControlChild {
scroller: Scroller = new Scroller();
scroller2: Scroller = new Scroller()
private arr: number[] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
private childRecognizer: GestureRecognizer = new GestureRecognizer();
private currentRecognizer: GestureRecognizer = new GestureRecognizer();
private lastOffset: number = 0;
@State innerState: string = "IDLE"; // 内部滚动容器状态
@State stateHistory: string[] = ["状态历史:"]; // 状态变化历史记录
updateState(newState: string) {
this.innerState = newState;
this.stateHistory.push(` ${newState}`);
if (this.stateHistory.length > 10) {
this.stateHistory = this.stateHistory.slice(this.stateHistory.length - 10);
}
}
build() {
Stack({ alignContent: Alignment.TopStart }) {
// 主内容区域
Scroll(this.scroller) {
Column() {
Text("Scroll Area")
.width('90%')
.height(150)
.backgroundColor(0xFFFFFF)
.borderRadius(15)
.fontSize(16)
.textAlign(TextAlign.Center)
.margin({ top: 10 })
Scroll(this.scroller2) {
Column() {
Text("Scroll Area2")
.width('90%')
.height(150)
.backgroundColor(0xFFFFFF)
.borderRadius(15)
.fontSize(16)
.textAlign(TextAlign.Center)
.margin({ top: 10 })
Column() {
ForEach(this.arr, (item: number) => {
Text(item.toString())
.width('90%')
.height(150)
.backgroundColor(0xFFFFFF)
.borderRadius(15)
.fontSize(16)
.textAlign(TextAlign.Center)
.margin({ top: 10 })
}, (item: string) => item)
}.width('100%')
}
}
.id("inner")
.width('100%')
.height(800)
.onTouch((event) => {
if (event.type === TouchType.Down) {
this.updateState("TOUCHING");
} else if (event.type === TouchType.Up||event.type === TouchType.Cancel) {
this.updateState("IDLE");
}
})
}.width('100%')
}
.id("outer")
.height('100%')
.scrollable(ScrollDirection.Vertical)
.scrollBar(BarState.On)
.scrollBarColor(Color.Gray)
.scrollBarWidth(10)
.edgeEffect(EdgeEffect.None)
.shouldBuiltInRecognizerParallelWith((current: GestureRecognizer, others: Array<GestureRecognizer>) => {
for (let i = 0; i < others.length; i++) {
let target = others[i].getEventTargetInfo();
if (target) {
if (target.getId() == "inner" && others[i].isBuiltIn() &&
others[i].getType() == GestureControl.GestureType.PAN_GESTURE) {
this.currentRecognizer = current;
this.childRecognizer = others[i];
return others[i];
}
}
}
return undefined;
})
.onGestureRecognizerJudgeBegin((event: BaseGestureEvent, current: GestureRecognizer,
others: Array<GestureRecognizer>,
touchRecognizers?: Array<TouchRecognizer>) => {
if (current && touchRecognizers) {
let target = current.getEventTargetInfo();
if (target) {
if (target.getId() == "outer" && current.isBuiltIn() &&
current.getType() == GestureControl.GestureType.PAN_GESTURE) {
return GestureJudgeResult.CONTINUE
}
for (let index = 0; index < touchRecognizers.length; index++) {
const element = touchRecognizers![index];
let touchTarget = element.getEventTargetInfo()
if (touchTarget && touchTarget.getId() == "inner") {
this.updateState("CANCELLED");
element.cancelTouch()
}
}
}
}
return GestureJudgeResult.CONTINUE;
})
.onTouch((event) => {
if (event.type === TouchType.Down) {
this.updateState("OUTER_TOUCHING");
}
})
.parallelGesture(
PanGesture()
.onActionUpdate((event: GestureEvent) => {
if (this.childRecognizer.getState() != GestureRecognizerState.SUCCESSFUL||
this.currentRecognizer.getState() != GestureRecognizerState.SUCCESSFUL) {
return;
}
let target = this.childRecognizer.getEventTargetInfo() as ScrollableTargetInfo;
let currentTarget = this.currentRecognizer.getEventTargetInfo() as ScrollableTargetInfo;
if (target instanceof ScrollableTargetInfo && currentTarget instanceof ScrollableTargetInfo) {
if (target.isEnd()) {
if ((event.offsetY - this.lastOffset) < 0) {
this.childRecognizer.setEnabled(false)
if (currentTarget.isEnd()) {
this.currentRecognizer.setEnabled(false)
} else {
this.currentRecognizer.setEnabled(true)
}
} else {
this.childRecognizer.setEnabled(true)
this.currentRecognizer.setEnabled(false)
}
} else if (target.isBegin()) {
if ((event.offsetY - this.lastOffset) > 0) {
this.childRecognizer.setEnabled(false)
if (currentTarget.isBegin()) {
this.currentRecognizer.setEnabled(false)
} else {
this.currentRecognizer.setEnabled(true)
}
} else {
this.childRecognizer.setEnabled(true)
this.currentRecognizer.setEnabled(false)
}
} else {
this.childRecognizer.setEnabled(true)
this.currentRecognizer.setEnabled(false)
}
}
this.lastOffset = event.offsetY
})
)
// 状态显示区域
Column() {
// 当前状态显示
Text(`当前状态: ${this.innerState}`)
.fontSize(20)
.fontColor(this.getStateColor(this.innerState))
.margin({ bottom: 10 })
// 状态历史记录
ForEach(this.stateHistory, (item: string) => {
Text(item)
.fontSize(20)
.textAlign(TextAlign.Start)
.margin({ left: 10, top: 4 })
}, (item: string) => item)
}
.width('90%')
.height(240)
.backgroundColor(Color.White)
.border({ width: 1, color: Color.Gray })
.position({ x: '5%', y: '75%' })
.margin({ top: -160 })
}
.width('100%')
.height('100%')
.backgroundColor(0xDCDCDC)
}
// 根据状态返回不同颜色
private getStateColor(state: string): Color {
switch (state) {
case "IDLE":
return Color.Gray;
case "TOUCHING":
return Color.Blue;
case "CANCELLED":
return Color.Red;
case "OUTER_TOUCHING":
return Color.Green;
default:
return Color.Black;
}
}
}
### 示例5(自定义手势识别器是否参与手势处理)
该示例通过配置onTouchTestDone指定手势识别器不参与后续手势处理,触发回调时,调用preventBegin()阻止手势识别器参与后续处理。
// xxx.ets
@Entry
@Component
struct TouchTestDoneExample {
@State tagList: string[] = ['Null', 'Tap1', 'Tap2', 'Tap3', 'Tap4'];
@State tagId: number = 0;
@State textValue: string = '';
// 多层嵌套场景,为每一层的组件绑定一个Tap手势
build() {
Column() {
Column() {
Text('Tap1')
.margin(20)
Column() {
Text('Tap2')
.margin(20)
Column() {
Text('Tap3')
.margin(20)
Column() {
Text('Tap4')
.margin(20)
}
.backgroundColor('#D5D5D5')
.width('80%')
.height('80%')
.gesture(TapGesture().tag('Tap4').onAction(() => {
this.textValue = 'Tap4';
}))
}
.backgroundColor('#F7F7F7')
.width('80%')
.height('80%')
.gesture(TapGesture().tag('Tap3').onAction(() => {
this.textValue = 'Tap3';
}))
}
.backgroundColor('#707070')
.width('80%')
.height('80%')
.gesture(TapGesture().tag('Tap2').onAction(() => {
this.textValue = 'Tap2';
}))
}
.backgroundColor('#D5D5D5')
.width('80%')
.height('80%')
.gesture(TapGesture().tag('Tap1').onAction(() => {
this.textValue = 'Tap1';
}))
.onTouchTestDone((event, recognizers) => {
console.info('event is ' + JSON.stringify(event));
for (let i = 0; i < recognizers.length; i++) {
let recognizer = recognizers[i];
console.info('type is ' + JSON.stringify(recognizer.getType()))
// 根据tag的值屏蔽不同的手势识别器
if (recognizer.getTag() == this.tagList[this.tagId]) {
recognizer.preventBegin();
}
}
})
Text('Current Gesture: ' + this.textValue)
.margin(5)
Button('Click to change preventGesture')
.margin(5)
.onClick(() => {
this.tagId++;
this.tagId %= 5;
})
Text('Current prevent gesture tag: ' + this.tagList[this.tagId])
.margin(5)
}
.width('100%')
.height('100%')
// 示例gif中,点击Tap2和Tap1的重合区域,不调用preventBegin时,触发的为Tap2手势;调用preventBegin阻止Tap2时,触发的为Tap1手势
}
}
你可能感兴趣的鸿蒙文章
- 所属分类: 后端技术
- 本文标签:
热门推荐
-
2、 - 优质文章
-
3、 gate.io
-
8、 golang
-
9、 openharmony
-
10、 Vue中input框自动聚焦