当前位置: 首页 > news >正文

基于鸿蒙API10的RTSP播放器(八:音量和亮度调节功能的整合)

一、前言:

笔者在前面第六、七节文章当中,分别指出了音量和屏幕亮度的前置知识,在本节当中,我们将一并实现这两个功能,从而接续第五节内容。本文的逻辑分三大部分,先说用到的变量,再说界面,最后说功能。

其中音量功能,是设置的系统音量,而不是视频音量;其中亮度功能,是设置的应用亮度,而非系统亮度,请注意两者的区别。

亮度功能使用brightness库获取系统亮度值,在初始化亮度值,然后根据触摸情况通过window库设置亮度值

音量功能通过audio库,初始化音量值,根据触摸情况设置音量值

文中代码均是ArkTS代码,使用TS标志,是为了有颜色,好看,嘿嘿!

以下是效果图,即我手指左边垂直向下滑动时,出现亮度调节图标和进度条。
在这里插入图片描述

以下是效果图,即我手指右边垂直向下滑动时,出现音量调节图标和进度条。
在这里插入图片描述

二、状态变量:

// 以下代码均放在struct yourPageName{}结构体内,但在build(){}函数之外// 控制图标和进度条是否显示  
@State volumeVisible:boolean = false;  
@State brightVisible: boolean = false;  // 音量和亮度值  
@State volume:number = 0;  
@State bright:number = 50;  // 手指触点横坐标位置  
@State fingerPosition:number = 0;  // 屏幕一半宽度,我这里是500px  
@State halfDeviceWidth:number = 500;  // 根据全局变量获得窗口控制器 ,这里需要提前在EntryAbility中设置全局变量,并把windowStage放进去,代码附下
windowStage: window.WindowStage = AppStorage.get('windowStage') as window.WindowStage;  
// 获取主窗口的方式  
mainWin: window.Window = this.windowStage.getMainWindowSync();

import AbilityConstant from '@ohos.app.ability.AbilityConstant';  
import hilog from '@ohos.hilog';  
import UIAbility from '@ohos.app.ability.UIAbility';  
import Want from '@ohos.app.ability.Want';  
import window from '@ohos.window';  
import { BusinessError } from '@kit.BasicServicesKit';  export default class EntryAbility extends UIAbility {  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {  hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');  }  onDestroy(): void {  hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy');  }  onWindowStageCreate(windowStage: window.WindowStage): void {  // Main window is created, set main page for this ability  hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');  console.log('onWindowStageCreate');  // 这里设置全局变量,把我们需要的窗体控制器放进去AppStorage.setOrCreate('windowStage',windowStage);  windowStage.loadContent('pages/Index', (err) => {  if (err.code) {  hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');  return;  }  hilog.info(0x0000, 'testTag', 'Succeeded in loading the content.');  });  }  onWindowStageDestroy(): void {  // Main window is destroyed, release UI related resources  hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');  }  onForeground(): void {  // Ability has brought to foreground  hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground');  }  onBackground(): void {  // Ability has back to background  hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground');  }  
}
三、界面逻辑:**

这里使用了Stack组件,按照栈概念,可以将图片和进度条在同一时刻一起显示。可以看到笔者这里设置了if语句中的三个变量,分别判断触摸点是否移动,触摸点在屏幕左边还是右边,是否显示。

Stack(){  // 亮度调节UI  if (this.fingerPosition != 0 && this.fingerPosition < this.halfDeviceWidth && this.brightVisible){  Image($r('app.media.ic_bright_white'))  .width(50)  .aspectRatio(1.0)  Progress({value:this.bright,total:100,type:ProgressType.Ring})  .color('#ffffffff')  .width(100)  .aspectRatio(1.0)  // 音量调节UI  }else if (this.fingerPosition != 0 && this.fingerPosition > this.halfDeviceWidth && this.volumeVisible){  Image($r('app.media.ic_volume_white'))  .width(50)  .aspectRatio(1.0)  Progress({value:this.volume,total: 20,type:ProgressType.Ring})  .color('#ffffffff')  .width(100)  .aspectRatio(1.0)  }  
}  // Stack组件可以自行调节,这段代码也可以嵌入进其他代码中,里面的图片随便找一个就好了
.width('100%')  
.height('40%')  
.backgroundColor(Color.Black)
四、功能逻辑:

