完成基本的 ui 布局

@Entry
@ComponentV2
struct Index {
build() {
Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
Column() {
Row() {
Image($r('app.media.audio'))
.height(50)
.width(50)
.borderRadius(50)
Column() {
Text("lemonmusicstudio")
.fontSize(16)
Text("Inside You")
.fontSize(14)
.opacity(0.7)
}
.alignItems(HorizontalAlign.Start)
.width('100%')
.margin({left:10})
}

        Row() {
          // SymbolGlyph($r('sys.symbol.play'))
          SymbolGlyph($r('sys.symbol.pause'))
            .borderRadius('50%')
            .backgroundColor(Color.White)
            .padding(10)
            .fontSize(35)
            .opacity(0.7)
        }
        .margin({ top: 10, bottom: 10 })

        Column() {
          Slider()
          Row() {
            Text("0:00")
            Text("0:00")
          }
          .width('100%')
          .padding({ left: 13, right: 13 })
          .justifyContent(FlexAlign.SpaceBetween)
        }
      }
      .width('80%')
      .padding(40)
      .borderRadius(20)
      .shadow({radius:20,color:Color.Black})
      .backgroundColor("#99EA7D")
    }
    .height('100%')
    .width('100%')

}
}

制作播放与暂停的切换功能

// 加入变量是否播放音乐
  @Local isPlay:boolean = false
  // 切换动效果
  @Local changeNumber:number = 1

// 根据变量判断图标
SymbolGlyph(this.isPlay ? $r("sys.symbol.play") : $r("sys.symbol.pause"))
  .borderRadius("50%")
  .backgroundColor(Color.White)
  .padding(10)
  .fontSize(35)
  .opacity(0.7)
  // 加入切换动效果
  .symbolEffect(new ReplaceSymbolEffect(), this.changeNumber)
  // 加入点击时间 切换是否播放
  .onClick(() => {
    this.isPlay = !this.isPlay;
    this.changeNumber += 1;
  });

加入音乐媒体

// 应用上下文
  private context:common.UIAbilityContext = this.getUIContext().getHostContext() as common.UIAbilityContext
  private player:media.AVPlayer|null = null
  // 读取本地的媒体资源 媒体资源在rawfile/media.mp3
  readFile(path:string){
    // 获取resourceManager
    const resource = this.context.resourceManager
    const file = resource.getRawFdSync(path)
    return file
  }
  // 异步等待创建媒体 加载媒体资源 初始化
  async init(){
    this.player =await media.createAVPlayer()
    const playerSource:media.AVFileDescriptor = this.readFile("media.mp3")
    this.player.fdSrc = playerSource
    this.player.on('stateChange',(state)=>{
      if(state == 'initialized'){
        this.player?.prepare()
      }
    })
  }
  // 在aboutToAppear生命周期中执行 init方法
  async aboutToAppear() {
    await this.init()
  }

实现点击播放 修改代码;

SymbolGlyph(this.isPlay ? $r("sys.symbol.pause") : $r("sys.symbol.play"))
  .borderRadius("50%")
  .backgroundColor(Color.White)
  .padding(10)
  .fontSize(35)
  .opacity(0.7)
  // 加入切换动效果
  .symbolEffect(new ReplaceSymbolEffect(), this.changeNumber)
  // 加入点击时间 切换是否播放
  .onClick(() => {
    this.isPlay = !this.isPlay;
    this.changeNumber += 1;
    if (this.isPlay) {
      this.player?.play();
    } else {
      this.player?.pause();
    }
  });

制作时间控件

   // 音乐的总时长
  @Local duration:string = '0:00'
  // 当前播放的时间
  @Local currentTime:string = '0:00'

// 获取两个时间
 // 在aboutToAppear生命周期中执行 init方法
  async aboutToAppear() {
    await this.init()
    setInterval(()=>{
      this.duration = this.formatTime(this.player!.duration)
      this.currentTime = this.formatTime(this.player!.currentTime)
    },1000)
  }

  // 将毫秒转化为x:xx的格式
  formatTime(time:number){
    const second = Math.round(time / 1000)
    const min = Math.floor(second/60)
    const sec = second - min * 60
    if(sec < 10){
      return `${min}:0${sec}`
    }else{
      return `${min}:${sec}`
    }
  }

