上次写过一次鸿蒙的音乐项目,不过是基于api9,最近幽蓝君把它完善优化,并适配到api 12,也就是最新的鸿蒙NEXT版本,供大家参考。
最近有友友反馈分享的代码过期了,幽蓝君今天进行了更新,有遗漏的大家可以私信。
先来看这次音乐播放器项目的效果图:
下面为大家详解一下这个项目。
探索发现
16140443_670f577beb59f81456.png
这是个简单的音乐列表页,从全局看,有导航栏说明要用Navigation组件,当然也可以自定义,导航栏部分还有个切换开关,可以使用menu实现:相关代码如下:
@Builder NavigationMenu(){
Row({space:10}){
Text('探索')
.fontColor(Color.Black)
.fontSize(15)
Row()
.width(1)
.height(18)
.backgroundColor(Color.Gray)
Text('推荐')
.fontColor(Color.Gray)
.fontSize(15)
}
.width('100%')
.justifyContent(FlexAlign.Center)
.height(50)
.alignItems(VerticalAlign.Center)
}
Navigation(){
//内容部分
}
.titleMode(NavigationTitleMode.Mini)
.hideBackButton(true)
.width('100%')
.height('100%')
.backgroundColor('rgba(245, 245, 245, 1)')
.menus(this.NavigationMenu())
TypeScript然后,内容部分显然使用List组件实现,可以看到它可以分为3部分,分别是搜索框、今日热歌和歌单遨游指南。前两个部分都比较简单,歌单遨游指南是可以左右滑动的,所以我使用网格组件Grid实现,设置rowsTemplate属性可以使Grid水平方向滑动,相关代码如下:
ListItemGroup({header:this.SectionHeader('歌单遨游指南',false)}){
ListItem(){
Grid(){
ForEach(this.albumList,(item:Album,index)=>{
GridItem(){
Column(){
Image(item.cover)
.width(150)
.height(150)
Text(item.title)
.fontColor(Color.Black)
.fontSize(15)
.fontWeight(FontWeight.Bold)
.margin({top:5})
.maxLines(2)
}
.alignItems(HorizontalAlign.Center)
.width(150)
.height(200)
}
})
}
.width('100%')
.rowsTemplate('1fr 1fr')
.rowsGap(12)
.columnsGap(10)
.padding({left:12})
.margin({top:5})
.scrollBarWidth(0)
}
.height(400)
}
TypeScript播放音乐页面
这个页面看起来很复杂,其实并不难。这里幽蓝君想说的是,布局无非三种方式,横向、竖向和层叠,其他的布局方式都由这三种衍生而来。
所以对于这个界面,只要把它拆分开来就会发现其实很容易:
有一点难度的地方就是中间的图片是旋转的,我们给他设置一个动态的角度,使用定时器控制图片旋转,代码如下:
Image($rawfile(this.musicList[this.currentIndex].cover))
.width(this.screenWidth - 50)
.height(this.screenWidth - 50)
.borderRadius((this.screenWidth - 50)/2)
.objectFit(ImageFit.Fill)
.rotate({ x: 0, y: 0, z: 1, angle: this.value*360 })
this.timer = setInterval(() => {
// 保留2位小数
this.value = this.value + 0.005
}, 30);
TypeScript还有一个地方要说一下,点击列表按钮会弹出一个音乐列表,这里使用bindsheet实现,难倒不难,就是有很多友友不知道这个东西:
相关代码如下:
Column(){
}
.bindSheet($this.showList, this.listPage(), {
height: 40 + (58 + 5)*this.musicList.length,
backgroundColor: Color.White,
showClose:false,
})
@Builder listPage(){
Column(){
Divider()
.width('100%')
.height(0.8)
.backgroundColor('rgb(226,226,226)')
List({space:0}){
ForEach(this.musicList,(item:Music,index)=>{
ListItem(){
Row(){
Column(){
Text(item.name)
.fontColor('#222628')
.fontSize(16)
}
.alignItems(HorizontalAlign.Start)
if(this.currentIndex == index && this.isPlay){
Image($r('app.media.list_pause'))
.width(28)
.height(28)
.onClick(()=>{
this.playOrPause()
})
}else{
Image($r('app.media.list_play'))
.width(28)
.height(28)
.onClick(()=>{
this.playSong(index)
})
}
}
.alignItems(VerticalAlign.Center)
.justifyContent(FlexAlign.SpaceBetween)
.width('100%')
.height(62)
}
})
}
.divider({strokeWidth:0.5,color:'rgb(236,236,236)'})
.padding({left:20,right:20})
}
.expandSafeArea([SafeAreaType.SYSTEM],[SafeAreaEdge.BOTTOM])
.alignItems(HorizontalAlign.Start)
.width('100%')
.backgroundColor(Color.White)
.borderRadius({topLeft:20,topRight:20})
.shadow({ radius: 30, color: 'rgba(230,230,230,0.7)', offsetX: 0, offsetY: -20 })
}
TypeScript播放音乐
这个项目中使用本地音乐文件,所以跟大家分享下播放本地的音频文件。首先把文件放到rawfile文件夹中,播放音乐的代码如下:
// 创建avPlayer实例对象
let avPlayer: media.AVPlayer = await media.createAVPlayer();
// 创建状态机变化回调函数
this.setAVPlayerCallback(avPlayer);
// 通过UIAbilityContext的resourceManager成员的getRawFd接口获取媒体资源播放地址
// 返回类型为{fd,offset,length},fd为HAP包fd地址,offset为媒体资源偏移量,length为播放长度
let context = getContext(this) as common.UIAbilityContext;
let fileDescriptor = await context.resourceManager.getRawFd(this.musicList[this.currentIndex].url);
let avFileDescriptor: media.AVFileDescriptor =
{ fd: fileDescriptor.fd, offset: fileDescriptor.offset, length: fileDescriptor.length };
this.isSeek = false; // 支持seek操作
// 为fdSrc赋值触发initialized状态机上报
avPlayer.fdSrc = avFileDescriptor;
this.avPlayer = avPlayer
TypeScript阅读全文
下载说明:
1、本站所有资源均从互联网上收集整理而来,仅供学习交流之用,因此不包含技术服务请大家谅解!
2、本站不提供任何实质性的付费和支付资源,所有需要积分下载的资源均为网站运营赞助费用或者线下劳务费用!
3、本站所有资源仅用于学习及研究使用,您必须在下载后的24小时内删除所下载资源,切勿用于商业用途,否则由此引发的法律纠纷及连带责任本站和发布者概不承担!
4、本站站内提供的所有可下载资源,本站保证未做任何负面改动(不包含修复bug和完善功能等正面优化或二次开发),但本站不保证资源的准确性、安全性和完整性,用户下载后自行斟酌,我们以交流学习为目的,并不是所有的源码都100%无错或无bug!如有链接无法下载、失效或广告,请联系客服处理!
5、本站资源除标明原创外均来自网络整理,版权归原作者或本站特约原创作者所有,如侵犯到您的合法权益,请立即告知本站,本站将及时予与删除并致以最深的歉意!
6、如果您也有好的资源或教程,您可以投稿发布,成功分享后有站币奖励和额外收入!
7、如果您喜欢该资源,请支持官方正版资源,以得到更好的正版服务!
8、请您认真阅读上述内容,注册本站用户或下载本站资源即您同意上述内容!
原文链接:https://www.shuli.cc/?p=21642,转载请注明出处。
1、本站所有资源均从互联网上收集整理而来,仅供学习交流之用,因此不包含技术服务请大家谅解!
2、本站不提供任何实质性的付费和支付资源,所有需要积分下载的资源均为网站运营赞助费用或者线下劳务费用!
3、本站所有资源仅用于学习及研究使用,您必须在下载后的24小时内删除所下载资源,切勿用于商业用途,否则由此引发的法律纠纷及连带责任本站和发布者概不承担!
4、本站站内提供的所有可下载资源,本站保证未做任何负面改动(不包含修复bug和完善功能等正面优化或二次开发),但本站不保证资源的准确性、安全性和完整性,用户下载后自行斟酌,我们以交流学习为目的,并不是所有的源码都100%无错或无bug!如有链接无法下载、失效或广告,请联系客服处理!
5、本站资源除标明原创外均来自网络整理,版权归原作者或本站特约原创作者所有,如侵犯到您的合法权益,请立即告知本站,本站将及时予与删除并致以最深的歉意!
6、如果您也有好的资源或教程,您可以投稿发布,成功分享后有站币奖励和额外收入!
7、如果您喜欢该资源,请支持官方正版资源,以得到更好的正版服务!
8、请您认真阅读上述内容,注册本站用户或下载本站资源即您同意上述内容!
原文链接:https://www.shuli.cc/?p=21642,转载请注明出处。
评论0