内容简介:本来是要做一个仿网易云音乐的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播放多媒体
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
数据结构、算法与应用
(美)Sartaj Sahni / 汪诗林、孙晓东、等 / 机械工业出版社 / 2000-01 / 49.00
本书是关于计算机科学与工程领域的基础性研究科目之一――数据结构与算法的专著。 本书在简要回顾了基本的C++ 程序设计概念的基础上,全面系统地介绍了队列、堆栈、树、图等基本数据结构,以及贪婪算法、分而治之算法、分枝定界算法等多种算法设计方法,为数据结构与算法的继续学习和研究奠定了一个坚实的基础。更为可贵的是,本书不仅仅介绍了理论知识,还提供了50多个应用实例及600多道练习题。 本书......一起来看看 《数据结构、算法与应用》 这本书的介绍吧!