鸿蒙开发:实现一个简易的音乐播放器
·
完成基本的 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%')
}
}
更多推荐
所有评论(0)