模态转场

新的界面覆盖在旧的界面上,旧的界面不消失

属性 说明
bindContentCover 自定义全屏的模态展示界面(e.g. 点击查看大图)
bindSheet 半模态展示界面(e.g. 分享框)
bindMenu 点击弹出菜单(e.g. 点击"+"号弹出菜单)
bindContextMenu 长按/右键点击弹出菜单(e.g. 长按浮起)
bindPopup 弹出Popup弹框(e.g. 弹出临时说明)
if 增加/删除组件(e.g. 临时显示某页面)

手势说明

触摸事件——手势的基础

所有手势的基础:触摸事件(onTouch:Down,Up,Move,Cancel)

.onTouch((event)=>{
switch(event.type){
//按下
case TouchType.Down:
//event.touches[0]表示最新的数据
console.log("pos x: "+event.touches[0].x)
console.log("pos y: "+event.touches[0].y)
break
//抬起
case TouchType.Up:
console.log("x: "+event.touches[0].x)
console.log("y: "+event.touches[0].y)
break
//移动
case TouchType.Move:
console.log("x: "+event.touches[0].x)
console.log("y: "+event.touches[0].y)
break
case TouchType.Cancel:
console.log("x: "+event.touches[0].x)
console.log("y: "+event.touches[0].y)
break
}
}
)

规则如下:

  1. 监听onTouch事件的组件,若在手指落下时被触摸则均会收到onTouch事件的回调,被触摸受到触摸热区和触摸控制影响。

  2. onTouch事件的回调是闭环的。若组件收到了手指Id为0的Down事件,后续也会收到手指Id为0的Move事件和Up事件。

  3. onTouch事件的回调是一致的。若组件收到了手指Id为0的Down事件,而未收到手指Id为1的Down事件,后续只会收到手指Id为0的touch事件,不会收到手指Id为1的后续touch事件。

  4. 对于一般的容器组件,父子组件之间onTouch事件能够同时触发,兄弟组件之间onTouch事件根据布局进行触发。

  5. 除非显示声明允许多个手势同时成功,否则同一时间只会有一个手势响应

手势类型

手势类型 声明格式 说明
点击 TapGesture(
value?:{count?:number, fingers?:number}
)
上一次抬起和下一次按下的超时时间为300毫秒
长按 LongPressGesture(
value?:{fingers?:number, repeat?:boolean, duration?:number}
)
长按所需的最短时间默认值为500
拖动 PanGesture(
value?:{ fingers?:number, direction?:PanDirection, distance?:number}
)
滑动达到最小滑动距离(默认值为5vp)时拖动手势识别成功
捏合 PinchGesture(
value?:{fingers?:number, distance?:number}
)
1. 触发所需手指数最小为2,最大为5
2. 触发最小距离默认值为5
旋转 RotationGesture(
value?:{fingers?:number, angle?:number}
)
1. 触发所需手指数最小为2,最大为5
2. 最小改变度数默认值为1deg
滑动 SwipeGesture(
value?:{fingers?:number, direction?:SwipeDirection, speed?:number}v)
滑动速度大于100vp/s时可以识别成功

组合手势

GestureGroup(mode:GestureMode, gesture:GestureType[])
//手势触发后出现的内容
@Builder
content(){
Column(){
Row({space:100}){
Text("AAAAA")
.width("20%")
.aspectRatio(1)
.backgroundColor(Color.Pink)
.borderRadius(100)
.rotate({
angle:30
})
Text("BBBBBB")
.width("20%")
.aspectRatio(1)
.backgroundColor(Color.Blue)
.borderRadius(100)
.rotate({
angle:-30
})
}
}
}

//
Image('https://img-s-msn-com.akamaized.net/tenant/amp/entityid/AA1rYtdV.img?w=768&h=607&m=6&x=439&y=181&s=163&d=163')
.width("30%")
.aspectRatio(16/9)
.bindContentCover(this.isShow,this.content)

//触发手势
Button('change')
.gesture(
//GestureMode:Sequence、Parallel(并行执行)、Exclude(只能执行一个)
GestureGroup(GestureMode.Sequence,
//长按触发
LongPressGesture()
.onAction(()=>{
this.isShow = true
})
.onActionEnd(()=>{
this.isShow = false
})
.onActionCancel(()=>{
AlertDialog.show({message:"over"})
})
,
//拖拽触发
PanGesture()
.onActionStart(()=>{
this.isShow = true
})
.onActionUpdate((event)=>{
if(event.fingerList[0].globalX<this.screenWidth/2)
AlertDialog.show({message:"left"})
else AlertDialog.show({message:"right"})
})
.onActionEnd(()=>{
this.isShow = false
})
.onActionCancel(()=>{
AlertDialog.show({message:"over"})
})
)
)

//获取屏幕宽度,1vp = 3px
aboutToAppear(): void {
this.screenWidth = px2vp(display.getDefaultDisplaySync().width)
}

组合手势冲突说明

优先级

  • 系统 > 自定义
  • 除非显示声明允许多个手势同时成功,否则同一时间只会有一个手势响应
    响应优先级遵循以下条件:
  1. 当父子组件均绑定同一类手势时,子>父(
  2. 当一个组件绑定多个手势时,先达到手势触发条件的手势优先
  3. 如果父以带优先级的方式绑定手势(.priorityGesture),则可父>子
  4. 当父组件以.parallelGesture的形式绑定手势时,父和子所绑定的手势均可触发

冲突事件

冲突事件 | 运行逻辑 |
当有两次点击时 | 手势响应取决于绑定手势的顺序

  1. 若先绑定单击手势后绑定双击手势,单击手势在第一次点击时即宣告识别成功,此时双击手势已经失败。即使在规定时间内进行了第二次点击,双击手势事件也不会进行响应,此时会触发单击手势事件的第二次识别成功
  2. 若先绑定双击手势后绑定单击手势,则会响应双击手势不响应单击手势

自定义控制的多层级手势事件

通过设置属性,控制默认的多层级手势事件竞争流程

  • responseRegion属性和hitTestBehavior属性可以控制Touch事件的分发,从而可以影响到onTouch事件和手势的响应
  • 绑定手势方法属性可以控制手势的竞争从而影响手势的响应,但不能影响到onTouch事件
属性 说明
.responseRegion({Rect1, Rect2, Rect3}) 1. 实现组件的响应区域范围的变化
2. 响应区域范围可以超出或者小于组件的布局范围
3. 绑定responseRegion后,手势与事件的响应区域范围将以所绑定的区域范围为准,而不是以布局区域为准
.hitTestBehavior(HitTestMode.XXX) 使一些组件能够响应手势和事件,而一些组件不能响应手势和事件

tips: HitTestMode中sequence中第一个的onActionEnd不会执行,只会执行最后一个的