1. 綁定手勢方法
1.1 gesture(常規(guī)手勢綁定方法)
.gesture(gesture: GestureType, mask?: GestureMask)
gesture為通用的一種手勢綁定方法,可以將手勢綁定到對應(yīng)的組件上。
例如,可以將點擊手勢TapGesture通過gesture手勢綁定方法綁定到Text組件上。
// xxx.ets
@Entry
@Component
struct Index {
build() {
Column() {
Text('Gesture').fontSize(28)
// 采用gesture手勢綁定方法綁定TapGesture
.gesture(
TapGesture()
.onAction(() => {
console.info('TapGesture is onAction');
}))
}
.height(200)
.width(250)
}
}
1.2 priorityGesture(帶優(yōu)先級的手勢綁定方法)
.priorityGesture(gesture: GestureType, mask?: GestureMask)。
priorityGesture是帶優(yōu)先級的手勢綁定方法,可以在組件上綁定優(yōu)先識別的手勢。
在默認情況下,當父組件和子組件使用gesture綁定同類型的手勢時,子組件優(yōu)先識別通過gesture綁定的手勢。當父組件使用priorityGesture綁定與子組件同類型的手勢時,父組件優(yōu)先識別通過priorityGesture綁定的手勢。
例如,當父組件Column和子組件Text同時綁定TapGesture手勢時,父組件以帶優(yōu)先級手勢priorityGesture的形式進行綁定時,優(yōu)先響應(yīng)父組件綁定的TapGesture。
// xxx.ets
@Entry
@Component
struct Index {
build() {
Column() {
Text('Gesture').fontSize(28)
.gesture(
TapGesture()
.onAction(() => {
console.info('Text TapGesture is onAction');
}))
}
.height(200)
.width(250)
// 設(shè)置為priorityGesture時,點擊文本區(qū)域會忽略Text組件的TapGesture手勢事件,優(yōu)先響應(yīng)父組件Column的TapGesture手勢事件
.priorityGesture(
TapGesture()
.onAction(() => {
console.info('Column TapGesture is onAction');
}), GestureMask.IgnoreInternal)
}
}
1.3 parallelGesture(并行手勢綁定方法)
.parallelGesture(gesture: GestureType, mask?: GestureMask)
parallelGesture是并行的手勢綁定方法,可以在父子組件上綁定可以同時響應(yīng)的相同手勢。
在默認情況下,手勢事件為非冒泡事件,當父子組件綁定相同的手勢時,父子組件綁定的手勢事件會發(fā)生競爭,最多只有一個組件的手勢事件能夠獲得響應(yīng)。而當父組件綁定了并行手勢parallelGesture時,父子組件相同的手勢事件都可以觸發(fā),實現(xiàn)類似冒泡效果。
當父組件和子組件同時綁定單擊手勢事件和雙擊手勢事件時,父組件和子組件均只響應(yīng)單擊手勢事件。
2. 單一手勢
2.1 點擊手勢(TapGesture)
TapGesture(value?:{count?:number; fingers?:number})
點擊手勢支持單次點擊和多次點擊,擁有兩個可選參數(shù):
-
count:非必填參數(shù),聲明該點擊手勢識別的連續(xù)點擊次數(shù)。默認值為1,若設(shè)置小于1的非法值會被轉(zhuǎn)化為默認值。如果配置多次點擊,上一次抬起和下一次按下的超時時間為300毫秒。
-
fingers:非必填參數(shù),用于聲明觸發(fā)點擊的手指數(shù)量,最小值為1,最大值為10,默認值為1。當配置多指時,若第一根手指按下300毫秒內(nèi)未有足夠的手指數(shù)按下則手勢識別失敗。當實際點擊手指數(shù)超過配置值時,手勢識別失敗。
以在Text組件上綁定雙擊手勢(count值為2的點擊手勢)為例:
// xxx.ets
@Entry
@Component
struct Index {
@State value: string = "";
build() {
Column() {
Text('Click twice').fontSize(28)
.gesture(
// 綁定count為2的TapGesture
TapGesture({ count: 2 })
.onAction((event: GestureEvent) => {
this.value = JSON.stringify(event.fingerList[0]);
}))
Text(this.value)
}
.height(200)
.width(250)
.padding(20)
.border({ width: 3 })
.margin(30)
}
}
2.2 長按手勢(LongPressGesture)
LongPressGesture(value?:{fingers?:number; repeat?:boolean; duration?:number})
長按手勢用于觸發(fā)長按手勢事件,觸發(fā)長按手勢的最少手指數(shù)量為1,最短長按事件為500毫秒,擁有三個可選參數(shù):
-
fingers:非必選參數(shù),用于聲明觸發(fā)長按手勢所需要的最少手指數(shù)量,最小值為1,最大值為10,默認值為1。
-
repeat:非必選參數(shù),用于聲明是否連續(xù)觸發(fā)事件回調(diào),默認值為false。
-
duration:非必選參數(shù),用于聲明觸發(fā)長按所需的最短時間,單位為毫秒,默認值為500。
// xxx.ets
@Entry
@Component
struct Index {
@State count: number = 0;
build() {
Column() {
Text('LongPress OnAction:' + this.count).fontSize(28)
.gesture(
// 綁定可以重復(fù)觸發(fā)的LongPressGesture
LongPressGesture({ repeat: true })
.onAction((event: GestureEvent) => {
if (event.repeat) {
this.count++;
}
})
.onActionEnd(() => {
this.count = 0;
})
)
}
.height(200)
.width(250)
.padding(20)
.border({ width: 3 })
.margin(30)
}
}
2.3 拖動手勢(PanGesture)
PanGesture(value?:{ fingers?:number; direction?:PanDirection; distance?:number})
拖動手勢用于觸發(fā)拖動手勢事件,滑動達到最小滑動距離(默認值為5vp)時拖動手勢識別成功,擁有三個可選參數(shù):
-
fingers:非必選參數(shù),用于聲明觸發(fā)拖動手勢所需要的最少手指數(shù)量,最小值為1,最大值為10,默認值為1。
-
direction:非必選參數(shù),用于聲明觸發(fā)拖動的手勢方向,此枚舉值支持邏輯與(&)和邏輯或(|)運算。默認值為Pandirection.All。
-
distance:非必選參數(shù),用于聲明觸發(fā)拖動的最小拖動識別距離,單位為vp,默認值為5。
// xxx.ets
@Entry
@Component
struct Index {
@State offsetX: number = 0;
@State offsetY: number = 0;
@State positionX: number = 0;
@State positionY: number = 0;
build() {
Column() {
Text('PanGesture Offset:\nX: ' + this.offsetX + '\n' + 'Y: ' + this.offsetY)
.fontSize(28)
.height(200)
.width(300)
.padding(20)
.border({ width: 3 })
// 在組件上綁定布局位置信息
.translate({ x: this.offsetX, y: this.offsetY, z: 0 })
.gesture(
// 綁定拖動手勢
PanGesture()
.onActionStart((event: GestureEvent) => {
console.info('Pan start');
})
// 當觸發(fā)拖動手勢時,根據(jù)回調(diào)函數(shù)修改組件的布局位置信息
.onActionUpdate((event: GestureEvent) => {
this.offsetX = this.positionX + event.offsetX;
this.offsetY = this.positionY + event.offsetY;
})
.onActionEnd(() => {
this.positionX = this.offsetX;
this.positionY = this.offsetY;
})
)
}
.height(200)
.width(250)
}
}
大部分可滑動組件,如List、Grid、Scroll、Tab等組件是通過PanGesture實現(xiàn)滑動,在組件內(nèi)部的子組件綁定拖動手勢(PanGesture)或者滑動手勢(SwipeGesture)會導(dǎo)致手勢競爭。
當在子組件綁定PanGesture時,在子組件區(qū)域進行滑動僅觸發(fā)子組件的PanGesture。如果需要父組件響應(yīng),需要通過修改手勢綁定方法或者子組件向父組件傳遞消息進行實現(xiàn),或者通過修改父子組件的PanGesture參數(shù)distance使得拖動更靈敏。當子組件綁定SwipeGesture時,由于PanGesture和SwipeGesture觸發(fā)條件不同,需要修改PanGesture和SwipeGesture的參數(shù)以達到所需效果。
2.4 捏合手勢(PinchGesture)
PinchGesture(value?:{fingers?:number; distance?:number})
捏合手勢用于觸發(fā)捏合手勢事件,觸發(fā)捏合手勢的最少手指數(shù)量為2指,最大為5指,最小識別距離為5vp,擁有兩個可選參數(shù):
-
fingers:非必選參數(shù),用于聲明觸發(fā)捏合手勢所需要的最少手指數(shù)量,最小值為2,最大值為5,默認值為2。
-
distance:非必選參數(shù),用于聲明觸發(fā)捏合手勢的最小距離,單位為vp,默認值為5。
以在Column組件上綁定三指捏合手勢為例,可以通過在捏合手勢的函數(shù)回調(diào)中獲取縮放比例,實現(xiàn)對組件的縮小或放大:
// xxx.ets
@Entry
@Component
struct Index {
@State scaleValue: number = 1;
@State pinchValue: number = 1;
@State pinchX: number = 0;
@State pinchY: number = 0;
build() {
Column() {
Column() {
Text('PinchGesture scale:\n' + this.scaleValue)
Text('PinchGesture center:\n(' + this.pinchX + ',' + this.pinchY + ')')
}
.height(200)
.width(300)
.border({ width: 3 })
.margin({ top: 100 })
// 在組件上綁定縮放比例,可以通過修改縮放比例來實現(xiàn)組件的縮小或者放大
.scale({ x: this.scaleValue, y: this.scaleValue, z: 1 })
.gesture(
// 在組件上綁定三指觸發(fā)的捏合手勢
PinchGesture({ fingers: 3 })
.onActionStart((event: GestureEvent) => {
console.info('Pinch start');
})
// 當捏合手勢觸發(fā)時,可以通過回調(diào)函數(shù)獲取縮放比例,從而修改組件的縮放比例
.onActionUpdate((event: GestureEvent) => {
this.scaleValue = this.pinchValue * event.scale;
this.pinchX = event.pinchCenterX;
this.pinchY = event.pinchCenterY;
})
.onActionEnd(() => {
this.pinchValue = this.scaleValue;
console.info('Pinch end');
})
)
}
}
}
2.5 旋轉(zhuǎn)手勢(RotationGesture)
RotationGesture(value?:{fingers?:number; angle?:number})
旋轉(zhuǎn)手勢用于觸發(fā)旋轉(zhuǎn)手勢事件,觸發(fā)旋轉(zhuǎn)手勢的最少手指數(shù)量為2指,最大為5指,最小改變度數(shù)為1度,擁有兩個可選參數(shù):
-
fingers:非必選參數(shù),用于聲明觸發(fā)旋轉(zhuǎn)手勢所需要的最少手指數(shù)量,最小值為2,最大值為5,默認值為2。
-
angle:非必選參數(shù),用于聲明觸發(fā)旋轉(zhuǎn)手勢的最小改變度數(shù),單位為deg,默認值為1。
以在Text組件上綁定旋轉(zhuǎn)手勢實現(xiàn)組件的旋轉(zhuǎn)為例,可以通過在旋轉(zhuǎn)手勢的回調(diào)函數(shù)中獲取旋轉(zhuǎn)角度,從而實現(xiàn)組件的旋轉(zhuǎn):
// xxx.ets
@Entry
@Component
struct Index {
@State angle: number = 0;
@State rotateValue: number = 0;
build() {
Column() {
Text('RotationGesture angle:' + this.angle).fontSize(28)
// 在組件上綁定旋轉(zhuǎn)布局,可以通過修改旋轉(zhuǎn)角度來實現(xiàn)組件的旋轉(zhuǎn)
.rotate({ angle: this.angle })
.gesture(
RotationGesture()
.onActionStart((event: GestureEvent) => {
console.info('RotationGesture is onActionStart');
})
// 當旋轉(zhuǎn)手勢生效時,通過旋轉(zhuǎn)手勢的回調(diào)函數(shù)獲取旋轉(zhuǎn)角度,從而修改組件的旋轉(zhuǎn)角度
.onActionUpdate((event: GestureEvent) => {
this.angle = this.rotateValue + event.angle;
console.info('RotationGesture is onActionEnd');
})
// 當旋轉(zhuǎn)結(jié)束抬手時,固定組件在旋轉(zhuǎn)結(jié)束時的角度
.onActionEnd(() => {
this.rotateValue = this.angle;
console.info('RotationGesture is onActionEnd');
})
.onActionCancel(() => {
console.info('RotationGesture is onActionCancel');
})
)
}
.height(200)
.width(250)
}
}
2.6 滑動手勢(SwipeGesture)
SwipeGesture(value?:{fingers?:number; direction?:SwipeDirection; speed?:number})
滑動手勢用于觸發(fā)滑動事件,當滑動速度大于100vp/s時可以識別成功,擁有三個可選參數(shù):
-
fingers:非必選參數(shù),用于聲明觸發(fā)滑動手勢所需要的最少手指數(shù)量,最小值為1,最大值為10,默認值為1。
-
direction:非必選參數(shù),用于聲明觸發(fā)滑動手勢的方向,此枚舉值支持邏輯與(&)和邏輯或(|)運算。默認值為SwipeDirection.All。
-
speed:非必選參數(shù),用于聲明觸發(fā)滑動的最小滑動識別速度,單位為vp/s,默認值為100。
以在Column組件上綁定滑動手勢實現(xiàn)組件的旋轉(zhuǎn)為例:
// xxx.ets
@Entry
@Component
struct Index {
@State rotateAngle: number = 0;
@State speed: number = 1;
build() {
Column() {
Column() {
Text("SwipeGesture speed\n" + this.speed)
Text("SwipeGesture angle\n" + this.rotateAngle)
}
.border({ width: 3 })
.width(300)
.height(200)
.margin(100)
// 在Column組件上綁定旋轉(zhuǎn),通過滑動手勢的滑動速度和角度修改旋轉(zhuǎn)的角度
.rotate({ angle: this.rotateAngle })
.gesture(
// 綁定滑動手勢且限制僅在豎直方向滑動時觸發(fā)
SwipeGesture({ direction: SwipeDirection.Vertical })
// 當滑動手勢觸發(fā)時,獲取滑動的速度和角度,實現(xiàn)對組件的布局參數(shù)的修改
.onAction((event: GestureEvent) => {
this.speed = event.speed;
this.rotateAngle = event.angle;
})
)
}
}
}
當SwipeGesture和PanGesture同時綁定時,若二者是以默認方式或者互斥方式進行綁定時,會發(fā)生競爭。SwipeGesture的觸發(fā)條件為滑動速度達到100vp/s,PanGesture的觸發(fā)條件為滑動距離達到5vp,先達到觸發(fā)條件的手勢觸發(fā)??梢酝ㄟ^修改SwipeGesture和PanGesture的參數(shù)以達到不同的效果。
3. 組合手勢
組合手勢由多種單一手勢組合而成,通過在GestureGroup中使用不同的GestureMode來聲明該組合手勢的類型,支持順序識別、并行識別和互斥識別三種類型。
GestureGroup(mode:GestureMode, ...gesture:GestureType[])
- mode:必選參數(shù),為GestureMode枚舉類。用于聲明該組合手勢的類型。
- gesture:必選參數(shù),為由多個手勢組合而成的數(shù)組。用于聲明組合成該組合手勢的各個手勢。
3.1 順序識別
順序識別組合手勢對應(yīng)的GestureMode為Sequence。順序識別組合手勢將按照手勢的注冊順序識別手勢,直到所有的手勢識別成功。當順序識別組合手勢中有一個手勢識別失敗時,所有的手勢識別失敗。
以一個由長按手勢和拖動手勢組合而成的順序手勢為例:
在一個Column組件上綁定了translate屬性,通過修改該屬性可以設(shè)置組件的位置移動。然后在該組件上綁定LongPressGesture和PanGesture組合而成的Sequence組合手勢。當觸發(fā)LongPressGesture時,更新顯示的數(shù)字。當長按后進行拖動時,根據(jù)拖動手勢的回調(diào)函數(shù),實現(xiàn)組件的拖動。
// xxx.ets
@Entry
@Component
struct Index {
@State offsetX: number = 0;
@State offsetY: number = 0;
@State count: number = 0;
@State positionX: number = 0;
@State positionY: number = 0;
@State borderStyles: BorderStyle = BorderStyle.Solid
build() {
Column() {
Text('sequence gesture\n' + 'LongPress onAction:' + this.count + '\nPanGesture offset:\nX: ' + this.offsetX + '\n' + 'Y: ' + this.offsetY)
.fontSize(28)
}
// 綁定translate屬性可以實現(xiàn)組件的位置移動
.translate({ x: this.offsetX, y: this.offsetY, z: 0 })
.height(250)
.width(300)
//以下組合手勢為順序識別,當長按手勢事件未正常觸發(fā)時不會觸發(fā)拖動手勢事件
.gesture(
// 聲明該組合手勢的類型為Sequence類型
GestureGroup(GestureMode.Sequence,
// 該組合手勢第一個觸發(fā)的手勢為長按手勢,且長按手勢可多次響應(yīng)
LongPressGesture({ repeat: true })
// 當長按手勢識別成功,增加Text組件上顯示的count次數(shù)
.onAction((event: GestureEvent) => {
if (event.repeat) {
this.count++;
}
console.info('LongPress onAction');
})
.onActionEnd(() => {
console.info('LongPress end');
}),
// 當長按之后進行拖動,PanGesture手勢被觸發(fā)
PanGesture()
.onActionStart(() => {
this.borderStyles = BorderStyle.Dashed;
console.info('pan start');
})
// 當該手勢被觸發(fā)時,根據(jù)回調(diào)獲得拖動的距離,修改該組件的位移距離從而實現(xiàn)組件的移動
.onActionUpdate((event: GestureEvent) => {
this.offsetX = this.positionX + event.offsetX;
this.offsetY = this.positionY + event.offsetY;
console.info('pan update');
})
.onActionEnd(() => {
this.positionX = this.offsetX;
this.positionY = this.offsetY;
this.borderStyles = BorderStyle.Solid;
})
)
)
}
}
拖拽事件是一種典型的順序識別組合手勢事件,由長按手勢事件和滑動手勢事件組合而成。只有先長按達到長按手勢事件預(yù)設(shè)置的時間后進行滑動才會觸發(fā)拖拽事件。如果長按事件未達到或者長按后未進行滑動,拖拽事件均識別失敗。
3.2 并行識別
并行識別組合手勢對應(yīng)的GestureMode為Parallel。并行識別組合手勢中注冊的手勢將同時進行識別,直到所有手勢識別結(jié)束。并行識別手勢組合中的手勢進行識別時互不影響。
以在一個Column組件上綁定點擊手勢和雙擊手勢組成的并行識別手勢為例,由于單擊手勢和雙擊手勢是并行識別,因此兩個手勢可以同時進行識別,二者互不干涉。
// xxx.ets
@Entry
@Component
struct Index {
@State count1: number = 0;
@State count2: number = 0;
build() {
Column() {
Text('parallel gesture\n' + 'tapGesture count is 1:' + this.count1 + '\ntapGesture count is 2:' + this.count2 + '\n')
.fontSize(28)
}
.height(200)
.width(250)
// 以下組合手勢為并行并別,單擊手勢識別成功后,若在規(guī)定時間內(nèi)再次點擊,雙擊手勢也會識別成功
.gesture(
GestureGroup(GestureMode.Parallel,
TapGesture({ count: 1 })
.onAction(() => {
this.count1++;
}),
TapGesture({ count: 2 })
.onAction(() => {
this.count2++;
})
)
)
}
}
當由單擊手勢和雙擊手勢組成一個并行識別組合手勢后,在區(qū)域內(nèi)進行點擊時,單擊手勢和雙擊手勢將同時進行識別。
-
當只有單次點擊時,單擊手勢識別成功,雙擊手勢識別失敗。文章來源:http://www.zghlxwxcb.cn/news/detail-823993.html
-
當有兩次點擊時,若兩次點擊相距時間在規(guī)定時間內(nèi)(默認規(guī)定時間為300毫秒),觸發(fā)兩次單擊事件和一次雙擊事件。
-
當有兩次點擊時,若兩次點擊相距時間超出規(guī)定時間,觸發(fā)兩次單擊事件不觸發(fā)雙擊事件。
3.3 互斥識別
互斥識別組合手勢對應(yīng)的GestureMode為Exclusive?;コ庾R別組合手勢中注冊的手勢將同時進行識別,若有一個手勢識別成功,則結(jié)束手勢識別,其他所有手勢識別失敗。
以在一個Column組件上綁定單擊手勢和雙擊手勢組合而成的互斥識別組合手勢為例,由于單擊手勢只需要一次點擊即可觸發(fā)而雙擊手勢需要兩次,每次的點擊事件均被單擊手勢消費而不能積累成雙擊手勢,所以雙擊手勢無法觸發(fā)。
// xxx.ets
@Entry
@Component
struct Index {
@State count1: number = 0;
@State count2: number = 0;
build() {
Column() {
Text('parallel gesture\n' + 'tapGesture count is 1:' + this.count1 + '\ntapGesture count is 2:' + this.count2 + '\n')
.fontSize(28)
}
.height(200)
.width(250)
//以下組合手勢為互斥并別,單擊手勢識別成功后,雙擊手勢會識別失敗
.gesture(
GestureGroup(GestureMode.Exclusive,
TapGesture({ count: 1 })
.onAction(() => {
this.count1++;
}),
TapGesture({ count: 2 })
.onAction(() => {
this.count2++;
})
)
)
}
}
當由單擊手勢和雙擊手勢組成一個互斥識別組合手勢后,在區(qū)域內(nèi)進行點擊時,單擊手勢和雙擊手勢將同時進行識別。
當只有單次點擊時,單擊手勢識別成功,雙擊手勢識別失敗。
當有兩次點擊時,單擊手勢在第一次點擊時即宣告識別成功,此時雙擊手勢已經(jīng)失敗。即使在規(guī)定時間內(nèi)進行了第二次點擊,雙擊手勢事件也不會進行響應(yīng),此時會觸發(fā)單擊手勢事件的第二次識別成功。文章來源地址http://www.zghlxwxcb.cn/news/detail-823993.html
到了這里,關(guān)于鴻蒙開發(fā)筆記(二十七): 交互事件--手勢的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!