内容简介:本来是要做一个仿网易云音乐的flutter项目,但是因为最近事情比较多,项目周期跨度会比较长,因此分几个步骤来完成。这是仿网易云音乐项目系列文章的第一篇。没有完全照搬网易云音乐的UI,借鉴了其中的黑胶唱机动画。先贴上项目地址这个界面实现起来其实是比较简单的,大致分为如下几个部分:
本来是要做一个仿网易云音乐的flutter项目,但是因为最近事情比较多,项目周期跨度会比较长,因此分几个步骤来完成。这是仿网易云音乐项目系列文章的第一篇。没有完全照搬网易云音乐的UI,借鉴了其中的黑胶唱机动画。
先贴上项目地址 github.com/KinsomyJS/f…
初步效果图
思路
这个界面实现起来其实是比较简单的,大致分为如下几个部分:
- 1.背景的高斯模糊效果
- 2.黑胶唱头的旋转动画
- 3.黑胶唱片的旋转动画
- 4.下部控制器和进度条部分
我们一个个来说实现过程。
实践
整个界面是一个堆叠视图,最下面是一个背景图片,上面覆盖一层高斯模糊半透明遮罩,再上层是title,黑胶唱机和控制器。
1. 背景高斯模糊
首先使用stack组件用来包裹堆叠视图,在里面有两个container,第一个是背景网络图片,第二个就是一个 BackdropFilter
。
Stack( children: <Widget>[ new Container( decoration: new BoxDecoration( image: new DecorationImage( image: new NetworkImage(coverArt), fit: BoxFit.cover, colorFilter: new ColorFilter.mode( Colors.black54, BlendMode.overlay, ), ), ), ), new Container( child: new BackdropFilter( filter: ImageFilter.blur(sigmaX: 10.0, sigmaY: 10.0), child: Opacity( opacity: 0.6, child: new Container( decoration: new BoxDecoration( color: Colors.grey.shade900, ), ), ), )), ... ] 复制代码
这里的高斯模糊sigmaX和sigmaY的值选择了10,然后透明度为0.6,颜色为grey.shade900。
2.黑胶唱头的旋转动画
关于动画的知识这里就不做详细介绍了,可以参考官方文档传送门
自定义动画组件在 needle_anim.dart
文件里。 这里将动画和组件解耦,分别定义了动画过程类 PivotTransition
,顾名思义围绕一个支点旋转,继承自 AnimatedWidget
。
支点定在child组件的topcenter位置。 注意turns不能为空,需要根据turns的值计算旋转绕过的周长,围绕Z轴旋转。
class PivotTransition extends AnimatedWidget { /// 创建旋转变换 /// turns不能为空. PivotTransition({ Key key, this.alignment: FractionalOffset.topCenter, @required Animation<double> turns, this.child, }) : super(key: key, listenable: turns); /// The animation that controls the rotation of the child. /// If the current value of the turns animation is v, the child will be /// rotated v * 2 * pi radians before being painted. Animation<double> get turns => listenable; /// The pivot point to rotate around. final FractionalOffset alignment; /// The widget below this widget in the tree. final Widget child; @override Widget build(BuildContext context) { final double turnsValue = turns.value; final Matrix4 transform = new Matrix4.rotationZ(turnsValue * pi * 2.0); return new Transform( transform: transform, alignment: alignment, child: child, ); } } 复制代码
接下来就是自定义黑胶唱头组件。
final _rotateTween = new Tween<double>(begin: -0.15, end: 0.0); new Container( child: new PivotTransition( turns: _rotateTween.animate(controller_needle), alignment: FractionalOffset.topLeft, child: new Container( width: 100.0, child: new Image.asset("images/play_needle.png"), ), ), ), 复制代码
将png图片包裹在container内作为child参数传递给 PivotTransition
。
外部使用的时候传入一个Tween,起始位置为-0.15 ~ 0.0。
3.黑胶唱片的旋转动画
这部分代码在 record_anim.dart
文件内。使用了 package:flutter/animation.dart
提供的 RotationTransition
做旋转,很简单。
class RotateRecord extends AnimatedWidget { RotateRecord({Key key, Animation<double> animation}) : super(key: key, listenable: animation); Widget build(BuildContext context) { final Animation<double> animation = listenable; return new Container( margin: new EdgeInsets.symmetric(vertical: 10.0), height: 250.0, width: 250.0, child: new RotationTransition( turns: animation, child: new Container( decoration: BoxDecoration( shape: BoxShape.circle, image: DecorationImage( image: NetworkImage( "https://images-na.ssl-images-amazon.com/images/I/51inO4DBH0L._SS500.jpg"), ), ), )), ); } } 复制代码
接着自定义旋转动画的控制逻辑。旋转一圈用时十五秒钟,速度为线性匀速,同时会重复旋转动画。
controller_record = new AnimationController( duration: const Duration(milliseconds: 15000), vsync: this); animation_record = new CurvedAnimation(parent: controller_record, curve: Curves.linear); animation_record.addStatusListener((status) { if (status == AnimationStatus.completed) { controller_record.repeat(); } else if (status == AnimationStatus.dismissed) { controller_record.forward(); } }); 复制代码
4.下部控制器和进度条部分
播放流媒体音频使用了三方组件 audioplayers
,具体代码在 player_page.dart
文件内,封装了一个player组件,接受了一系列参数包括音频路径,播放操作回调等。该组件支持本地资源和网络资源,这里用网络音频资源做demo。
const Player( {@required this.audioUrl, @required this.onCompleted, @required this.onError, @required this.onNext, @required this.onPrevious, this.key, this.volume: 1.0, this.onPlaying, this.color: Colors.white, this.isLocal: false}); 复制代码
在initState方法里初始化 AudioPlayer
对象。".."是dart的级联操作符。
audioPlayer = new AudioPlayer(); audioPlayer ..completionHandler = widget.onCompleted ..errorHandler = widget.onError ..durationHandler = ((duration) { setState(() { this.duration = duration; if (position != null) { this.sliderValue = (position.inSeconds / duration.inSeconds); } }); }) ..positionHandler = ((position) { setState(() { this.position = position; if (duration != null) { this.sliderValue = (position.inSeconds / duration.inSeconds); } }); }); 复制代码
开始播放代码
audioPlayer.play( widget.audioUrl, isLocal: widget.isLocal, volume: widget.volume, ); 复制代码
开始播放后, durationHandler
会回调音频总时长, positionHandler
会回调播放进度,两个回调都返回一个 Duration
对象。根据这两个duration对象可以计算机播放进度的百分比,这里使用 Slider
组件做进度条。
new Slider( onChanged: (newValue) { if (duration != null) { int seconds = (duration.inSeconds * newValue).round(); print("audioPlayer.seek: $seconds"); audioPlayer.seek(new Duration(seconds: seconds)); } }, value: sliderValue ?? 0.0, activeColor: widget.color, ), 复制代码
总结
整体实现是非常简单的,只要对flutter的组件有所了解就能很快写出来,后面还会加入歌词滚动功能来丰富界面。
具体项目可以到 github.com/KinsomyJS/f… 查看,也欢迎star持续关注。
参考资料
以上所述就是小编给大家介绍的《Flutter仿网易云音乐:播放界面》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 跨平台多媒体播放器 VLC 4.0 将引入新的用户界面
- Python 播放音乐:使用 mido 编写,播放多声轨 MIDI 文件音乐
- Lotus 云盘 2.2 发布,增加视频转码及在线播放、MP3 播放功能
- CentOS 图形界面和字符界面切换
- 播放器性能优化之路
- Java播放多媒体
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Tales from Facebook
Daniel Miller / Polity Press / 2011-4-1 / GBP 55.00
Facebook is now used by nearly 500 million people throughout the world, many of whom spend several hours a day on this site. Once the preserve of youth, the largest increase in usage today is amongst ......一起来看看 《Tales from Facebook》 这本书的介绍吧!
XML 在线格式化
在线 XML 格式化压缩工具
Markdown 在线编辑器
Markdown 在线编辑器