我们需要在页面渲染之前完成一些初始化的工作,包括主窗体的获取,音量的初始化,亮度的初始化。

当然,也可以直接在第一部分定义变量的时候直接赋值,但直接赋值的弊端就是,以音量调节为例,进度条每次从设置的音量值开始变化,而不是从系统本来的值开始变化。笔者这里的初始化代码附下

// 此函数是生命周期函数,在struct yourPageName(){}中,build(){}之外
aboutToAppear() {  // 初始化音量audioManager.getVolume(audio.AudioVolumeType.MEDIA, (err: BusinessError, value: number) => {  if (err) {  console.error(`Failed to obtain the volume. ${err}`);  return;  }  this.volume = value;  console.info('Callback invoked to indicate that the volume is obtained:'+value);  });  ////  音量初始化,这里代码笔者注释了,选择在定义变量的时候直接赋值0.5
// brightness.getValue({  
//   success: (data: BrightnessResponse) => {  
//     console.log('success get brightness value:' + data.value);  
//     // brightness库中获取的亮度值介于0到255,而window库中设置的亮度值介于0到1,这里在做转换  
//     this.bright = ((data.value/255)*10)%10  
//     try {  
//       this.mainWin.setWindowBrightness(this.bright, (err) => {  
//         if (err.code) {  
//           console.error('Failed to set the brightness. Cause: ' + JSON.stringify(err));  
//           return;  
//         }  
//         console.info('Succeeded in setting the brightness.');  
//       });  
//     } catch (exception) {  
//       console.error('Failed to set the brightness. Cause: ' + JSON.stringify(exception));  
//     }  
//   },  
//   fail: (data: string, code: number) => {  
//     console.error('get brightness fail, code: ' + code + ', data: ' + data);  
//   }  
// });// 初始化主窗体this.windowStage = AppStorage.get('windowStage') as window.WindowStage;  // 获取主窗口的方式  this.mainWin = this.windowStage.getMainWindowSync();  // 获取最上层窗口的方式  // window.getLastWindow(getContext(this));  }

为上面的Stack组件添加触摸事件,具体功能见代码注释,这里面的try-catch语句主要方便调试,代码如果可以正常运行的话,直接去掉try-catch语句和日志打印,那么代码可以很简介。里面最核心的函数是if语句。


Stack(){//代码上面有,此处省略
}
.gesture(  GestureGroup(GestureMode.Exclusive,  // 添加触摸手势,并通过direction控制手势滑动方向为上下滑动  PanGesture({direction:PanDirection.Vertical})  .onActionStart((event: GestureEvent) => {  // 获取屏幕宽度和高度,便于后面的手势操作  if (event.fingerList[0].localX < this.halfDeviceWidth) {  this.brightVisible = true;  } else {  this.volumeVisible = true;  }  })  .onActionEnd(() => {  // 当手指离开屏幕时,清除currentIcon状态和关闭图标/进度条  this.volumeVisible = false;  this.brightVisible = false;  })  .onActionUpdate((event?:GestureEvent| undefined)=>{  // 取得系统亮度,为this.bright赋初值  if (!event) return; // 如果 event 是 undefined,直接返回,不执行后续代码  // 通过event.fingerList[0].localX获取触摸点的横坐标  this.fingerPosition = event.fingerList[0].localX  // 向上滑动  if (event.offsetY < 0){  // 触摸点在屏幕右侧  if (this.volume < 20 && this.fingerPosition > this.halfDeviceWidth){  // 音量值增加  this.volume += 0.2  audioManager.setVolume(audio.AudioVolumeType.MEDIA, this.volume, (err: BusinessError) => {  if (err) {  console.error(`Failed to set the volume. ${err}`);  return;  }  console.info('Callback invoked to indicate a successful volume setting.');  });  }  // 触摸点在屏幕左侧  if (this.bright < 100 && this.fingerPosition < this.halfDeviceWidth){  // 亮度值增加  this.bright += 1  try {  this.mainWin.setWindowBrightness(this.bright / 100 , (err) => {  if (err.code) {  console.error('Failed to set the brightness. Cause: ' + JSON.stringify(err));  return;  }  console.info('Succeeded in setting the brightness.');  });  } catch (exception) {  console.error('Failed to set the brightness. Cause: ' + JSON.stringify(exception));  }  }        // 向下滑动  }else{  // 触摸点在屏幕右侧  if (this.volume > 0 && this.fingerPosition > this.halfDeviceWidth){  // 音量值减小  this.volume -= 0.2  audioManager.setVolume(audio.AudioVolumeType.MEDIA, this.volume, (err: BusinessError) => {  if (err) {  console.error(`Failed to set the volume. ${err}`);  return;  }  console.info('Callback invoked to indicate a successful volume setting.');  });  }  // 触摸点在屏幕左侧  if (this.bright > 0 && this.fingerPosition < this.halfDeviceWidth){  // 亮度值减小  this.bright -= 1  try {  this.mainWin.setWindowBrightness(this.bright / 100 , (err) => {  if (err.code) {  console.error('Failed to set the brightness. Cause: ' + JSON.stringify(err));  return;  }  console.info('Succeeded in setting the brightness.');  });  } catch (exception) {  console.error('Failed to set the brightness. Cause: ' + JSON.stringify(exception));  }  }        }      }),  )  
)

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • LeetCode --- 414周赛
  • 深入理解Linux中的多路复用技术:select、poll与epoll
  • 玄机靶场初体验
  • 目标检测-小目标检测方法
  • 《ORANGE‘s 一个操作系统的实现》-- ubuntu14.04下bochs2.3.5的配置与使用
  • 【第34章】Spring Cloud之SkyWalking分布式日志
  • JVM四种垃圾回收算法以及G1垃圾回收器(面试)
  • 今日leetCode 242.有效的字母异位词
  • 云服务器部署DB-GPT项目
  • .Net 执行Linux下多行shell命令方法
  • 无线领夹麦克风哪个牌子好,口碑最好的麦克风品牌,领夹麦推荐
  • 什么是数据资源?
  • ImportError: DLL load failed while importing _ssl: 找不到指定的模块的解决方法
  • .NET/C#⾯试题汇总系列:集合、异常、泛型、LINQ、委托、EF!(完整版)
  • 大模型从失败中学习 —— 微调大模型以提升Agent性能
  • angular组件开发
  • ES6 ...操作符
  • Fabric架构演变之路
  • java取消线程实例
  • mongodb--安装和初步使用教程
  • Perseus-BERT——业内性能极致优化的BERT训练方案
  • socket.io+express实现聊天室的思考(三)
  • Spring核心 Bean的高级装配
  • Vue ES6 Jade Scss Webpack Gulp
  • 安卓应用性能调试和优化经验分享
  • 番外篇1:在Windows环境下安装JDK
  • 给github项目添加CI badge
  • 嵌入式文件系统
  • 容器服务kubernetes弹性伸缩高级用法
  • 扫描识别控件Dynamic Web TWAIN v12.2发布,改进SSL证书
  • 使用 QuickBI 搭建酷炫可视化分析
  • 突破自己的技术思维
  • 推荐一款sublime text 3 支持JSX和es201x 代码格式化的插件
  • ​虚拟化系列介绍(十)
  • # 学号 2017-2018-20172309 《程序设计与数据结构》实验三报告
  • $HTTP_POST_VARS['']和$_POST['']的区别
  • (06)Hive——正则表达式
  • (3)Dubbo启动时qos-server can not bind localhost22222错误解决
  • (CPU/GPU)粒子继承贴图颜色发射
  • (delphi11最新学习资料) Object Pascal 学习笔记---第14章泛型第2节(泛型类的类构造函数)
  • (ZT) 理解系统底层的概念是多么重要(by趋势科技邹飞)
  • (层次遍历)104. 二叉树的最大深度
  • (分享)一个图片添加水印的小demo的页面,可自定义样式
  • (论文阅读31/100)Stacked hourglass networks for human pose estimation
  • (十七)devops持续集成开发——使用jenkins流水线pipeline方式发布一个微服务项目
  • (一)appium-desktop定位元素原理
  • (一)UDP基本编程步骤
  • (转)菜鸟学数据库(三)——存储过程
  • (转载)从 Java 代码到 Java 堆
  • (最全解法)输入一个整数,输出该数二进制表示中1的个数。
  • .equal()和==的区别 怎样判断字符串为空问题: Illegal invoke-super to void nio.file.AccessDeniedException
  • .Net Core 中间件验签
  • .net php 通信,flash与asp/php/asp.net通信的方法
  • .net 开发怎么实现前后端分离_前后端分离:分离式开发和一体式发布
  • .net 使用ajax控件后如何调用前端脚本