如何为组件的不同触摸区域添加不同交互动作(通过Event坐标实现)

系统 OpenHarmony
当前OpenHarmony提供的热区设置属性(ResponseRegion)只能在不同的触摸热区中触发相同的事件,那么如何实现不同热区不同事件呢,本例即以上述视频播放场景为例进行说明。

想了解更多关于开源的内容,请访问:

51CTO 开源基础软件社区

https://ost.51cto.com

场景说明

应用开发中经常需要给同一个组件划分不同的触摸热区,并且不同热区触发的操作也不同,比如阅读应用通常包含左右两个触摸热区,用户触摸左侧触发向后翻页,触摸右侧触发向前翻页;同样的,视频应用中,长按视频播放器的左侧触发快退播放,长按右侧触发快进播放等等。
当前OpenHarmony提供的热区设置属性(responseRegion)只能在不同的触摸热区中触发相同的事件,那么如何实现不同热区不同事件呢,本例即以上述视频播放场景为例进行说明。

效果呈现

效果说明:开始时视频以正常速度播放,播放到5秒时,长按播放器右侧触发快进播放,播放到14秒时长按播放器左侧触发快退播放。

环境要求

本例基于以下环境开发,开发者也可以基于其他适配的版本进行开发:

  • IDE: DevEco Studio 4.0 Release
  • SDK: Ohos_sdk_public 4.0.10.13 (API Version 10 Release)

实现思路

几乎组件的所有触摸事件都会返回event,通过返回的event可以获取到触摸点的坐标位置,那么就可以根据坐标位置为不同的组件区域添加不同的交互动作。如图:假设有一个长度为200vp的组件,我们希望点击组件的左侧时触发事件A,点击组件的右侧时触发事件B,那么就可以通过触摸点的坐标来判断,当触摸点的x坐标<=100时,触发事件A,反之触发事件B。

本例即采用上述思路为Video组件的左右两侧添加不同的交互动作。从而实现长按视频播放器的左侧触发后退播放,长按右侧触发快进播放。

开发步骤

本例详细开发步骤如下,开发步骤中仅展示相关步骤代码,全量代码请参考完整代码章节的内容。

通过Video组件创建视频播放器,并添加触摸手势,通过触摸控制视频的播放、暂停。

@Component
export struct VideoPlayer{
  //...
  private isPlaying:boolean = true
  private updateTime: number
  private videoController:VideoController = new VideoController()

  build(){
    // 添加视频组件
    Video({src:this.videoSrc, controller:this.videoController, previewUri:this.videoPreviewer,currentProgressRate:this.playRate})
      //...
      // 获取当前进度条的时间点
      .onUpdate((e)=>{
        this.updateTime = e.time
      })
      .gesture(
        // 添加触摸手势
        TapGesture({count:1})
          .onAction((event:GestureEvent)=>{
            if (this.isPlaying){
              // 触摸触发播放
              this.videoController.start()
              this.isPlaying = !this.isPlaying
            } else {
              // 再次触摸触发暂停
              this.videoController.pause()
              this.isPlaying =!this.isPlaying
            }
          })
      )
  }
}

为Video组件添加长按手势,通过长按手势触发播放的快退和快进动作。由于触摸手势和长按手势需要互斥,即一次只能触发一种手势,所以通过GestureGroup来实现手势的互斥。

.gesture(
  // 通过GestureGroup的GestureMode.Exclusive参数控制手势互斥
  GestureGroup(GestureMode.Exclusive,
    // 添加触摸手势
    TapGesture({count:1})
      .onAction((event:GestureEvent)=>{
        if (this.isPlaying){
          // 触摸触发播放
          this.videoController.start()
          this.isPlaying = !this.isPlaying
        } else {
          // 再次触摸触发暂停
          this.videoController.pause()
          this.isPlaying =!this.isPlaying
        }
      }),
    // 添加长按手势
    LongPressGesture({repeat:true})
      // 长按时触发快进或快退
      .onAction((event)=>{
        //添加快进和快退的逻辑,通过event获取手势坐标进行判断。
      })
      // 长按结束后播放速度回归正常
      .onActionEnd(()=>{
       // 添加回归正常播放的逻辑
      })
  )
)

补充长按手势中的业务逻辑:通过event获取到触摸点的x坐标:localX,当localX>=200时,说明触摸点在组件的右侧,触发快进播放;当localX<200时,说明触摸点在左侧,触发快退播放。当触摸停止时,回归正常播放速度。

