Flutter仿网易云音乐:播放界面
写在前头
本来是要做一个仿网易云音乐的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仿网易云音乐:播放界面的更多相关文章
- 2.Android高仿网易云音乐-引导界面和广告界面实现
效果图 效果图依次为图片广告,视频广告,引导界面. 系列文章目录导航 目录 1.实现分析 广告界面就是显示图片和视频,所以可以放一个图片控件,视频控件,然后跳过按钮,提示按钮,WiFi预加载提示都是放 ...
- Android高仿网易云音乐-启动界面实现和动态权限处理
效果 实现分析 基本上没有什么难点,就是布局,然后显示用户协议对话框,动态处理权限,判断是否显示引导界面,是否显示广告界面等. 布局 <?xml version="1.0" ...
- 《云阅》一个仿网易云音乐UI,使用Gank.Io及豆瓣Api开发的开源项目
CloudReader 一款基于网易云音乐UI,使用GankIo及豆瓣api开发的符合Google Material Desgin阅读类的开源项目.项目采取的是Retrofit + RxJava + ...
- C# WPF 低仿网易云音乐(PC)歌词控件
原文:C# WPF 低仿网易云音乐(PC)歌词控件 提醒:本篇博客记录了修改的过程,废话比较多,需要项目源码和看演示效果的直接拉到文章最底部~ 网易云音乐获取歌词的api地址 http://music ...
- C# WPF 低仿网易云音乐(PC)Banner动画控件
原文:C# WPF 低仿网易云音乐(PC)Banner动画控件 由于技术有限没能做到一模一样的动画,只是粗略地做了一下.动画有点生硬,还有就是没做出网易云音乐的立体感.代码非常简单粗暴,而且我也写有很 ...
- iOS 开发仿网易云音乐歌词海报
使用网易云音乐也是一个巧合,我之前一直使用QQ音乐听歌,前几天下 app 手机内存告急.于是就把QQ音乐给卸载掉了,正好晚上朋友圈里有一个朋友用网易云音乐分享了一首歌曲,于是我也就尝试下载了网易云音乐 ...
- 新鲜出炉高仿网易云音乐 APP
我的引语 晚上好,我是吴小龙同学,我的公众号「一分钟GitHub」会推荐 GitHub 上好玩的项目,一分钟 get 一个优秀的开源项目,挖掘开源的价值,欢迎关注我. 项目中成长是最快的,如何成长,就 ...
- android仿网易云音乐引导页、仿书旗小说Flutter版、ViewPager切换、爆炸菜单、风扇叶片效果等源码
Android精选源码 复现网易云音乐引导页效果 高仿书旗小说 Flutter版,支持iOS.Android Android Srt和Ass字幕解析器 Material Design ViewPage ...
- WPF仿网易云音乐系列(序)
1.简介 由于之前做了一个播放器,苦于不懂界面设计,只得去借鉴借鉴一些成功的作品,网易云音乐就甚合朕心,哈哈,最后做出来的效果如下: 本系列文章就来和大家讨论以下,如何用WPF去仿制一个网易云音乐来: ...
随机推荐
- Shell:Day04.笔记
grep与正则表达式: 1.grep程序 Linux下有文本处理三剑客 - - grep sed awk grep:文本 行 过滤工具 sed:文本 行 编辑器(流编辑器) awk:报告生成器(做文本 ...
- web日志分析的重要性
虽然不可能对庞大的日志文件进行逐条的阅读,但是在这些日志文件中,确实会包含一些非常重要的信息.例如,在什么时间.有哪些ip地址访问了网站中的什么资源,等等. 通过对日志文件的分析,可以获得如下信息. ...
- 批处理 bat 查询局域网内在线电脑IP
查看自己局域网的IP和物理网卡地址可以在 WIN+R –> 打开cmd 键入 arp -a 可以看到局域网中所有的在线IP COLOR 0A CLS @ECHO Off Title 查询局域网内 ...
- 文件的读写 - open
#写文件,r路径\n 空格\t 缩进# fan=open(r'C:/Users/demiyangping_v/Desktop/fan.txt','w', encoding='utf-8')# fan. ...
- Array(数组)对象-->数组的删除
1.数组的删除: 用delete操作符删除特定的元素 删除元素的位置只是被留空了,为undefined值 举例:删除下面数组中的第二个元素 var arr = [1,2,3,4,5]; /*删除第二个 ...
- HTML5实现刷脸支付
最近刷脸支付很火,老板们当然要追赶时代潮流,于是就有了刷脸支付这个项目.前端实现关键的技术是摄像头录像,拍照和人脸比对,本文来探讨一下如何在html5环境中如何实现刷脸支付以及开发过程中遇到的问题. ...
- Python Requests-学习笔记(3)-处理json
JSON响应内容 Requests中也有一个内置的JSON解码器,助你处理JSON数据: r = requests.get('https://github.com/timeline.json') pr ...
- BMI的Python实现
str1 = float(input('请输入您的身高(单位:米):')) # input默认转化为字符串型 用float转化为浮点型 str2 = float(input('请输入您的体重(单位:千 ...
- 小程序wepy2 模拟vant PasswordInput, NumberKeyboard 密码输入框控件
vant weapp小程序端控件目前是没有PasswordInput,NumberKeyboard的.实现效果: 数字键盘组件代码(keyboard.wpy): <template> &l ...
- curl 交叉编译 支持http2和openssl
touch run.sh chmod 755 run.sh mkdir build cd build ../run.sh run.sh #!/bin/bash #cd /build ../config ...