Skip to content

Commit

Permalink
使用Provider管理全局视频状态,保证上个视频开始播放时自动停止下个视频
Browse files Browse the repository at this point in the history
  • Loading branch information
xwh817 committed Nov 8, 2019
1 parent 92c0c94 commit 729a5f0
Show file tree
Hide file tree
Showing 12 changed files with 239 additions and 128 deletions.
Binary file removed images/music_1.jpg
Binary file not shown.
Binary file added images/placeholder_play_list.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import 'package:flutter_music_player/utils/colors.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:provider/provider.dart';
import 'model/play_list.dart';
import 'model/video_controller.dart';
import 'pages/home_page.dart';

void main() => runApp(_buildProvider());
Expand All @@ -13,6 +14,7 @@ _buildProvider() {
return MultiProvider(
providers: [
ChangeNotifierProvider<PlayList>.value(value: PlayList()),
ChangeNotifierProvider<VideoControllerProvider>.value(value: VideoControllerProvider()),
],
child: MyApp(),
);
Expand Down
29 changes: 29 additions & 0 deletions lib/model/video_controller.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import 'package:flutter/foundation.dart';
import 'package:video_player/video_player.dart';

class VideoControllerProvider with ChangeNotifier{
VideoPlayerController controller;

setController(VideoPlayerController controller){
/* if (controller != null) { // 把上一个停掉
controller.pause();
controller.dispose();
} */
this.controller = controller;
notifyListeners();
}

VideoPlayerController getController(){
return this.controller;
}

// 判断参数是否是当前controller,如果是就把全局controller置空。
bool clearController(VideoPlayerController itemController){
bool isCurrentController = itemController!= null && itemController == this.controller;
if (isCurrentController) {
this.controller = null;
}
return isCurrentController;
}

}
36 changes: 21 additions & 15 deletions lib/pages/play_list_detail.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,13 @@ class _PlayListPageState extends State<PlayListPage> {
GlobalKey<ScaffoldState>();

double _appBarHeight = 256.0;
AppBarBehavior _appBarBehavior = AppBarBehavior.pinned;
List _songs = List();
bool _imageLoaded = true;

@override
void initState() {
// appBar和图片宽高比相同
_appBarHeight = ScreenUtil.screenWidth * 4 / 6;
_appBarHeight = ScreenUtil.screenWidth * 4 / 6;
_getPlayListSongs();
super.initState();
}
Expand All @@ -41,9 +40,11 @@ class _PlayListPageState extends State<PlayListPage> {

_getPlayListSongs() async {
MusicDao.getPlayListDetail(widget.playlist['id'] as int).then((list) {
setState(() {
_songs = list;
});
if (mounted) {
setState(() {
_songs = list;
});
}
});
}

Expand All @@ -61,10 +62,9 @@ class _PlayListPageState extends State<PlayListPage> {
slivers: <Widget>[
SliverAppBar(
expandedHeight: _appBarHeight,
pinned: _appBarBehavior == AppBarBehavior.pinned,
floating: _appBarBehavior == AppBarBehavior.floating ||
_appBarBehavior == AppBarBehavior.snapping,
snap: _appBarBehavior == AppBarBehavior.snapping,
pinned: true,
floating: false,
snap: false,
flexibleSpace: FlexibleSpaceBar(
title: Text(
"${widget.playlist['name']}",
Expand All @@ -73,15 +73,22 @@ class _PlayListPageState extends State<PlayListPage> {
style: TextStyle(fontSize: 16.0),
),
centerTitle: false,
titlePadding: EdgeInsetsDirectional.only(start: 42, bottom: 16),
titlePadding:
EdgeInsetsDirectional.only(start: 46.0, bottom: 16.0),
background: Stack(
fit: StackFit.expand,
children: <Widget>[
Hero(
tag: "playListImage_${widget.playlist['id']}",
child:CachedNetworkImage(imageUrl: "${widget.playlist['coverImgUrl']}?param=600y400", fit: BoxFit.cover,
height: _appBarHeight)
),
tag: "playListImage_${widget.playlist['id']}",
child: CachedNetworkImage(
imageUrl:
"${widget.playlist['coverImgUrl']}?param=600y400",
fit: BoxFit.cover,
placeholder: (context, url) => Image.asset(
'images/placeholder_play_list.jpg',
fit: BoxFit.cover,
),
height: _appBarHeight)),
// This gradient ensures that the toolbar icons are distinct
// against the background image.
const DecoratedBox(
Expand Down Expand Up @@ -110,5 +117,4 @@ class _PlayListPageState extends State<PlayListPage> {
),
);
}

}
2 changes: 1 addition & 1 deletion lib/pages/play_list_tab_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class _PlayListTabPageState extends State<PlayListTabPage> {

_getPlaylists() async {
await MusicDao.getPlayList(widget.type).then((result) {
// 界面未加载,返回。
// 界面未加载或者已关闭,返回。
if (!mounted) return;

print("getPlayList result");
Expand Down
21 changes: 15 additions & 6 deletions lib/pages/player_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import 'package:flutter_music_player/model/play_list.dart';
import 'package:flutter_music_player/model/song_util.dart';
import 'package:flutter_music_player/utils/colors.dart';
import 'package:flutter_music_player/utils/screen_util.dart';
import 'package:flutter_music_player/widget/blur_widget.dart';
import 'package:flutter_music_player/widget/favorite_widget.dart';
import 'package:flutter_music_player/widget/lyric_widget.dart';
import 'package:flutter_music_player/widget/music_progress_bar_2.dart';
Expand Down Expand Up @@ -299,15 +300,22 @@ class _PlayerPageState extends State<PlayerPage>

Widget _buildCDCover() {
return Container(
width: 66.0,
height: 66.0,
width: 50.0,
height: 50.0,
child: Container(
child:
ClipOval(child: Container(color: Colors.black.withAlpha(234))),
margin: EdgeInsets.all(16.0)),
width: 20.0,
height: 20.0,
margin: EdgeInsets.all(14.0),
child:BlurOvalWidget(
//padding: 8.0,
sigma: 1.0,
color:Colors.grey.shade700,
child: SizedBox(width: 20, height: 20,)),
),
decoration: BoxDecoration(
color: Colors.white24,
border: Border.all(
width: 2.0,
width: 0.5,
color: Colors.black45,
),
shape: BoxShape.circle));
Expand Down Expand Up @@ -341,6 +349,7 @@ class _PlayerPageState extends State<PlayerPage>
onTap: () => {isGoingPlaying() ? pause() : play()},
child: ClipOval(child: _getSongImage(BoxFit.cover))),
),
_buildCDCover(),
_buildProgressIndicator(),
],
));
Expand Down
34 changes: 34 additions & 0 deletions lib/widget/blur_widget.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import 'dart:ui';

import 'package:flutter/material.dart';

/// 毛玻璃背景
class BlurOvalWidget extends StatelessWidget {
final Widget child;
final double padding;
final Color color;
final double sigma;

BlurOvalWidget(
{this.child,
this.padding: 0.0,
this.sigma: 10.0,
this.color: Colors.white10});

@override
Widget build(BuildContext context) {
return ClipOval(
child: BackdropFilter(
filter: ImageFilter.blur(
sigmaX: 8,
sigmaY: 8,
),
child: Container(
color: color,
padding: EdgeInsets.all(padding),
child: child,
),
),
);
}
}
162 changes: 84 additions & 78 deletions lib/widget/favorite_widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class _FavoriteIconState extends State<FavoriteIcon> {
MusicDB().getFavoriteById(song['id']).then((fav) {
print('getFavoriteById : $fav');
setState(() {
isFavorited = fav != null;
isFavorited = fav != null;
});
});
}
Expand All @@ -39,90 +39,96 @@ class _FavoriteIconState extends State<FavoriteIcon> {
}
//print('FavoriteIcon build');
return IconButton(
icon: Icon(
Icons.favorite,
color: isFavorited ? Colors.pink : Colors.white60,
),
onPressed: () {
if (this.isFavorited) {
_cancelFavorite(context);
} else {
_favorite(context);
}
},
icon: Icon(
Icons.favorite,
color: isFavorited ? Colors.pink : Colors.white60,
),
onPressed: () {
if (this.isFavorited) {
_cancelFavorite(context);
} else {
_favorite(context);
}
},
);
}

_showSnackBar({IconData icon, String title, String subTitle}) {
SnackBar snackBar = SnackBar(
content: ListTile(
leading: Icon(icon),
title: Text(title, style: TextStyle(fontSize: 16.0)),
subtitle:
Text(subTitle, style: TextStyle(fontSize: 14.0, height: 2.0)),
),
duration: Duration(seconds: 3));
Scaffold.of(context).showSnackBar(snackBar);
}

void _favorite(context){
void _favorite(context) {
bool success = false;
MusicDB().addFavorite(widget.song).then((re){
print('addFavorite re: $re , song: ${widget.song}');
}).then((_){
return FileUtil.getSongLocalPath(widget.song);
}).then((savePath){
String url = SongUtil.getSongUrl(widget.song);
HttpUtil.download(url, savePath);
print('download: $url');
setState(() {
isFavorited = true;
});
success = true;
}).catchError((error){
print('addFavorite error: $error');
success = false;
}).whenComplete((){

SnackBar snackBar = SnackBar(content: ListTile(
title: Text(success ? '已添加收藏' : '添加收藏失败'),
subtitle: Text(success ? '正在下载歌曲...' : ''),
), duration: Duration(seconds: 2));
Scaffold.of(context).showSnackBar(snackBar);
MusicDB().addFavorite(widget.song).then((re) {
print('addFavorite re: $re , song: ${widget.song}');
}).then((_) {
return FileUtil.getSongLocalPath(widget.song);
}).then((savePath) {
String url = SongUtil.getSongUrl(widget.song);
HttpUtil.download(url, savePath);
print('download: $url');
setState(() {
isFavorited = true;
});
success = true;
}).catchError((error) {
print('addFavorite error: $error');
success = false;
}).whenComplete(() {
_showSnackBar(
icon: Icons.file_download,
title: success ? '已添加收藏' : '添加收藏失败',
subTitle: success ? '正在下载歌曲...' : '');
});
}

void _cancelFavorite(context){
void _cancelFavorite(context) {
bool success = false;
showDialog(context: context, barrierDismissible: true,
builder: (_)=>AlertDialog(
title: Text('取消收藏?'),
content: Text(('已下载歌曲会被删掉')),
actions: <Widget>[
new FlatButton(
child: new Text("继续收藏"),
onPressed: () {
Navigator.of(context).pop();
},
),
new FlatButton(
child: new Text("确定删除"),
onPressed: () {
MusicDB().deleteFavorite(widget.song['id'])
.then((re){
return FileUtil.deleteLocalSong(widget.song);
}).then((re){
success = true;
Navigator.of(context).pop();
setState(() {
isFavorited = false;
});
}).catchError((error){
success = false;
print('deleteFavorite error: $error');
throw Exception('取消收藏失败');
}).whenComplete((){
SnackBar snackBar = SnackBar(content: ListTile(
title: Text(success ? '已取消收藏' : '取消收藏失败'),
subtitle: Text(success ? '正在取消...' : ''),
), duration: Duration(seconds: 1));
Scaffold.of(context).showSnackBar(snackBar);
});
},
),
],
));

showDialog(
context: context,
barrierDismissible: true,
builder: (_) => AlertDialog(
title: Text('取消收藏?', style: TextStyle(fontSize: 16.0)),
content: Text('已下载歌曲会被删掉', style: TextStyle(fontSize: 14.0)),
actions: <Widget>[
new FlatButton(
child: new Text("继续收藏"),
onPressed: () {
Navigator.of(context).pop();
},
),
new FlatButton(
child: new Text("确定删除"),
onPressed: () {
MusicDB().deleteFavorite(widget.song['id']).then((re) {
return FileUtil.deleteLocalSong(widget.song);
}).then((re) {
success = true;
Navigator.of(context).pop();
setState(() {
isFavorited = false;
});
}).catchError((error) {
success = false;
print('deleteFavorite error: $error');
throw Exception('取消收藏失败');
}).whenComplete(() {
_showSnackBar(
icon: Icons.delete_sweep,
title: success ? '已取消收藏' : '取消收藏失败',
subTitle: success ? '正在取消...' : '');
});
},
),
],
));
}


}
}
Loading

0 comments on commit 729a5f0

Please sign in to comment.