// 添加长按手势
LongPressGesture({repeat:true})
// 长按时触发快进或快退
.onAction((event)=>{
  // 获取到触摸点x坐标localX,当localX>=200时,说明触摸点在组件的右侧,触发快进播放
  if (event.fingerList[0].localX>=200){
    // 播放速度变为2倍速
    this.playRate = PlaybackSpeed.Speed_Forward_2_00_X
  }
  // 当localX<200时,说明触摸点在左侧,触发快退播放
  if (event.fingerList[0].localX<200){
    if (this.intervalCount===0){
      // 通过进度时间减小来达到快退的目的,通过setInterval来控制后退的速度,否则会连续触发后退,瞬间后退到播放起点
      this.seekBack = setInterval(()=>{
        this.updateTime -= 1
        this.videoController.setCurrentTime(this.updateTime)
      },500)
    }
    this.intervalCount = 1
  }
})
// 长按结束后播放速度回归正常
.onActionEnd(()=>{
  // 播放回归到1倍速
  this.playRate = PlaybackSpeed.Speed_Forward_1_00_X
  // 清空计时器
  clearInterval(this.seekBack)
  this.intervalCount = 0
})

完整代码

本例完整代码如下:

说明:

本例中使用的视频等资源需要替换为开发者自己的资源。

@Entry
@Component
export struct VideoPlayer{
  private videoSrc:Resource = $rawfile('video_1.mp4')
  private isPlaying:boolean = true
  private updateTime: number = 0
  private videoPreviewer:Resource = $r('app.media.wandering_previewer')
  private videoController:VideoController = new VideoController()
  @State playRate:number = 1
  private seekBack:number = 0
  private intervalCount:number = 0

  build(){
    Column(){
      // 添加视频组件
      Video({src:this.videoSrc, controller:this.videoController, previewUri:this.videoPreviewer,currentProgressRate:this.playRate})
        .width('100%')
        .height('30%')
        .backgroundColor('#fffff0')
        .controls(true)
        .objectFit(ImageFit.Contain)
        // 获取当前进度条的时间点
        .onUpdate((e)=>{
          this.updateTime = e.time
        })
        .gesture(
          // 通过GestureGroup的GestureMode.Exclusive参数控制手势互斥
          GestureGroup(GestureMode.Exclusive,
            // 添加触摸手势
            TapGesture({count:1})
              .onAction((event:GestureEvent)=>{
                if (this.isPlaying){
                  // 触摸触发播放
                  this.videoController.start()
                  this.isPlaying = !this.isPlaying
                } else {
                  // 再次触摸触发暂停
                  this.videoController.pause()
                  this.isPlaying =!this.isPlaying
                }
              }),
            // 添加长按手势
            LongPressGesture({repeat:true})
              // 长按时触发快进或快退
              .onAction((event)=>{
                // 获取到触摸点x坐标localX,当localX>=200时,说明触摸点在组件的右侧,触发快进播放
                if (event.fingerList[0].localX>=200){
                  // 播放速度变为2倍速
                  this.playRate = PlaybackSpeed.Speed_Forward_2_00_X
                }
                // 当localX<200时,说明触摸点在左侧,触发快退播放
                if (event.fingerList[0].localX<200){
                  if (this.intervalCount===0){
                    // 通过进度时间减小来达到快退的目的,通过setInterval来控制后退的速度,否则会连续触发后退,瞬间后退到播放起点
                    this.seekBack = setInterval(()=>{
                      this.updateTime -= 1
                      this.videoController.setCurrentTime(this.updateTime)
                    },500)
                  }
                  this.intervalCount = 1
                }
              })
                // 长按结束后播放速度回归正常
              .onActionEnd(()=>{
                // 播放回归到1倍速
                this.playRate = PlaybackSpeed.Speed_Forward_1_00_X
                // 清空计时器
                clearInterval(this.seekBack)
                this.intervalCount = 0
              })
          )
        )
    }
    .height('100%')
    .width('100%')
  }
}

参考

想了解更多关于开源的内容,请访问:

51CTO 开源基础软件社区

https://ost.51cto.com

责任编辑:jianghua 来源: 51CTO 开源基础软件社区
相关推荐

2014-07-18 09:54:57

vlan路​由​器

2022-10-21 09:01:33

小组件iOS

2009-12-17 16:53:13

.NET Framew

2009-11-05 09:01:41

WinForm

2024-01-08 09:27:28

自动驾驶模型

2021-01-15 11:21:33

UbuntuPHP命令

2009-07-02 13:40:45

面试

2009-02-19 15:40:00

Linux不同网段访问

2013-08-27 12:42:42

浏览器

2010-11-30 11:00:10

数据中心指标

2016-04-06 16:38:39

2022-03-02 07:52:13

React类组件函数式组件

2020-03-17 14:25:34

架构运维技术

2011-04-19 10:53:05

SSAS

2022-04-12 07:37:08

CSS滚动视差效果前端

2012-11-27 10:14:01

.net条件编译

2020-09-06 09:55:13

git分支命令

2021-06-11 06:10:25

Linux发行版操作系统

2010-07-01 16:12:10

UML组件图

2015-07-07 10:12:52

数据中心闪存
点赞
收藏

51CTO技术栈公众号