HarmonyOS 鸿蒙Next求助:时间进度条怎么搞?

HarmonyOS 鸿蒙Next求助:时间进度条怎么搞?

cke_247.png

本人目前想做一个时间进度条(刻度条)开始时间是0:00,结束时间是24:00,小时和小时之间还有刻度

时间进度条的特性:

  1. 可以滑动,滑动到哪里,中间的紫色显示滑动到的时间。精确到秒
  2. 时间轴可以放大缩小:小时和小时之间6个格子(1格子代表10分钟),根据收拾捏合放大缩小

放大:原来默认小时为单位(1刻度代表10分钟),放大后10分钟为单位(里面1刻度代表1分钟),继续放大到1分钟为单位(1刻度代表1秒钟)

这种需求怎么搞?我没有做过相关,有大佬可以指一下路吗?或者有相关Demo可以提供一下,感激不尽


更多关于HarmonyOS 鸿蒙Next求助:时间进度条怎么搞?的实战教程也可以访问 https://www.itying.com/category-93-b0.html

13 回复
  1. 实现时间卡尺模型:
if(this.divisorMode == TimeBarViewModel.MODE_HOUR) {
   //小时模式
   //中心点距离左边所占用的时长
   this.middleLineDuration = Math.floor((this.viewWidth / 2) * (TimeBarViewModel.TEN_MINUTE / this.divisorWidth))
   //计算屏幕最左边的时间
   this.leftTime = this.middleLineMillis - this.middleLineDuration
   //计算左边第一个刻度线的位置
   //由原来Java代码中的Math.ceil改成Math.floor,解决分钟模式下左侧不绘制刻度问题
   minuteNum = Math.floor(this.leftTime / TimeBarViewModel.TEN_MINUTE)
   xPosition =
     ((minuteNum * TimeBarViewModel.TEN_MINUTE) - this.leftTime) * (this.divisorWidth / TimeBarViewModel.TEN_MINUTE)
 } else if (this.divisorMode == TimeBarViewModel.MODE_MINUTE) {
   //分钟模式
   ...
 }
 //计算左边第一个刻度线是今天的第多少个分钟数
 for (let i = 0; i < scaleNum; i++) {
   if (this.divisorMode == TimeBarViewModel.MODE_HOUR) {
     //小时级别的画法
     if (minuteNum % 6 == 0) { //大刻度
       //画上面的大刻度

       this.scalePaint!.beginPath()
       this.scalePaint!.moveTo(xPosition + i * this.divisorWidth, this.viewHeight - this.scaleHeight * 2)
       this.scalePaint!.lineTo(xPosition + i * this.divisorWidth, this.viewHeight)
       this.scalePaint!.stroke()

       let hourMinute = this.getHourMinute(minuteNum)
       let timeStrWidth = this.scalePaint!.measureText(hourMinute).width
       this.timeStrHeight = this.scalePaint!.measureText(hourMinute).height
       //画出时间文字
       this.scalePaint!.fillText(hourMinute, xPosition + i * this.divisorWidth - timeStrWidth / 2,
         this.viewHeight - (this.scaleHeight * 2 + this.timeStrHeight))

     } else {
       //画上面的小刻度
       this.scalePaint!.beginPath()
       this.scalePaint!.moveTo(xPosition + i * this.divisorWidth, this.viewHeight - this.scaleHeight)
       this.scalePaint!.lineTo(xPosition + i * this.divisorWidth, this.viewHeight)
       this.scalePaint!.stroke()
     }
   } else if (this.divisorMode == TimeBarViewModel.MODE_MINUTE) {
     //分钟级别的画法
     ...
   }
   //每一格刻度代表10分钟
   if (this.divisorMode == TimeBarViewModel.MODE_HOUR) {
     minuteNum++;
   } else if(this.divisorMode == TimeBarViewModel.MODE_MINUTE) {
     secondNum++;
   }

在onPanActionEnd手势动作函数钟,通过middleLineMillis和videoCaliperInfo实现视频进度同步

// 视频同步
this.videoInfoList.forEach((video, index) => {
   video.isPlayed = this.hasVideoPlayed(index);
   if(video.isPlayed) {
     this.controller.setCurrentTime(Math.floor((this.middleLineMillis - video.caliperBeginStamp)/1000))
   }
})

完整代码:

import { RecordSegment } from './RecordSegment'
import { TimeBarView } from './TimeBarView'
import { TimeBarViewModel } from './TimeBarViewModel';
import List from '@ohos.util.List';
import dayJs from 'dayjs'
import { VideoCaliperInfo } from '../utils/VideoCaliperInfo';

@Entry
@Component
struct Index {
  @State private model: TimeBarViewModel = new TimeBarViewModel();
  @State currentTime: number = 0


  aboutToAppear(): void {
    let videos: List<VideoCaliperInfo> = new List();
    let beginTime1: number = this.model.yyyy_MM_dd_T_HH_mm_SSSZToCalendar('2024-05-13T23:37:16.000+08:00').getTime();
    let beginTime2: number = this.model.yyyy_MM_dd_T_HH_mm_SSSZToCalendar('2024-05-14T03:10:24.000+08:00').getTime();
    let endTime1: number = this.model.yyyy_MM_dd_T_HH_mm_SSSZToCalendar('2024-05-13T23:37:29.000+08:00').getTime();
    let endTime2: number = this.model.yyyy_MM_dd_T_HH_mm_SSSZToCalendar('2024-05-14T03:10:58.000+08:00').getTime();
    let videoOptions1: VideoOptions = { src:$rawfile('1.mp4'), controller:this.model.controller }
    let videoOptions2: VideoOptions = { src:$rawfile('3.mp4'), controller:this.model.controller }
    let videoCaliperInfo1: VideoCaliperInfo = new VideoCaliperInfo(videoOptions1, beginTime1, endTime1, false)
    let videoCaliperInfo2: VideoCaliperInfo = new VideoCaliperInfo(videoOptions2, beginTime2, endTime2, false)
    videos.add(videoCaliperInfo1);
    videos.add(videoCaliperInfo2);

    let fileInfoList: List<RecordSegment> = new List();
    let recordSegment1 = new RecordSegment()
    recordSegment1.recordType = 0
    recordSegment1.beginTime = '2024-05-13T23:37:16.000+08:00'
    recordSegment1.endTime = '2024-05-13T23:37:29.000+08:00'
    fileInfoList.add(recordSegment1)

    let recordSegment2 = new RecordSegment()
    recordSegment2.beginTime = '2024-05-14T03:10:24.000+08:00'
    recordSegment2.endTime = '2024-05-14T03:10:58.000+08:00'
    fileInfoList.add(recordSegment2)
    this.model.addFileInfoList(fileInfoList)

    this.model.addVideoInfoList(videos)
  }

  build() {
    Column() {
      Column(){
        Text('录像时间卡尺')
          .fontSize('30fp')
          .fontWeight(700)
          .margin({ top: '64vp' })
      }
      .width('100%')
      .height('20%')
      .margin({bottom:40})
      .justifyContent(FlexAlign.Start)
      .alignItems(HorizontalAlign.Start)

      Stack(){
        ForEach(this.model.getVideosList(), (video: VideoCaliperInfo, index: number) => {
          if(video.isPlayed) {
            Video(video.videoOption)
              .controls(false)
              .autoPlay(true)
          }
        })
      }
      .margin({bottom:20})
      .height('30%')

      Column(){
        Text(dayJs(new Date(this.model.middleLineMillis)).format('YYYY-MM-DD HH:mm:ss'))
          .padding(15)
        TimeBarView({ model: this.model })
      }
      .height('30%')
    }
    .width('100%')
    .height('100%')
  }
}

更多关于HarmonyOS 鸿蒙Next求助:时间进度条怎么搞?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


是的 和我发现的Demo代码一样 谢谢,

我来做的话会自定义组件 结合手势自己写一套 看楼主是怎么实现的

楼主这个是想做一个拖动获取或者设置时间的UI吗,成功了的话 我也参考学习一下

你不准学了,快去振刀,

你不准学了,快去振刀,

学习鸿蒙,

时间刻度轴

  • 开始时间: 2023-01-01
  • 结束时间: 2023-12-31

事件1

  • 日期: 2023-03-15

事件2

  • 日期: 2023-06-20

事件3

  • 日期: 2023-09-10

有要学HarmonyOS AI的同学吗,联系我:https://www.itying.com/goods-1206.html

可以试试用scroll组件,横向,然后自定义滑块样式,或者里面元素滚动,

项目名称

  • 项目类型: 网站
  • 状态: 进行中
  • 开始日期: 2023-09-01
  • 结束日期: 2023-12-31
  • 描述: 这是一个示例项目,用于展示如何将HTML内容转换为Markdown格式。

在HarmonyOS Next中,使用<Progress>组件创建时间进度条。设置progress属性为当前进度值(0-100),style属性可自定义样式。示例代码:

<Progress
    progress="30"
    style="width: 300px; height: 6px;"
    class="my-progress"/>

通过$element获取组件对象,调用setProgress()动态更新进度值。支持线性/环形样式,通过type属性切换。

在HarmonyOS Next中实现时间进度条,可以使用Slider组件结合自定义绘制来实现。以下是关键实现思路:

  1. 使用Slider作为基础控件,设置minValue=0,maxValue=86400(24小时对应的秒数)

  2. 自定义刻度绘制:

@Component
struct TimeSlider {
  @State currentTime: number = 0
  @State scaleLevel: number = 1 // 缩放级别

  build() {
    Slider({
      value: this.currentTime,
      min: 0,
      max: 86400,
      step: this.getStep(),
      style: SliderStyle.OutSet
    })
    .onChange(value => {
      this.currentTime = value
    })
    .trackThickness(20)
    .selectedColor(Color.Purple)
    .showSteps(true)
    .showTips(true)
  }

  // 根据缩放级别返回步长
  private getStep(): number {
    switch(this.scaleLevel) {
      case 1: return 600 // 10分钟
      case 2: return 60 // 1分钟
      case 3: return 1 // 1秒
      default: return 600
    }
  }
}
  1. 添加捏合手势识别:
.gesture(
  PinchGesture()
    .onActionStart(() => {
      // 处理缩放开始
    })
    .onActionUpdate((event: PinchGestureEvent) => {
      if(event.scale > 1.5) {
        this.scaleLevel = Math.min(this.scaleLevel + 1, 3)
      } else if(event.scale < 0.5) {
        this.scaleLevel = Math.max(this.scaleLevel - 1, 1)
      }
    })
)
  1. 时间显示可以使用Text组件实时更新:
Text(this.formatTime(this.currentTime))
  .fontSize(20)
  .fontColor(Color.Purple)

private formatTime(seconds: number): string {
  // 秒数转HH:mm:ss格式
}

注意:完整实现还需要处理手势冲突、刻度标签绘制等细节。建议参考HarmonyOS的Slider和Canvas组件文档进行扩展开发。

回到顶部