Commit b1869cf8c5a103abd2206171c56033fe68ce78c8
1 parent
d5fb5080
背景音乐添加
Showing
11 changed files
with
187 additions
and
77 deletions
lib/pages/games/bloc.dart
| ... | ... | @@ -2,17 +2,17 @@ import 'package:bloc/bloc.dart'; |
| 2 | 2 | import 'package:flutter/cupertino.dart'; |
| 3 | 3 | import 'package:flutter/services.dart'; |
| 4 | 4 | import 'package:wow_english/common/extension/string_extension.dart'; |
| 5 | +import 'package:wow_english/utils/audioplayer_util.dart'; | |
| 5 | 6 | |
| 6 | 7 | import 'event.dart'; |
| 7 | 8 | import 'game_entity.dart'; |
| 8 | 9 | import 'state.dart'; |
| 9 | 10 | |
| 10 | 11 | class GamesBloc extends Bloc<GamesEvent, GamesState> { |
| 11 | - | |
| 12 | 12 | late MethodChannel _methodChannel; |
| 13 | 13 | |
| 14 | 14 | //手动初始化4个GameEntity对象 |
| 15 | - final List<GameEntity> _games = [ | |
| 15 | + final List<GameEntity> _games = [ | |
| 16 | 16 | GameEntity() |
| 17 | 17 | ..id = 1 |
| 18 | 18 | ..imageName = 'game_food_1'.assetPng |
| ... | ... | @@ -31,7 +31,7 @@ class GamesBloc extends Bloc<GamesEvent, GamesState> { |
| 31 | 31 | ..name = 'Animal' |
| 32 | 32 | ]; |
| 33 | 33 | |
| 34 | - List<GameEntity> get listData => _games; | |
| 34 | + List<GameEntity> get listData => _games; | |
| 35 | 35 | |
| 36 | 36 | GamesBloc() : super(GamesState().init()) { |
| 37 | 37 | on<InitEvent>(_init); |
| ... | ... | @@ -39,13 +39,16 @@ class GamesBloc extends Bloc<GamesEvent, GamesState> { |
| 39 | 39 | } |
| 40 | 40 | |
| 41 | 41 | void _init(InitEvent event, Emitter<GamesState> emit) async { |
| 42 | + AudioPlayerUtil.getInstance().playAudio(AudioPlayerUtilType.inMyTummy); | |
| 42 | 43 | emit(state.clone()); |
| 43 | 44 | } |
| 44 | 45 | |
| 45 | 46 | void _gotoGamePage(GotoGamePageEvent event, Emitter<GamesState> emit) async { |
| 47 | + AudioPlayerUtil.getInstance().pause(); | |
| 46 | 48 | try { |
| 47 | 49 | _methodChannel = const MethodChannel('wow_english/game_method_channel'); |
| 48 | - await _methodChannel.invokeMethod('openGamePage', { "gameId": event.gameId }); | |
| 50 | + await _methodChannel | |
| 51 | + .invokeMethod('openGamePage', {"gameId": event.gameId}); | |
| 49 | 52 | } on PlatformException catch (e) { |
| 50 | 53 | debugPrint("Failed to go to native page: '${e.message}'."); |
| 51 | 54 | } | ... | ... |
lib/pages/home/bloc.dart
| ... | ... | @@ -2,6 +2,7 @@ import 'package:audioplayers/audioplayers.dart'; |
| 2 | 2 | import 'package:bloc/bloc.dart'; |
| 3 | 3 | import 'package:wow_english/common/core/user_util.dart'; |
| 4 | 4 | import 'package:wow_english/common/extension/string_extension.dart'; |
| 5 | +import 'package:wow_english/utils/audioplayer_util.dart'; | |
| 5 | 6 | |
| 6 | 7 | import '../../common/core/app_config_helper.dart'; |
| 7 | 8 | import '../../common/request/dao/system_dao.dart'; |
| ... | ... | @@ -17,16 +18,10 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> { |
| 17 | 18 | } |
| 18 | 19 | |
| 19 | 20 | bool exchangeResult = false; |
| 20 | - late AudioPlayer audioPlayer; | |
| 21 | - late AudioPlayer studyPlayer; | |
| 22 | - late AudioPlayer gamePlayer; | |
| 23 | 21 | |
| 24 | 22 | void _init(InitEvent event, Emitter<HomeState> emit) async { |
| 25 | 23 | if (UserUtil.isLogined()) { |
| 26 | - audioPlayer = AudioPlayer(playerId: 'audio'); | |
| 27 | - gamePlayer = AudioPlayer(playerId: 'game'); | |
| 28 | - studyPlayer = AudioPlayer(playerId: 'study'); | |
| 29 | - audioPlayer.play(AssetSource('welcome_to_wow'.assetMp3)); | |
| 24 | + AudioPlayerUtil.getInstance().playAudio(AudioPlayerUtilType.welcomeToWow); | |
| 30 | 25 | } |
| 31 | 26 | await _checkUpdate(emit); |
| 32 | 27 | } | ... | ... |
lib/pages/home/view.dart
| ... | ... | @@ -12,6 +12,7 @@ import 'package:wow_english/pages/home/state.dart'; |
| 12 | 12 | import 'package:wow_english/pages/home/widgets/BaseHomeHeaderWidget.dart'; |
| 13 | 13 | import 'package:wow_english/pages/shop/exchane/bloc/exchange_lesson_bloc.dart'; |
| 14 | 14 | import 'package:wow_english/pages/user/bloc/user_bloc.dart'; |
| 15 | +import 'package:wow_english/utils/audioplayer_util.dart'; | |
| 15 | 16 | |
| 16 | 17 | import '../../common/core/user_util.dart'; |
| 17 | 18 | import '../../common/dialogs/show_dialog.dart'; |
| ... | ... | @@ -60,6 +61,8 @@ class _HomePageView extends StatelessWidget { |
| 60 | 61 | children: [ |
| 61 | 62 | BaseHomeHeaderWidget( |
| 62 | 63 | callBack: (value) => { |
| 64 | + AudioPlayerUtil.getInstance() | |
| 65 | + .playAudio(AudioPlayerUtilType.touch), | |
| 63 | 66 | bloc.exchangeResult = value['exchange'], |
| 64 | 67 | bloc.add(ExchangeSuccessEvent()) |
| 65 | 68 | }), |
| ... | ... | @@ -71,8 +74,8 @@ class _HomePageView extends StatelessWidget { |
| 71 | 74 | child: GestureDetector( |
| 72 | 75 | onTap: () { |
| 73 | 76 | _checkPermission(() { |
| 74 | - bloc.studyPlayer | |
| 75 | - .play(AssetSource('class_time'.assetMp3)); | |
| 77 | + AudioPlayerUtil.getInstance() | |
| 78 | + .playAudio(AudioPlayerUtilType.classTime); | |
| 76 | 79 | Future.delayed(const Duration(seconds: 1), () { |
| 77 | 80 | pushNamed(AppRouteName.courseUnit) |
| 78 | 81 | .then((value) => { |
| ... | ... | @@ -108,29 +111,38 @@ class _HomePageView extends StatelessWidget { |
| 108 | 111 | ), |
| 109 | 112 | ), |
| 110 | 113 | ), |
| 111 | - Expanded( | |
| 112 | - child: BlocBuilder<UserBloc, UserState>( | |
| 113 | - builder: (context, userState) { | |
| 114 | - return GestureDetector( | |
| 115 | - onTap: () { | |
| 116 | - _checkPermission(() { | |
| 117 | - Navigator.of(context).pushNamed( | |
| 118 | - AppRouteName.webView, | |
| 119 | - arguments: { | |
| 120 | - 'urlStr': AppConsts.xiaoeShopUrl, | |
| 121 | - 'webViewTitle': 'Wow精选' | |
| 122 | - }); | |
| 123 | - }, bloc); | |
| 124 | - }, | |
| 125 | - child: Column( | |
| 126 | - mainAxisAlignment: MainAxisAlignment.center, | |
| 127 | - children: [ | |
| 128 | - Image.asset('xe_shop'.assetPng, | |
| 129 | - width: 140.5.w, height: 172.h), | |
| 130 | - 44.verticalSpace | |
| 131 | - ], | |
| 132 | - )); | |
| 133 | - }), | |
| 114 | + Offstage( | |
| 115 | + offstage: AppConfigHelper.shouldHidePay() || | |
| 116 | + !UserUtil.isLogined(), | |
| 117 | + child: Expanded( | |
| 118 | + child: BlocBuilder<UserBloc, UserState>( | |
| 119 | + builder: (context, userState) { | |
| 120 | + return GestureDetector( | |
| 121 | + onTap: () { | |
| 122 | + _checkPermission(() { | |
| 123 | + AudioPlayerUtil.getInstance().pause(); | |
| 124 | + Navigator.of(context).pushNamed( | |
| 125 | + AppRouteName.webView, | |
| 126 | + arguments: { | |
| 127 | + 'urlStr': AppConsts.xiaoeShopUrl, | |
| 128 | + 'webViewTitle': 'Wow精选' | |
| 129 | + }).then((value) => { | |
| 130 | + AudioPlayerUtil.getInstance() | |
| 131 | + .playAudio( | |
| 132 | + AudioPlayerUtilType.touch), | |
| 133 | + }); | |
| 134 | + }, bloc); | |
| 135 | + }, | |
| 136 | + child: Column( | |
| 137 | + mainAxisAlignment: MainAxisAlignment.center, | |
| 138 | + children: [ | |
| 139 | + Image.asset('xe_shop'.assetPng, | |
| 140 | + width: 140.5.w, height: 172.h), | |
| 141 | + 44.verticalSpace | |
| 142 | + ], | |
| 143 | + )); | |
| 144 | + }), | |
| 145 | + ), | |
| 134 | 146 | ), |
| 135 | 147 | Expanded( |
| 136 | 148 | child: BlocBuilder<UserBloc, UserState>( |
| ... | ... | @@ -138,9 +150,14 @@ class _HomePageView extends StatelessWidget { |
| 138 | 150 | return GestureDetector( |
| 139 | 151 | onTap: () { |
| 140 | 152 | _checkPermission(() { |
| 141 | - bloc.gamePlayer.play( | |
| 142 | - AssetSource('game_time'.assetMp3)); | |
| 143 | - pushNamed(AppRouteName.games); | |
| 153 | + AudioPlayerUtil.getInstance().playAudio( | |
| 154 | + AudioPlayerUtilType.gameTime); | |
| 155 | + pushNamed(AppRouteName.games) | |
| 156 | + .then((value) => { | |
| 157 | + AudioPlayerUtil.getInstance() | |
| 158 | + .playAudio(AudioPlayerUtilType | |
| 159 | + .touch), | |
| 160 | + }); | |
| 144 | 161 | }, bloc); |
| 145 | 162 | }, |
| 146 | 163 | child: Column( |
| ... | ... | @@ -189,6 +206,8 @@ class _HomePageView extends StatelessWidget { |
| 189 | 206 | }, rightTap: () { |
| 190 | 207 | popPage(); |
| 191 | 208 | pushNamed(AppRouteName.shop).then((value) { |
| 209 | + AudioPlayerUtil.getInstance() | |
| 210 | + .playAudio(AudioPlayerUtilType.touch); | |
| 192 | 211 | if (value != null) { |
| 193 | 212 | bloc.exchangeResult = value['exchange']; |
| 194 | 213 | bloc.add(ExchangeSuccessEvent()); | ... | ... |
lib/pages/home/widgets/BaseHomeHeaderWidget.dart
| ... | ... | @@ -3,6 +3,7 @@ import 'package:flutter_bloc/flutter_bloc.dart'; |
| 3 | 3 | import 'package:flutter_screenutil/flutter_screenutil.dart'; |
| 4 | 4 | import 'package:wow_english/common/core/app_config_helper.dart'; |
| 5 | 5 | import 'package:wow_english/common/extension/string_extension.dart'; |
| 6 | +import 'package:wow_english/utils/audioplayer_util.dart'; | |
| 6 | 7 | |
| 7 | 8 | import '../../../common/core/user_util.dart'; |
| 8 | 9 | import '../../../models/course_entity.dart'; |
| ... | ... | @@ -84,6 +85,7 @@ class BaseHomeHeaderWidget extends StatelessWidget { |
| 84 | 85 | !UserUtil.isLogined(), |
| 85 | 86 | child: GestureDetector( |
| 86 | 87 | onTap: () => { |
| 88 | + AudioPlayerUtil.getInstance().pause(), | |
| 87 | 89 | pushNamed(AppRouteName.shop).then((value) { |
| 88 | 90 | if (value != null) { |
| 89 | 91 | if (callBack == null) { |
| ... | ... | @@ -115,6 +117,7 @@ class BaseHomeHeaderWidget extends StatelessWidget { |
| 115 | 117 | |
| 116 | 118 | void onUserClick() { |
| 117 | 119 | if (UserUtil.isLogined()) { |
| 120 | + AudioPlayerUtil.getInstance().pause(); | |
| 118 | 121 | pushNamed(AppRouteName.user).then((value) { |
| 119 | 122 | if (value != null) { |
| 120 | 123 | if (callBack == null) { | ... | ... |
lib/pages/section/bloc/section_bloc.dart
| ... | ... | @@ -9,6 +9,7 @@ import 'package:wow_english/common/request/dao/lesson_dao.dart'; |
| 9 | 9 | import 'package:wow_english/common/request/exception.dart'; |
| 10 | 10 | import 'package:wow_english/common/request/dao/listen_dao.dart'; |
| 11 | 11 | import 'package:wow_english/models/course_process_entity.dart'; |
| 12 | +import 'package:wow_english/utils/audioplayer_util.dart'; | |
| 12 | 13 | import 'package:wow_english/utils/loading.dart'; |
| 13 | 14 | import 'package:wow_english/utils/toast_util.dart'; |
| 14 | 15 | |
| ... | ... | @@ -45,8 +46,6 @@ class SectionBloc extends Bloc<SectionEvent, SectionState> { |
| 45 | 46 | ///单元列表是否有刷新,有的话返回上一页时通知其刷新接口数据 |
| 46 | 47 | bool courseUnitEntityChanged = false; |
| 47 | 48 | |
| 48 | - late AudioPlayer audioPlayer; // 点击播放器 | |
| 49 | - late AudioPlayer backgroundPlayer; // 背景播放器 | |
| 50 | 49 | ///courseUnitId与课程环节列表的映射 |
| 51 | 50 | final Map<int, List<CourseSectionEntity>?> _courseSectionDatasMap = {}; |
| 52 | 51 | |
| ... | ... | @@ -66,25 +65,12 @@ class SectionBloc extends Bloc<SectionEvent, SectionState> { |
| 66 | 65 | on<RequestVideoLessonEvent>(_requestVideoLesson); |
| 67 | 66 | on<CurrentUnitIndexChangeEvent>(_pageControllerChange); |
| 68 | 67 | on<InitEvent>((event, emit) { |
| 69 | - audioPlayer = AudioPlayer(playerId: 'section'); | |
| 70 | - backgroundPlayer = AudioPlayer(playerId: 'back'); | |
| 71 | - backgroundPlayer.play(AssetSource('count_with_me_instrumental'.assetMp3)); | |
| 72 | - | |
| 73 | - backgroundPlayer.onPlayerStateChanged.listen((event) async { | |
| 74 | - if (event == PlayerState.completed) { | |
| 75 | - // 播放结束再次播放 | |
| 76 | - backgroundPlayer | |
| 77 | - .play(AssetSource('count_with_me_instrumental'.assetMp3)); | |
| 78 | - } | |
| 79 | - }); | |
| 68 | + AudioPlayerUtil.getInstance().playAudio(AudioPlayerUtilType.countWithMe); | |
| 80 | 69 | }); |
| 81 | 70 | } |
| 82 | 71 | @override |
| 83 | 72 | Future<void> close() { |
| 84 | - audioPlayer.release(); | |
| 85 | - audioPlayer.dispose(); | |
| 86 | - backgroundPlayer.release(); | |
| 87 | - backgroundPlayer.dispose(); | |
| 73 | + AudioPlayerUtil.getInstance().pause(); | |
| 88 | 74 | return super.close(); |
| 89 | 75 | } |
| 90 | 76 | ... | ... |
lib/pages/section/bloc/section_state.dart
lib/pages/section/section_page.dart
| ... | ... | @@ -12,6 +12,8 @@ import 'package:wow_english/pages/section/widgets/section_item.dart'; |
| 12 | 12 | import 'package:wow_english/pages/section/widgets/section_bouns_item.dart'; |
| 13 | 13 | import 'package:wow_english/pages/section/widgets/section_header_widget.dart'; |
| 14 | 14 | import 'package:wow_english/route/route.dart'; |
| 15 | +import 'package:wow_english/utils/audioplayer_util.dart'; | |
| 16 | +import 'package:wow_english/utils/log_util.dart'; | |
| 15 | 17 | import 'package:wow_english/utils/toast_util.dart'; |
| 16 | 18 | |
| 17 | 19 | import '../../models/course_section_entity.dart'; |
| ... | ... | @@ -89,23 +91,23 @@ class _SectionPageView extends StatelessWidget { |
| 89 | 91 | currentTime: dataMap['currentTime'], |
| 90 | 92 | autoNextSection: dataMap['nextSection'])); |
| 91 | 93 | } |
| 92 | - if (bloc.backgroundPlayer.state == PlayerState.paused) { | |
| 93 | - bloc.backgroundPlayer.resume(); | |
| 94 | - } | |
| 94 | + AudioPlayerUtil.getInstance() | |
| 95 | + .playAudio(AudioPlayerUtilType.countWithMe); | |
| 95 | 96 | }); |
| 96 | 97 | return; |
| 97 | 98 | } |
| 98 | 99 | |
| 99 | 100 | if (state is RequestEnterClassState) { |
| 100 | - bloc.backgroundPlayer.pause(); | |
| 101 | 101 | if (state.courseType != SectionType.practice.value && |
| 102 | 102 | state.courseType != SectionType.pictureBook.value) { |
| 103 | 103 | ///视频类型 |
| 104 | 104 | ///获取视频课程内容 |
| 105 | 105 | if (state.courseType == 1) { |
| 106 | - bloc.audioPlayer.play(AssetSource('music_time'.assetMp3)); | |
| 106 | + AudioPlayerUtil.getInstance() | |
| 107 | + .playAudio(AudioPlayerUtilType.musicTime); | |
| 107 | 108 | } else { |
| 108 | - bloc.audioPlayer.play(AssetSource('video_time'.assetMp3)); | |
| 109 | + AudioPlayerUtil.getInstance() | |
| 110 | + .playAudio(AudioPlayerUtilType.videoTime); | |
| 109 | 111 | } |
| 110 | 112 | Future.delayed(const Duration(seconds: 1), () { |
| 111 | 113 | bloc.add(RequestVideoLessonEvent( |
| ... | ... | @@ -116,7 +118,8 @@ class _SectionPageView extends StatelessWidget { |
| 116 | 118 | } |
| 117 | 119 | |
| 118 | 120 | if (state.courseType == SectionType.pictureBook.value) { |
| 119 | - bloc.audioPlayer.play(AssetSource('reading_time'.assetMp3)); | |
| 121 | + AudioPlayerUtil.getInstance() | |
| 122 | + .playAudio(AudioPlayerUtilType.readingTime); | |
| 120 | 123 | Future.delayed(const Duration(seconds: 1), () { |
| 121 | 124 | //绘本 |
| 122 | 125 | pushNamed(AppRouteName.reading, |
| ... | ... | @@ -130,9 +133,8 @@ class _SectionPageView extends StatelessWidget { |
| 130 | 133 | currentStep: dataMap['currentStep'], |
| 131 | 134 | autoNextSection: dataMap['nextSection'], |
| 132 | 135 | )); |
| 133 | - if (bloc.backgroundPlayer.state == PlayerState.paused) { | |
| 134 | - bloc.backgroundPlayer.resume(); | |
| 135 | - } | |
| 136 | + AudioPlayerUtil.getInstance() | |
| 137 | + .playAudio(AudioPlayerUtilType.countWithMe); | |
| 136 | 138 | } |
| 137 | 139 | }); |
| 138 | 140 | }); |
| ... | ... | @@ -142,7 +144,8 @@ class _SectionPageView extends StatelessWidget { |
| 142 | 144 | |
| 143 | 145 | if (state.courseType == SectionType.practice.value) { |
| 144 | 146 | //练习 |
| 145 | - bloc.audioPlayer.play(AssetSource('quiz_time'.assetMp3)); | |
| 147 | + AudioPlayerUtil.getInstance() | |
| 148 | + .playAudio(AudioPlayerUtilType.quizTime); | |
| 146 | 149 | Future.delayed(const Duration(seconds: 1), () { |
| 147 | 150 | pushNamed(AppRouteName.topicPic, |
| 148 | 151 | arguments: {'courseLessonId': state.courseLessonId}) |
| ... | ... | @@ -154,9 +157,8 @@ class _SectionPageView extends StatelessWidget { |
| 154 | 157 | currentStep: dataMap['currentStep'], |
| 155 | 158 | autoNextSection: dataMap['nextSection'])); |
| 156 | 159 | } |
| 157 | - if (bloc.backgroundPlayer.state == PlayerState.paused) { | |
| 158 | - bloc.backgroundPlayer.resume(); | |
| 159 | - } | |
| 160 | + AudioPlayerUtil.getInstance() | |
| 161 | + .playAudio(AudioPlayerUtilType.countWithMe); | |
| 160 | 162 | }); |
| 161 | 163 | }); |
| 162 | 164 | return; | ... | ... |
lib/pages/unit/bloc.dart
| 1 | 1 | import 'package:bloc/bloc.dart'; |
| 2 | 2 | import 'package:wow_english/pages/unit/widget/home_tab_header_widget.dart'; |
| 3 | +import 'package:wow_english/utils/audioplayer_util.dart'; | |
| 3 | 4 | |
| 4 | 5 | import '../../common/request/dao/lesson_dao.dart'; |
| 5 | 6 | import '../../common/request/exception.dart'; |
| ... | ... | @@ -24,6 +25,9 @@ class UnitBloc extends Bloc<UnitEvent, UnitState> { |
| 24 | 25 | |
| 25 | 26 | UnitBloc(CourseModuleEntity? courseEntity) : super(UnitState().init()) { |
| 26 | 27 | on<RequestUnitDataEvent>(_requestUnitDatas); |
| 28 | + on<UnitInitEvent>((event, emit) { | |
| 29 | + AudioPlayerUtil.getInstance().playAudio(AudioPlayerUtilType.inMyTummy); | |
| 30 | + }); | |
| 27 | 31 | } |
| 28 | 32 | |
| 29 | 33 | void _requestUnitDatas( |
| ... | ... | @@ -45,15 +49,26 @@ class UnitBloc extends Bloc<UnitEvent, UnitState> { |
| 45 | 49 | } |
| 46 | 50 | |
| 47 | 51 | void headerActionEvent(HeaderActionType type) { |
| 52 | + AudioPlayerUtil.getInstance().pause(); | |
| 48 | 53 | if (type == HeaderActionType.video) { |
| 49 | 54 | pushNamed(AppRouteName.reAfter); |
| 50 | 55 | } else if (type == HeaderActionType.phase) { |
| 51 | - pushNamed(AppRouteName.courseModule); | |
| 56 | + pushNamed(AppRouteName.courseModule).then((value) => { | |
| 57 | + AudioPlayerUtil.getInstance() | |
| 58 | + .playAudio(AudioPlayerUtilType.inMyTummy) | |
| 59 | + }); | |
| 60 | + ; | |
| 52 | 61 | } else if (type == HeaderActionType.listen) { |
| 53 | - pushNamed(AppRouteName.listen); | |
| 62 | + pushNamed(AppRouteName.listen).then((value) => { | |
| 63 | + AudioPlayerUtil.getInstance() | |
| 64 | + .playAudio(AudioPlayerUtilType.inMyTummy) | |
| 65 | + }); | |
| 54 | 66 | } else if (type == HeaderActionType.shop) { |
| 55 | - pushNamed(AppRouteName.shop) | |
| 56 | - .then((value) => {exchangeResult = value['exchange']}); | |
| 67 | + pushNamed(AppRouteName.shop).then((value) => { | |
| 68 | + AudioPlayerUtil.getInstance() | |
| 69 | + .playAudio(AudioPlayerUtilType.inMyTummy), | |
| 70 | + exchangeResult = value['exchange'] | |
| 71 | + }); | |
| 57 | 72 | } else if (type == HeaderActionType.user) { |
| 58 | 73 | pushNamed(AppRouteName.user); |
| 59 | 74 | } | ... | ... |
lib/pages/unit/event.dart
lib/pages/unit/view.dart
| ... | ... | @@ -5,6 +5,7 @@ import 'package:wow_english/pages/unit/state.dart'; |
| 5 | 5 | import 'package:wow_english/pages/unit/widget/course_unit_item.dart'; |
| 6 | 6 | import 'package:wow_english/pages/unit/widget/home_tab_header_widget.dart'; |
| 7 | 7 | import 'package:wow_english/route/route.dart'; |
| 8 | +import 'package:wow_english/utils/audioplayer_util.dart'; | |
| 8 | 9 | |
| 9 | 10 | import '../../models/course_module_entity.dart'; |
| 10 | 11 | import '../../models/course_unit_entity.dart'; |
| ... | ... | @@ -23,6 +24,7 @@ class UnitPage extends StatelessWidget { |
| 23 | 24 | Widget build(BuildContext context) { |
| 24 | 25 | return BlocProvider( |
| 25 | 26 | create: (BuildContext context) => UnitBloc(courseModuleEntity) |
| 27 | + ..add(UnitInitEvent()) | |
| 26 | 28 | ..add(RequestUnitDataEvent(courseModuleEntity?.id)), |
| 27 | 29 | child: Builder(builder: (context) => _buildPage(context)), |
| 28 | 30 | ); |
| ... | ... | @@ -41,6 +43,8 @@ class UnitPage extends StatelessWidget { |
| 41 | 43 | HomeTabHeaderWidget( |
| 42 | 44 | courseModuleCode: bloc.getCourseModuleCode(), |
| 43 | 45 | onBack: () { |
| 46 | + AudioPlayerUtil.getInstance() | |
| 47 | + .playAudio(AudioPlayerUtilType.touch); | |
| 44 | 48 | popPage(data: {'exchange': bloc.exchangeResult}); |
| 45 | 49 | }, |
| 46 | 50 | actionTap: (HeaderActionType type) { |
| ... | ... | @@ -63,12 +67,14 @@ class UnitPage extends StatelessWidget { |
| 63 | 67 | showToast('当前单元课程暂未解锁'); |
| 64 | 68 | return; |
| 65 | 69 | } |
| 66 | - | |
| 70 | + AudioPlayerUtil.getInstance().pause(); | |
| 67 | 71 | pushNamed(AppRouteName.courseSection, |
| 68 | 72 | arguments: { |
| 69 | 73 | 'courseUnitEntity': bloc.unitData, |
| 70 | 74 | 'courseUnitId': data.id |
| 71 | 75 | }).then((value) { |
| 76 | + AudioPlayerUtil.getInstance() | |
| 77 | + .playAudio(AudioPlayerUtilType.inMyTummy); | |
| 72 | 78 | if (value != null) { |
| 73 | 79 | Map<String, dynamic> dataMap = |
| 74 | 80 | value as Map<String, dynamic>; | ... | ... |
lib/utils/audioplayer_util.dart
0 → 100644
| 1 | +import 'package:audioplayers/audioplayers.dart'; | |
| 2 | +import 'package:wow_english/common/extension/string_extension.dart'; | |
| 3 | + | |
| 4 | +enum AudioPlayerUtilType { | |
| 5 | + welcomeToWow('welcome_to_wow'), | |
| 6 | + classTime('class_time'), | |
| 7 | + gameTime('game_time'), | |
| 8 | + musicTime('music_time'), | |
| 9 | + readingTime('reading_time'), | |
| 10 | + videoTime('video_time'), | |
| 11 | + quizTime('quiz_time'), | |
| 12 | + countWithMe('count_with_me_instrumental'), | |
| 13 | + inMyTummy('in_my_tummy_instrumental'), | |
| 14 | + touch('touch_instrumental'); | |
| 15 | + | |
| 16 | + const AudioPlayerUtilType(this.path); | |
| 17 | + | |
| 18 | + final String path; | |
| 19 | +} | |
| 20 | + | |
| 21 | +class AudioPlayerUtil { | |
| 22 | + static AudioPlayerUtil? _instance; | |
| 23 | + late AudioPlayer audioPlayer; | |
| 24 | + late AudioPlayerUtilType currentType; | |
| 25 | + | |
| 26 | + // 私有构造函数 | |
| 27 | + AudioPlayerUtil._internal() { | |
| 28 | + audioPlayer = AudioPlayer(); | |
| 29 | + audioPlayer.onPlayerStateChanged.listen((event) async { | |
| 30 | + if (event == PlayerState.completed) { | |
| 31 | + // 播放结束再次播放 | |
| 32 | + if (currentType == AudioPlayerUtilType.inMyTummy) { | |
| 33 | + AudioPlayerUtil.getInstance() | |
| 34 | + .playAudio(AudioPlayerUtilType.inMyTummy); | |
| 35 | + } | |
| 36 | + if (currentType == AudioPlayerUtilType.countWithMe) { | |
| 37 | + AudioPlayerUtil.getInstance() | |
| 38 | + .playAudio(AudioPlayerUtilType.countWithMe); | |
| 39 | + } | |
| 40 | + if (currentType == AudioPlayerUtilType.welcomeToWow) { | |
| 41 | + AudioPlayerUtil.getInstance().playAudio(AudioPlayerUtilType.touch); | |
| 42 | + } | |
| 43 | + if (currentType == AudioPlayerUtilType.touch) { | |
| 44 | + AudioPlayerUtil.getInstance().playAudio(AudioPlayerUtilType.touch); | |
| 45 | + } | |
| 46 | + } | |
| 47 | + }); | |
| 48 | + } | |
| 49 | + | |
| 50 | + static AudioPlayerUtil getInstance() { | |
| 51 | + _instance ??= AudioPlayerUtil._internal(); | |
| 52 | + return _instance!; | |
| 53 | + } | |
| 54 | + | |
| 55 | +// 播放音频 | |
| 56 | + Future<void> playAudio(AudioPlayerUtilType type) async { | |
| 57 | + currentType = type; | |
| 58 | + String path = type.path; | |
| 59 | + await audioPlayer.play(AssetSource(path.assetMp3), volume: 0.5); | |
| 60 | + await audioPlayer.onPlayerComplete.first; | |
| 61 | + } | |
| 62 | + | |
| 63 | + // stop | |
| 64 | + void stop() { | |
| 65 | + audioPlayer.stop(); | |
| 66 | + } | |
| 67 | + | |
| 68 | + // pause | |
| 69 | + void pause() { | |
| 70 | + if (audioPlayer.state == PlayerState.playing) { | |
| 71 | + audioPlayer.pause(); | |
| 72 | + } | |
| 73 | + } | |
| 74 | + | |
| 75 | + // resume | |
| 76 | + void resume() { | |
| 77 | + if (audioPlayer.state == PlayerState.paused) { | |
| 78 | + audioPlayer.resume(); | |
| 79 | + } | |
| 80 | + } | |
| 81 | +} | ... | ... |