前言:又是為大家貢獻自己頭發的一天,這幾天在網上搜了搜,發現Flutter的音樂播放器比較少(也還是有幾款比較好的,文章最后推薦給大家😜),要么就是代碼不全無法運行,要么就是UI沒法看,于是我就站了出來,給大家帶來了這些播放器,所以,兄弟們給個贊吧,頭發沒幾根了😭
原始碼在文章最后,是兄弟就來運行看看
話不多說,先上效果圖(有圖有真相啊):
有和我一樣喜歡Jay的嘛


閱讀本文的注意點:
-
使用的插件:
assets_audio_player: ^2.0.14 //用于音樂的播放 flutter_swiper: any //用于第一張效果圖的左右切換效果,如果只要實作第二張的話就不需要啦~ -
文章只展示重要代碼,完整原始碼在文章的最后
正文:
1.帶有波浪式影片的播放/暫停音樂按鈕

當點擊播放時,將多個不同顏色的橢圓形堆疊在一起,然后進行旋轉,
-
所以根據效果需求我們實作需要3個步驟:
1.創建一個無狀態的背景橢圓形
2.使用將多個背景圓形存放于Stack中,以及點擊處理
3.添加縮放和旋轉影片AnimationController來控制背景圓形
-
定義需要傳入的引數
double _rotation = 0; double _scale = 0.85; -
創建一個無狀態的Blob,用于接收傳進來的color和旋轉以及縮放值
封裝處理一下:
//無狀態的 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), ), ), ), ), ); } } -
使用將多個背景橢圓形存放于Stack中
首先,我們定義狀態,這是一個:一個
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,需要SingleTickerProviderStateMixinmixin(或者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(); }
這樣按鈕效果就完成啦![[靈光一現]](https://img.uj5u.com/2021/10/12/273440121842315.png)
2.輪播圖型別的播放
-
分析:
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()));
}),
);
}
本文結束了,看到這里的兄弟們給點點贊吧,又是掉頭發的一天😭
卡通風格的音樂播放器
炫酷波浪風格的音樂播放器
源代碼在這里哦
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/309958.html
標籤:其他
上一篇:將輸入的5位數轉換為文字