滚动条

 // 滚动条的最大值
  @Local Max:number = 0

   // 在aboutToAppear生命周期中执行 init方法
  async aboutToAppear() {
    await this.init()
    setInterval(()=>{
      this.duration = this.formatTime(this.player!.duration)
      this.currentTime = this.formatTime(this.player!.currentTime)
      this.Max = this.player!.duration
    },1000)
  }

  Slider({
        min:0,
        max:this.Max,
        value:this.player?.currentTime
      })
        .onChange((time:number)=>{
          this.player?.seek(time)
        })

完整代码

import { media } from '@kit.MediaKit'
import { common } from '@kit.AbilityKit'

@Entry
@ComponentV2
struct Index {
  // 加入变量是否播放音乐
  @Local isPlay:boolean = false
  // 切换动效果
  @Local changeNumber:number = 1


  // 音乐的总时长
  @Local duration:string = '0:00'
  // 当前播放的时间
  @Local currentTime:string = '0:00'
  // 滚动条的最大值
  @Local Max:number = 0


  // 应用上下文
  private context:common.UIAbilityContext = this.getUIContext().getHostContext() as common.UIAbilityContext
  private player:media.AVPlayer|null = null
  // 读取本地的媒体资源 媒体资源在rawfile/media.mp3
  readFile(path:string){
    // 获取resourceManager
    const resource = this.context.resourceManager
    const file = resource.getRawFdSync(path)
    return file
  }
  // 异步等待创建媒体 加载媒体资源 初始化
  async init(){
    this.player =await media.createAVPlayer()
    const playerSource:media.AVFileDescriptor = this.readFile("media.mp3")
    this.player.fdSrc = playerSource
    this.player.on('stateChange',(state)=>{
      if(state == 'initialized'){
        this.player?.prepare()
      }
    })
  }
  // 在aboutToAppear生命周期中执行 init方法
  async aboutToAppear() {
    await this.init()
    setInterval(()=>{
      this.duration = this.formatTime(this.player!.duration)
      this.currentTime = this.formatTime(this.player!.currentTime)
      this.Max = this.player!.duration
    },1000)
  }

  // 将毫秒转化为x:xx的格式
  formatTime(time:number){
    const second = Math.round(time / 1000)
    const min = Math.floor(second/60)
    const sec = second - min * 60
    if(sec < 10){
      return `${min}:0${sec}`
    }else{
      return `${min}:${sec}`
    }
  }

  build() {
    Flex({ justifyContent: FlexAlign.Center, alignItems: ItemAlign.Center }) {
      Column() {
        Row() {
          Image($r('app.media.audio'))
            .height(50)
            .width(50)
            .borderRadius(50)
          Column() {
            Text("lemonmusicstudio")
              .fontSize(16)
            Text("Inside You")
              .fontSize(14)
              .opacity(0.7)
          }
          .alignItems(HorizontalAlign.Start)
          .width('100%')
          .margin({left:10})
        }

        Row() {
          // 根据变量判断图标
          SymbolGlyph(this.isPlay?$r('sys.symbol.pause'):$r('sys.symbol.play'))
            .borderRadius('50%')
            .backgroundColor(Color.White)
            .padding(10)
            .fontSize(35)
            .opacity(0.7)
            // 加入切换动效果
            .symbolEffect(new ReplaceSymbolEffect(),this.changeNumber)
            // 加入点击时间 切换是否播放
            .onClick(()=>{
              this.isPlay = !this.isPlay
              this.changeNumber += 1
              if(this.isPlay){
                this.player?.play()
              }else{
                this.player?.pause()
              }
            })
        }
        .margin({ top: 10, bottom: 10 })

        Column() {
            Slider({
              min:0,
              max:this.Max,
              value:this.player?.currentTime
            })
              .onChange((time:number)=>{
                this.player?.seek(time)
              })

          Row() {
            Text(this.currentTime)
            Text(this.duration)
          }
          .width('100%')
          .padding({ left: 13, right: 13 })
          .justifyContent(FlexAlign.SpaceBetween)
        }
      }
      .width('80%')
      .padding(40)
      .borderRadius(20)
      .shadow({radius:20,color:Color.Black})
      .backgroundColor("#99EA7D")
    }
    .height('100%')
    .width('100%')
  }
}
Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