脚本宝典收集整理的这篇文章主要介绍了女朋友想要听歌,我反手用Flutter做了2个音乐播放器,给她拿捏了,脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。
源码在文章最后,是兄弟就来运行看看
有和我一样喜欢Jay的嘛
使用的插件:
assets_audio_player: ^2.0.14 //用于音乐的播放
flutter_swiper: any //用于第一张效果图的左右切换效果,如果只要实现第二张的话就不需要啦~
文章只展示重要代码,完整源码在文章的最后
当点击播放时,将多个不同颜色的椭圆形堆叠在一起,然后进行旋转。
1.创建一个无状态的背景椭圆形
2.使用将多个背景圆形存放于Stack中,以及点击处理
3.添加缩放和旋转动画AnimationController来控制背景圆形
double _rotation = 0;
double _scale = 0.85;
封装处理一下:
//无状态的
class Blob extends StatelessWidget {
final Color color; //传入的颜色
final double rotation; //传入旋转的角度
final double scale; //传入缩放的比例
const Blob({this.color, this.rotation = 0, this.scale = 1});
@override
Widget build(BuildContext context) {
return Transform.scale(
scale: scale,
child: Transform.rotate(
angle: rotation,
child: Container(
///背景的椭圆形卡片
decoration: BoxDecoration(
color: color,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(150),
topRight: Radius.circular(240),
bottomLeft: Radius.circular(220),
bottomRight: Radius.circular(180),
),
),
),
),
);
}
}
首先,我们定义状态,这是一个:一个bool isPlaying
按钮,播放/暂停,第二部分是rotation
和scale
值适用于我们的Blob
秒。稍后,我们将对这些旋转和缩放值进行动画处理。
bool isPlaying;
@override
void initState() {
isPlaying = widget.initialIsPlaying;
super.initState();
}
return Container(
//控制播放按钮大小
width: widget.iconSize + 30,
height: widget.iconSize + 30,
child: Stack(
alignment: Alignment.center,
children: [
if (_showWaves) ...[
//创建3个椭圆形进行叠加
Blob(color: Color(0xff0092ff), scale: _scale, rotation: _rotation),
Blob(
color: Color(0xff4ac7b7),
scale: _scale,
rotation: _rotation * 2 - 30),
Blob(
color: Color(0xffa4a6f6),
scale: _scale,
rotation: _rotation * 3 - 45),
],
Container(
constraints: BoxConstraints.expand(),
child: IconButton(
icon: isPlaying ? widget.pauseIcon : widget.playIcon,
onPressed: _onToggle,
),
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.white,
),
),
],
),
);
在 flutter 中添加动画常用的情况是创建一个AnimationController
,需要SingleTickerProviderStateMixin
mixin(或者TickerProviderStateMixin
用于使用多个控制器)的对象,addListener
它setState
在有状态的小部件上执行导致重建。
首先我们先给小部件添加两个AnimationController,然后添加两个常量,它们是两个持续时间,每个控制器一个。我们会将它们标记static const
因为它们永远不会改变。
static const _kToggleDuration = Duration(milliseconds: 300);
static const _kRotationDuration = Duration(seconds: 5);
AnimationController _rotationController;
AnimationController _scaleController;
我们需要在initState
方法中初始化控制器。因为是要一直旋转下去,所以我们将使用我们的repeat
方法,_rotationController
它也将立即启动我们的动画。该_scaleController
是相似的,但只能在按钮按下运行。
@override
void initState() {
isPlaying = widget.initialIsPlaying;
_rotationController =
AnimationController(vsync: this, duration: _kRotationDuration)
..addListener(() => setState(_updateRotation))
..repeat();
_scaleController =
AnimationController(vsync: this, duration: _kToggleDuration)
..addListener(() => setState(_updateScale));
super.initState();
}
为了动画更加的流畅,我还定义了两个辅助方法来更新旋转和缩放。
void _updateRotation() => _rotation = _rotationController.value * 2 * pi;
void _updateScale() => _scale = (_scaleController.value * 0.2) + 0.85;
触发动画,按钮点击时启动动画
void _onToggle() {
setState(() {
isPlaying = !isPlaying;
_scale = _scale == 1 ? .85 : 1;
});
widget.onPressed();
}
这样按钮效果就完成啦
分析:
1.格式化时间处理
2.需要实现音乐播放功能
3.左右切换歌曲功能
4.进度条定位处理
我们会获取到两个参数,一个是歌曲当前播放的时间,一个是歌曲的总时间
我们需要对其进行格式化
该方法类似于求整数和求其余数
minuteString获取到当前的分钟
secondString获取到当前的秒数
String transformString(int seconds) {
String minuteString =
'${(seconds / 60).floor() < 10 ? 0 : ''}${(seconds / 60).floor()}';
String secondString = '${seconds % 60 < 10 ? 0 : ''}${seconds % 60}';
return '$minuteString:$secondString';
}
使用:
当前播放时间:
Text(
transformString(realtimePlayingInfos.currentPosition.inSeconds),
style: TextStyle(
color: Colors.white, fontWeight: FontWeight.bold, fontSize: 17),
),
歌曲总时间也一样的写法,只是参数不同,详细看源代码哈~
这个是一个播放器最重要的功能
本文使用assets_audio_player,大家有其他需求的话也可以使用其他的插件,原理都差不多
我们先定义静态资源:
//音乐名和图片名不能为中文!!中文是无法识别的
List<Audio> audioList = [
Audio('assets/daphneOdera.mp3',
metas: Metas(
title: '七里香',
artist: 'Jay',
image: MetasImage.asset('assets/daphneOdera.jpg'))),
...其他的歌曲
];
对于播放器我们需要一个控制器
final AssetsAudioPlayer audioPlayer = AssetsAudioPlayer();
第一步:我们需要对其进行初始化:
@override
void initState() {
super.initState();
setupPlaylist();
}
void setupPlaylist() async {
//初始化播放器,对静态资源也进行初始化
audioPlayer.open(Playlist(audios: audioList),
autoStart: false, loopMode: LoopMode.playlist);
}
第二步:进行播放以及暂停控制
在此次我们需要用到插件的RealtimePlayingInfos 参数,用于获取静态资源
Widget playBar(RealtimePlayingInfos realtimePlayingInfos) {
return PlayButton(
//PlayButton就是前面封装的播放按钮
onPressed: () => audioPlayer.playOrPause(), //播放或暂停
initialIsPlaying:false,
iconColor: highlightColor,
iconSize:screenHeight * 0.06,
);
}
这样简单的播放功能就完成了,这个插件封装的还是很简单的
这个也是这个播放器最难的点,因为要在处理切换的时候,还要切歌,判断当前是哪一首歌
轮播图实现,这里使用了插件,如果有特殊需求的话,大家也可以使用PageView自己写
//传入RealtimePlayingInfos参数
Widget swiper(RealtimePlayingInfos realtimePlayingInfos) {
//定义轮播图
return Container(
width: screenWidth,
height: screenHeight * 0.45,
child: Swiper(
controller: swiperController,
itemCount: audioList.length,
itemBuilder: (context, index) {
return ClipRRect(
borderRadius: BorderRadius.circular(50.0),
child: Image.asset(
//获取歌曲封面
audioList[index].metas.image.path,
fit: BoxFit.cover,
),
);
},
onIndexChanged: (newIndex) async {
//左右切换时,传入新的参数,用于定位当前播放歌曲
audioPlayer.playlistPlayAtIndex(newIndex);
},
viewportFraction: 0.75,
scale: 0.8,
),
);
}
通过当前的时间与总时长进行计算,具体的参数大家可以参考SliderTheme,在这里就是传入了两个参数。
audioPlayer.seek()方法用于定位到拖动位置
Widget slider(RealtimePlayingInfos realtimePlayingInfos) {
return SliderTheme(
data: SliderThemeData(
thumbColor: highlightColor,
thumbShape: RoundSliderThumbShape(enabledThumbRadius: 1),
activeTrackColor: highlightColor,
inactiveTrackColor: Colors.grey[800],
overlayColor: Colors.transparent),
child: Slider.adaptive(
value: realtimePlayingInfos.currentPosition.inSeconds.toDouble(),
max: realtimePlayingInfos.duration.inSeconds.toDouble(),
min: 0,
onChanged: (value) {
audioPlayer.seek(Duration(seconds: value.toInt()));
}));
}
swiperController.previous() 上一首歌曲
swiperController.next() 下一首歌曲
IconButton(
icon: Icon(Icons.skip_previous_rounded),
onPressed: () => swiperController.previous(),
iconSize: screenHeight * 0.06,
color: Colors.white,
splashColor: Colors.transparent,
highlightColor: Colors.transparent,
),
这样就把轮播图效果的播放器完成啦
第二张效果主要是布局上的一些差别,功能是没有什么区别的,主要是进度条的样式有些不同,这里简单分析一下:
主要是在拖动时有个小点,代码区别不大。
Widget slider(RealtimePlayingInfos realtimePlayingInfos) {
return SliderTheme(
data: SliderThemeData(
trackShape: CustomTrackShape(),
thumbShape: RoundSliderThumbShape(enabledThumbRadius: 8)),
child: Slider.adaptive(
value: realtimePlayingInfos.currentPosition.inSeconds.toDouble(),
max: realtimePlayingInfos.duration.inSeconds.toDouble(),
activeColor: Color(0xffe3eb6b),
inactiveColor: Colors.grey[850],
onChanged: (value) {
audioPlayer.seek(Duration(seconds: value.toInt()));
}),
);
}
本文结束了,看到这里的兄弟们给点点赞吧,又是掉头发的一天😭
卡通风格的音乐播放器
炫酷波浪风格的音乐播放器
源代码在这里哦
以上是脚本宝典为你收集整理的女朋友想要听歌,我反手用Flutter做了2个音乐播放器,给她拿捏了全部内容,希望文章能够帮你解决女朋友想要听歌,我反手用Flutter做了2个音乐播放器,给她拿捏了所遇到的问题。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。