目录
2.musicPage中调用AvPlayerManager完成播放歌曲
1.封装播放对象管理类
封装一个播放对象,之后播放音乐直接调用该对象。
src/main/ets/services/AvPlayerManager.ets:
export interface songItemType {
img: string
name: string
author: string
url: string
id: string
}
//作用:负责管理播放对象的各种方法封装的
import media from '@ohos.multimedia.media'
//定义并导出播放对象管理类
export class AvPlayerManager {
static avPlayer: media.AVPlayer = Object()
// 1.0 封装初始化AvPlayer对象的方法
// init方法将来在ets页面的aboutToAppear方法中调用
static async init() {
// 创建实例对象并且保存到全局的静态变量中
AvPlayerManager.avPlayer = await media.createAVPlayer()
// 监听状态的改变
AvPlayerManager.avPlayer.on('stateChange', (state) => {
// 查看state的状态
console.log('mylog', '当前状态:', state)
// 准备播放
if (state == 'initialized') {
AvPlayerManager.avPlayer.prepare()
}
// 播放
if (state == 'prepared') {
AvPlayerManager.avPlayer.play()
}
})
}
// 2.0 设置播放源(并且要能够实现重置)
static async playMusic(music: songItemType) {
console.log('mylog,播放歌曲:', music.name, 'url=', music.url)
await AvPlayerManager.avPlayer.reset() //重置播放对象使其空闲
AvPlayerManager.avPlayer.url = music.url //给播放对象设置播放源
}
}
export class AvPlayerManager{}用来定义一个播放对象管理类;
static async init() {},用来封装初始化AvPlayer对象的方法, init方法将来在ets页面的aboutToAppear方法中调用;
实例对象 :AvPlayerManager.avPlayer,实例:AvPlayerManager.avPlayer.prepare()、AvPlayerManager.avPlayer.play();
2.musicPage中调用AvPlayerManager完成播放歌曲
src/main/ets/pages/muiscPage.ets:
import { AvPlayerManager, songItemType } from '../services/AvPlayerManager'
@Entry
@Component
export struct MuiscPage {
// 歌曲列表
@State songs: songItemType[] = [
{
img: 'http://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/0.jpg',
name: '直到世界的尽头',
author: 'WANDS',
url: 'http://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/0.m4a',
id: '0000'
},
{
img: 'http://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/1.jpg',
name: '画',
author: '赵磊',
url: 'http://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/1.mp3',
id: '0001'
},
{
img: 'http://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/2.jpg',
name: 'Sweet Dreams',
author: 'TPaul Sax / Eurythmics',
url: 'http://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/2.mp3',
id: '0002'
},
{
img: 'http://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/3.jpg',
name: '奢香夫人',
author: '凤凰传奇',
url: 'http://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/3.m4a',
id: '0003'
},
{
img: 'http://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/4.jpg',
name: '空心',
author: '光泽',
url: 'http://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/4.mp3',
id: '0004'
},
{
img: 'http://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/5.jpg',
name: '反转地球',
author: '潘玮柏',
url: 'http://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/5.mp3',
id: '0005'
},
{
img: 'http://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/6.jpg',
name: 'No.9',
author: 'T-ara',
url: 'http://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/6.m4a',
id: '0006'
},
{
img: 'http://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/7.jpg',
name: '孤独',
author: 'G.E.M.邓紫棋',
url: 'http://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/7.m4a',
id: '0007'
},
{
img: 'http://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/8.jpg',
name: 'Lose Control',
author: 'Hedley',
url: 'http://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/8.m4a',
id: '0008'
},
{
img: 'http://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/9.jpg',
name: '倩女幽魂',
author: '张国荣',
url: 'http://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/9.m4a',
id: '0009'
},
{
img: 'http://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/10.jpg',
name: '北京北京',
author: '汪峰',
url: 'http://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/10.m4a',
id: '0010'
},
{
img: 'http://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/11.jpg',
name: '苦笑',
author: '汪苏泷',
url: 'http://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/11.mp3',
id: '0011'
},
{
img: 'http://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/12.jpg',
name: '一生所爱',
author: '卢冠廷 / 莫文蔚',
url: 'http://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/12.m4a',
id: '0012'
},
{
img: 'http://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/13.jpg',
name: '月半小夜曲',
author: '李克勤',
url: 'http://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/13.mp3',
id: '0013'
},
{
img: 'http://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/14.jpg',
name: 'Rolling in the Deep',
author: 'Adele',
url: 'http://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/14.m4a',
id: '0014'
},
{
img: 'http://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/15.jpg',
name: '海阔天空',
author: 'Beyond',
url: 'http://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/15.m4a',
id: '0015'
}
]
async aboutToAppear() {
await AvPlayerManager.init()
}
build() {
Column() {
// 信息区域
Column({ space: 40 }) {
// 喜欢的音乐
Row({ space: 10 }) {
Column() {
Image($r('app.media.ic_favorite'))
.width(80)
.fillColor('#ff5286')
}
.justifyContent(FlexAlign.Center)
.width(100)
.height(100)
.backgroundColor(Color.White)
.borderRadius(10)
// 文字信息
Column({ space: 10 }) {
Text('我喜欢的音乐')
.fontColor(Color.White)
.width('100%')
.fontWeight(700)
Text('黑马程序员')
.fontColor('#ffb7b8ba')
.width('100%')
.fontSize(12)
}
}
.width('100%')
// 三个按钮
Row() {
Button({ type: ButtonType.Normal }) {
Row({ space: 10 }) {
Image($r('app.media.ic_share'))
.width(20)
.fillColor('#d2577c')
Text('分享').fontColor(Color.White)
.fontSize(12)
}
}
.backgroundColor('#ff363737')
.width(90)
.height(40)
.borderRadius(20)
Button({ type: ButtonType.Normal }) {
Row({ space: 10 }) {
Image($r('app.media.ic_comment'))
.width(20)
.fillColor('#d2577c')
Text('评论').fontColor(Color.White).fontSize(12)
}
}
.backgroundColor('#ff363737')
.width(90)
.height(40)
.borderRadius(20)
Button({ type: ButtonType.Normal }) {
Row({ space: 10 }) {
Image($r('app.media.ic_collect'))
.width(20)
.fillColor('#d2577c')
Text('收藏').fontColor(Color.White).fontSize(12)
}
}
.backgroundColor('#ff363737')
.width(90)
.height(40)
.borderRadius(20)
}
.width('100%')
.justifyContent(FlexAlign.SpaceBetween)
}
.padding({ top: 30, right: 20, bottom: 30, left: 20 })
.width('100%')
// .backgroundColor(Color.Pink)
.layoutWeight(1)
.radialGradient({
center: ['90%', '-10%'], // 设置中心点
radius: '150%', // 设置半径
colors: [ // 设置颜色的
['#5c4111', 0.2],
[Color.Transparent, 1] //Color.Transparent表示透明色
]
})
// 播放列表
Column() {
// 全部播放容器
Row({ space: 5 }) {
Image($r('app.media.ic_play'))
.width(15)
.fillColor('#d2577c')
Text('播放全部(16)')
.fontColor(Color.White)
.fontSize(12)
}
.width('100%')
.padding(10)
// 歌曲列表
List() {
ForEach(this.songs, (item: songItemType, index: number) => {
if (index < 3) {
// 每一首歌曲的信息布局(带图片)
ListItem() {
Row() {
// 如果是第0个,则显示黄色文字编号
if (index == 0) {
Text((index + 1).toString())
.fontColor(Color.Yellow)
.width(30)
.textAlign(TextAlign.Center)
}
// 如果是第1个,则显示红色文字编号
if (index == 1) {
Text((index + 1).toString())
.fontColor('#d2577c')
.width(30)
.textAlign(TextAlign.Center)
}
// 如果是第2个,则显示蓝色文字编号
if (index == 2) {
Text((index + 1).toString())
.fontColor('#0094ff')
.width(30)
.textAlign(TextAlign.Center)
}
Row({ space: 10 }) {
Image(item.img)
.width(30)
.borderRadius(5)
Column() {
Text(item.name)
.fontColor('#ff9fa0a1')
.fontSize(12)
.width('100%')
Text(item.author)
.fontColor('#ff9fa0a1')
.fontSize(10)
.width('100%')
}
}
.layoutWeight(1)
Image($r('app.media.ic_more'))
.fillColor(Color.White)
.width(15)
}
.width('100%')
.padding({ top: 8, bottom: 8 })
}
.onClick(() => {
// 用户点击就将此歌曲对象传入avplayerManager.playMusic()
AvPlayerManager.playMusic(item)
})
} else {
// 每一首歌曲的信息布局(不带图片)
ListItem() {
Row() {
Text((index + 1).toString())
.fontColor(Color.White)
.width(30)
.textAlign(TextAlign.Center)
Row({ space: 10 }) {
Column() {
Text(item.name)
.fontColor('#ff9fa0a1')
.fontSize(12)
.width('100%')
Text(item.author)
.fontColor('#ff9fa0a1')
.fontSize(10)
.width('100%')
}
}
.layoutWeight(1)
Image($r('app.media.ic_more'))
.fillColor(Color.White)
.width(15)
}
.width('100%')
.padding({ top: 8, bottom: 8 })
}
.onClick(() => {
// 用户点击就将此歌曲对象传入avplayerManager.playMusic()
AvPlayerManager.playMusic(item)
})
}
})
// 增加ListItem来防止最后一个歌曲看不到的问题
ListItem() {
Text('已经到低了~~~~')
.fontColor(Color.White)
.width('100%')
.textAlign(TextAlign.Center)
}
.height(60)
.padding({ bottom: 40 })
}
}
.width('100%')
.backgroundColor('#ff333333')
.layoutWeight(2)
.borderRadius({ topLeft: 10, topRight: 10 })
}
.height('100%')
.width('100%')
.backgroundColor(Color.Black)
}
}
新增:
async aboutToAppear() {
await AvPlayerManager.init()
}
表示一进入该页面就触发调用AvPlayerManager.init()方法,实现播放歌曲。
.onClick(() => {
// 用户点击就将此歌曲对象传入avplayerManager.playMusic()
AvPlayerManager.playMusic(item)
})
List() {}容器增加onclick属性,表示点击后触发大括号内的函数;将item: songItemType, index: number传给AvPlayerManager.playMusic,而AvPlayerManager.playMusic代码如下:
// 2.0 设置播放源(并且要能够实现重置)
static async playMusic(music: songItemType) {
console.log('mylog,播放歌曲:', music.name, 'url=', music.url)
await AvPlayerManager.avPlayer.reset() //重置播放对象使其空闲
AvPlayerManager.avPlayer.url = music.url //给播放对象设置播放源
}
}
表示能更新歌曲的信息,实现切换歌曲的功能。
3.index.ets的播放信息样式
播放栏图片样式如下:
src/main/ets/pages/Index.ets:
import { FindPage } from './FindPage'
import { MimePage } from './mimePage'
import { MomentPage } from './momentPage'
import { MuiscPage } from './muiscPage'
import { RecommendPage } from './recommendPage'
@Entry
@Component
struct Index {
@State currentIndex: number = 0 //页面加载的时候就应该把第一个tab点亮
aboutToAppear() {
console.log('mylog', 'index页面执行了日志打印')
}
@Builder
tabBuilder(text: string, img: Resource, index: number) {
// 三元表达式
// 条件成立?取值1:取值2
Column({ space: 5 }) {
Image(img)
.width(25)
.borderRadius(25)
.backgroundColor(this.currentIndex == index ? '#d2577c' : '')
.padding(2)
.fillColor(this.currentIndex == index ? Color.White : '#4bb0c4')
Text(text)
.fontColor(this.currentIndex == index ? '#d2577c' : '#4bb0c4')
}
}
build() {
Stack({ alignContent: Alignment.Bottom }) {
// 底部导航栏
Tabs({ barPosition: BarPosition.End }) {
TabContent() {
RecommendPage()
}
.tabBar(this.tabBuilder('推荐', $r('app.media.ic_recommend'), 0))
.backgroundColor(Color.Black)
TabContent() {
FindPage()
}
.tabBar(this.tabBuilder('发现', $r('app.media.ic_find'), 1))
.backgroundColor(Color.Black)
TabContent() {
MuiscPage()
}
.tabBar(this.tabBuilder('muisc', $r('app.media.ic_logo'), 2))
.backgroundColor(Color.Black)
TabContent() {
MomentPage()
}
.tabBar(this.tabBuilder('动态', $r('app.media.ic_moment'), 3))
.backgroundColor(Color.Black)
TabContent() {
MimePage()
}
.tabBar(this.tabBuilder('我的', $r('app.media.ic_mine'), 4))
.backgroundColor(Color.Black)
}
.onChange((index: number) => {
console.log('当前索引', index)
this.currentIndex = index
})
.backgroundColor('#ff3b3b3b')
// 播放歌曲信息后面完成
Row() {
Row({ space: 10 }) {
Image('http://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/0.jpg')
.height(50)
Column() {
Text('直到世界的尽头')
.width('100%')
.fontColor(Color.White)
Text('WANDS')
.width('100%')
.fontColor(Color.White)
.fontSize(12)
}
}
.padding({ left: 10 })
.layoutWeight(2)
.height('100%')
Row() {
Image($r('app.media.ic_prev'))
.height(25)
.fillColor('#4bb0c4')
Image($r('app.media.ic_play'))
.height(25)
.fillColor('#4bb0c4')
Image($r('app.media.ic_paused'))
.height(25)
.fillColor('#4bb0c4')
Image($r('app.media.ic_next'))
.height(25)
.fillColor('#4bb0c4')
}
.justifyContent(FlexAlign.SpaceBetween)
.layoutWeight(1)
.height('100%')
}
.backgroundColor(Color.Black)
.height(60)
.margin({ bottom: 60 })
}
.height('100%')
.backgroundColor(Color.Black)
}
}
简单的静态结构布局,不再赘述。
4.musicPage向index传数据
实现将music页面的歌曲信息传入index页面的播放栏里。
src/main/ets/services/AvPlayerManager.ets:
// 3. 0负责使用emitter发送数据的
static sendMusicData(music: songItemType) {
/*
* {
img: 'http://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/0.jpg',
name: '直到世界的尽头',
author: 'WANDS',
url: 'http://yjy-teach-oss.oss-cn-beijing.aliyuncs.com/HeimaCloudMusic/0.m4a',
id: '0000'
}
* */
// 注意点:emitter只能传字符串格式的数据,所以我们需要JSON.stringify(music)转成json字符串
emitter.emit({ eventId: 0 }, { data: { item: JSON.stringify(music) } })
}
src/main/ets/pages/muiscPage.ets:
ForEach(this.songs, (item: songItemType, index: number) => {
if (index < 3) {
// 每一首歌曲的信息布局(带图片)
ListItem() {
Row() {
// 如果是第0个,则显示黄色文字编号
if (index == 0) {
Text((index + 1).toString())
.fontColor(Color.Yellow)
.width(30)
.textAlign(TextAlign.Center)
}
// 如果是第1个,则显示红色文字编号
if (index == 1) {
Text((index + 1).toString())
.fontColor('#d2577c')
.width(30)
.textAlign(TextAlign.Center)
}
// 如果是第2个,则显示蓝色文字编号
if (index == 2) {
Text((index + 1).toString())
.fontColor('#0094ff')
.width(30)
.textAlign(TextAlign.Center)
}
Row({ space: 10 }) {
Image(item.img)
.width(30)
.borderRadius(5)
Column() {
Text(item.name)
.fontColor('#ff9fa0a1')
.fontSize(12)
.width('100%')
Text(item.author)
.fontColor('#ff9fa0a1')
.fontSize(10)
.width('100%')
}
}
.layoutWeight(1)
Image($r('app.media.ic_more'))
.fillColor(Color.White)
.width(15)
}
.width('100%')
.padding({ top: 8, bottom: 8 })
}
.onClick(() => {
// 用户点击就将此歌曲对象传入avplayerManager.playMusic()
AvPlayerManager.playMusic(item)
// 同步数据
AvPlayerManager.sendMusicData(item)
})
} else {
// 每一首歌曲的信息布局(不带图片)
ListItem() {
Row() {
Text((index + 1).toString())
.fontColor(Color.White)
.width(30)
.textAlign(TextAlign.Center)
Row({ space: 10 }) {
Column() {
Text(item.name)
.fontColor('#ff9fa0a1')
.fontSize(12)
.width('100%')
Text(item.author)
.fontColor('#ff9fa0a1')
.fontSize(10)
.width('100%')
}
}
.layoutWeight(1)
Image($r('app.media.ic_more'))
.fillColor(Color.White)
.width(15)
}
.width('100%')
.padding({ top: 8, bottom: 8 })
}
.onClick(() => {
// 用户点击就将此歌曲对象传入avplayerManager.playMusic()
AvPlayerManager.playMusic(item)
// 同步数据
AvPlayerManager.sendMusicData(item)
})
}
})
src/main/ets/pages/Index.ets:
import { FindPage } from './FindPage'
import { MimePage } from './mimePage'
import { MomentPage } from './momentPage'
import { MuiscPage } from './muiscPage'
import { RecommendPage } from './recommendPage'
import emitter from '@ohos.events.emitter'
@Entry
@Component
struct Index {
@State currentIndex: number = 0 //页面加载的时候就应该把第一个tab点亮
@State img: string = ''
@State name: string = ''
@State author: string = ''
aboutToAppear() {
emitter.on({ eventId: 0 }, (rec) => {
console.log('mylog->', JSON.stringify(rec.data['item']))
// rec.data['item'] -> 获取到的是music这个对象的字符串形式(JSON)
let obj = JSON.parse(rec.data['item']) //将json字符串转成对象
this.img = obj['img']
this.name = obj['name']
this.author =obj['author']
})
}
@Builder
tabBuilder(text: string, img: Resource, index: number) {
// 三元表达式实现切换歌曲,该歌曲变颜色
// 条件成立?取值1:取值2
Column({ space: 5 }) {
Image(img)
.width(25)
.borderRadius(25)
.backgroundColor(this.currentIndex == index ? '#d2577c' : '')
.padding(2)
.fillColor(this.currentIndex == index ? Color.White : '#4bb0c4')
Text(text)
.fontColor(this.currentIndex == index ? '#d2577c' : '#4bb0c4')
}
}
build() {
Stack({ alignContent: Alignment.Bottom }) {
// 底部导航栏
Tabs({ barPosition: BarPosition.End }) {
TabContent() {
RecommendPage()
}
.tabBar(this.tabBuilder('推荐', $r('app.media.ic_recommend'), 0))
.backgroundColor(Color.Black)
TabContent() {
FindPage()
}
.tabBar(this.tabBuilder('发现', $r('app.media.ic_find'), 1))
.backgroundColor(Color.Black)
TabContent() {
MuiscPage()
}
.tabBar(this.tabBuilder('muisc', $r('app.media.ic_logo'), 2))
.backgroundColor(Color.Black)
TabContent() {
MomentPage()
}
.tabBar(this.tabBuilder('动态', $r('app.media.ic_moment'), 3))
.backgroundColor(Color.Black)
TabContent() {
MimePage()
}
.tabBar(this.tabBuilder('我的', $r('app.media.ic_mine'), 4))
.backgroundColor(Color.Black)
}
.onChange((index: number) => {
console.log('当前索引', index)
this.currentIndex = index
})
.backgroundColor('#ff3b3b3b')
// 播放歌曲信息后面完成
Row() {
Row({ space: 10 }) {
Image(this.img)
.height(50)
Column() {
Text(this.name)
.width('100%')
.fontColor(Color.White)
Text(this.author)
.width('100%')
.fontColor(Color.White)
.fontSize(12)
}
}
.padding({ left: 10 })
.layoutWeight(2)
.height('100%')
Row() {
Image($r('app.media.ic_prev'))
.height(25)
.fillColor('#4bb0c4')
Image($r('app.media.ic_play'))
.height(25)
.fillColor('#4bb0c4')
Image($r('app.media.ic_paused'))
.height(25)
.fillColor('#4bb0c4')
Image($r('app.media.ic_next'))
.height(25)
.fillColor('#4bb0c4')
}
.justifyContent(FlexAlign.SpaceBetween)
.layoutWeight(1)
.height('100%')
}
.backgroundColor(Color.Black)
.height(60)
.margin({ bottom: 55 })
}
.height('100%')
.backgroundColor(Color.Black)
}
}
主要还是增加MusicPage页面的:
// 同步数据
AvPlayerManager.sendMusicData(item)
用户点击就将此歌曲对象传入avplayerManager.playMusic()。
然后Index页面接收传入的数据。
@State img: string = ''
@State name: string = ''
@State author: string = ''
aboutToAppear() {
emitter.on({ eventId: 0 }, (rec) => {
console.log('mylog->', JSON.stringify(rec.data['item']))
// rec.data['item'] -> 获取到的是music这个对象的字符串形式(JSON)
let obj = JSON.parse(rec.data['item']) //将json字符串转成对象
this.img = obj['img']
this.name = obj['name']
this.author =obj['author']
})
}