屏幕作业区域控制视频快进或回退

屏幕作业区域控制视频快进或回退

HarmonyOS
2024-05-28 20:11:26
浏览
收藏 0
回答 1
待解决
回答 1
按赞同
/
按时间
li_jian_jun

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

效果说明

开始时视频以正常速度播放,长按播放器右侧触发快进播放,长按播放器左侧触发快退播放。

环境要求

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

IDE: DevEco Studio 4.1 Release

SDK: Ohos_sdk_public 4.0.10.13 (API Version 10 Release)

实现思路

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

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

本例即采用上述思路为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%') 
} 
}
分享
微博
QQ
微信
回复
2024-05-29 21:00:39
相关问题
HarmonyOS 2怎么回退至EMUI官方稳定版本
4676浏览 • 1回复 已解决
panel组件点击区域问题
3408浏览 • 1回复 待解决
指定页面区域转化为图片
769浏览 • 1回复 待解决
如何屏蔽弹窗外的区域事件
1010浏览 • 1回复 待解决
日志的log区域不相关信息太多。
249浏览 • 1回复 待解决
如何获取屏幕相关配置
378浏览 • 1回复 待解决
鸿蒙手机屏幕怎么适配
8347浏览 • 1回复 待解决
如何获取手机屏幕信息
267浏览 • 1回复 待解决
如何获取系统屏幕固定。
2317浏览 • 0回复 待解决