Commit 1e22b7d1bfc9bfeef388fe4b909281f759dd02d6
1 parent
26982eea
feat:儿歌/视频环节接口请求时机优化
Showing
11 changed files
with
172 additions
and
187 deletions
lib/common/request/dao/lesson_dao.dart
... | ... | @@ -13,6 +13,7 @@ class LessonDao { |
13 | 13 | } |
14 | 14 | |
15 | 15 | ///课程单元列表 |
16 | + ///@param moduleId 模块id | |
16 | 17 | static Future<CourseUnitEntity?> courseUnit(int? moduleId) async { |
17 | 18 | Map<String, dynamic> mapData = {}; |
18 | 19 | if (moduleId != null) { |
... | ... | @@ -32,7 +33,7 @@ class LessonDao { |
32 | 33 | return data; |
33 | 34 | } |
34 | 35 | |
35 | - ///课程(单元)列表 | |
36 | + ///课程(环节)列表 | |
36 | 37 | static Future<List<CourseSectionEntity>?> courseSection({required int courseUnitId}) async { |
37 | 38 | Map<String, dynamic> mapData = {}; |
38 | 39 | mapData['courseUnitId'] = courseUnitId; | ... | ... |
lib/pages/practice/bloc/topic_picture_bloc.dart
... | ... | @@ -19,6 +19,7 @@ import '../../../common/permission/permissionRequester.dart'; |
19 | 19 | import '../../../route/route.dart'; |
20 | 20 | |
21 | 21 | part 'topic_picture_event.dart'; |
22 | + | |
22 | 23 | part 'topic_picture_state.dart'; |
23 | 24 | |
24 | 25 | enum VoicePlayState { |
... | ... | @@ -47,6 +48,8 @@ class TopicPictureBloc |
47 | 48 | |
48 | 49 | CourseProcessEntity? _entity; |
49 | 50 | |
51 | + CourseProcessEntity? get entity => _entity; | |
52 | + | |
50 | 53 | ///正在评测 |
51 | 54 | bool _isVoicing = false; |
52 | 55 | |
... | ... | @@ -63,8 +66,6 @@ class TopicPictureBloc |
63 | 66 | |
64 | 67 | bool get forbiddenWhenCorrect => _forbiddenWhenCorrect; |
65 | 68 | |
66 | - CourseProcessEntity? get entity => _entity; | |
67 | - | |
68 | 69 | int get currentPage => _currentPage + 1; |
69 | 70 | |
70 | 71 | int get selectItem => _selectItem; |
... | ... | @@ -257,8 +258,8 @@ class TopicPictureBloc |
257 | 258 | XSVoiceStartEvent event, Emitter<TopicPictureState> emitter) async { |
258 | 259 | await audioPlayer.stop(); |
259 | 260 | // 调用封装好的权限检查和请求方法 |
260 | - bool result = | |
261 | - await requestPermission(context, Permission.microphone, "录音", "用于开启录音,识别您的开口作答并给出反馈"); | |
261 | + bool result = await requestPermission( | |
262 | + context, Permission.microphone, "录音", "用于开启录音,识别您的开口作答并给出反馈"); | |
262 | 263 | if (result) { |
263 | 264 | methodChannel.invokeMethod('startVoice', { |
264 | 265 | 'word': event.testWord, | ... | ... |
lib/pages/section/bloc/section_bloc.dart
1 | -import 'package:audioplayers/audioplayers.dart'; | |
2 | 1 | import 'package:flutter/cupertino.dart'; |
3 | 2 | import 'package:flutter/foundation.dart'; |
4 | 3 | import 'package:flutter/material.dart'; |
5 | 4 | import 'package:flutter_bloc/flutter_bloc.dart'; |
6 | 5 | import 'package:flutter_screenutil/flutter_screenutil.dart'; |
7 | -import 'package:wow_english/common/extension/string_extension.dart'; | |
8 | 6 | import 'package:wow_english/common/request/dao/lesson_dao.dart'; |
9 | 7 | import 'package:wow_english/common/request/exception.dart'; |
10 | 8 | import 'package:wow_english/common/request/dao/listen_dao.dart'; |
11 | -import 'package:wow_english/models/course_process_entity.dart'; | |
12 | 9 | import 'package:wow_english/utils/audio_player_util.dart'; |
13 | 10 | import 'package:wow_english/utils/loading.dart'; |
14 | 11 | import 'package:wow_english/utils/toast_util.dart'; |
... | ... | @@ -53,10 +50,6 @@ class SectionBloc extends Bloc<SectionEvent, SectionState> { |
53 | 50 | Map<int, List<CourseSectionEntity>?> get courseSectionDatasMap => |
54 | 51 | _courseSectionDatasMap; |
55 | 52 | |
56 | - CourseProcessEntity? _processEntity; | |
57 | - | |
58 | - CourseProcessEntity? get processEntity => _processEntity; | |
59 | - | |
60 | 53 | ///点击环节后先请求数据再进入,标志位避免频繁点击多次请求(以及多次进入) |
61 | 54 | bool _isRequesting = false; |
62 | 55 | |
... | ... | @@ -66,7 +59,6 @@ class SectionBloc extends Bloc<SectionEvent, SectionState> { |
66 | 59 | on<RequestDataEvent>(_requestSectionsData); |
67 | 60 | on<RequestEndClassEvent>(_requestEndClass); |
68 | 61 | on<RequestEnterClassEvent>(_requestEnterClass); |
69 | - on<RequestVideoLessonEvent>(_requestVideoLesson); | |
70 | 62 | on<CurrentUnitIndexChangeEvent>(_pageControllerChange); |
71 | 63 | on<InitEvent>((event, emit) async { |
72 | 64 | await AudioPlayerUtil.getInstance().playAudio(AudioPlayerUtilType.countWithMe); |
... | ... | @@ -92,23 +84,6 @@ class SectionBloc extends Bloc<SectionEvent, SectionState> { |
92 | 84 | } |
93 | 85 | } |
94 | 86 | |
95 | - void _requestVideoLesson( | |
96 | - RequestVideoLessonEvent event, Emitter<SectionState> emitter) async { | |
97 | - try { | |
98 | - await loading(() async { | |
99 | - _processEntity = await ListenDao.process(event.courseLessonId); | |
100 | - emitter( | |
101 | - RequestVideoLessonState(event.courseLessonId, event.courseType)); | |
102 | - }); | |
103 | - } catch (e) { | |
104 | - if (e is ApiException) { | |
105 | - showToast(e.message ?? '请求失败,请检查网络连接'); | |
106 | - } | |
107 | - } finally { | |
108 | - _isRequesting = false; | |
109 | - } | |
110 | - } | |
111 | - | |
112 | 87 | void _requestEnterClass( |
113 | 88 | RequestEnterClassEvent event, Emitter<SectionState> emitter) async { |
114 | 89 | try { |
... | ... | @@ -124,8 +99,9 @@ class SectionBloc extends Bloc<SectionEvent, SectionState> { |
124 | 99 | } catch (e) { |
125 | 100 | if (e is ApiException) { |
126 | 101 | showToast(e.message ?? '请求失败,请检查网络连接'); |
127 | - _isRequesting = false; | |
128 | 102 | } |
103 | + } finally { | |
104 | + _isRequesting = false; | |
129 | 105 | } |
130 | 106 | } |
131 | 107 | ... | ... |
lib/pages/section/bloc/section_event.dart
... | ... | @@ -11,14 +11,6 @@ class RequestDataEvent extends SectionEvent { |
11 | 11 | |
12 | 12 | class InitEvent extends SectionEvent {} |
13 | 13 | |
14 | -///获取视频课程内容 | |
15 | -class RequestVideoLessonEvent extends SectionEvent { | |
16 | - final String courseLessonId; | |
17 | - final int courseType; | |
18 | - | |
19 | - RequestVideoLessonEvent(this.courseLessonId, this.courseType); | |
20 | -} | |
21 | - | |
22 | 14 | ///进入课堂 |
23 | 15 | class RequestEnterClassEvent extends SectionEvent { |
24 | 16 | final String courseLessonId; | ... | ... |
lib/pages/section/bloc/section_state.dart
... | ... | @@ -7,13 +7,6 @@ class LessonInitial extends SectionState {} |
7 | 7 | |
8 | 8 | class LessonDataLoadState extends SectionState {} |
9 | 9 | |
10 | -class RequestVideoLessonState extends SectionState { | |
11 | - final String courseLessonId; | |
12 | - final int type; | |
13 | - | |
14 | - RequestVideoLessonState(this.courseLessonId, this.type); | |
15 | -} | |
16 | - | |
17 | 10 | class RequestEnterClassState extends SectionState { |
18 | 11 | final String courseLessonId; |
19 | 12 | final int courseType; | ... | ... |
lib/pages/section/section_page.dart
... | ... | @@ -60,58 +60,36 @@ class _SectionPageView extends StatelessWidget { |
60 | 60 | final bloc = BlocProvider.of<SectionBloc>(context); |
61 | 61 | return BlocListener<SectionBloc, SectionState>( |
62 | 62 | listener: (context, state) async { |
63 | - if (state is RequestVideoLessonState) { | |
64 | - final videoUrl = bloc.processEntity?.videos?.videoUrl ?? ''; | |
65 | - var title = ''; | |
66 | - if (state.type == SectionType.song.value) { | |
67 | - title = 'song'; | |
68 | - } | |
69 | - | |
70 | - if (state.type == SectionType.video.value) { | |
71 | - title = 'video'; | |
72 | - } | |
73 | - | |
74 | - if (state.type == SectionType.bouns.value) { | |
75 | - title = 'bonus'; | |
76 | - } | |
77 | - | |
78 | - if (videoUrl.isEmpty || !videoUrl.contains('http')) { | |
79 | - return; | |
80 | - } | |
81 | - pushNamed(AppRouteName.lookVideo, arguments: { | |
82 | - 'videoUrl': videoUrl, | |
83 | - 'title': title, | |
84 | - 'courseLessonId': state.courseLessonId, | |
85 | - 'isTopic': true | |
86 | - }).then((value) { | |
87 | - if (value != null) { | |
88 | - Map<String, dynamic> dataMap = value as Map<String, dynamic>; | |
89 | - bloc.add(RequestEndClassEvent( | |
90 | - dataMap['courseLessonId']!, dataMap['isCompleted'], | |
91 | - currentTime: dataMap['currentTime'], | |
92 | - autoNextSection: dataMap['nextSection'])); | |
93 | - } | |
94 | - AudioPlayerUtil.getInstance() | |
95 | - .playAudio(AudioPlayerUtilType.countWithMe); | |
96 | - }); | |
97 | - return; | |
98 | - } | |
99 | - | |
100 | 63 | if (state is RequestEnterClassState) { |
101 | - if (state.courseType != SectionType.practice.value && | |
102 | - state.courseType != SectionType.pictureBook.value) { | |
103 | - ///视频类型 | |
104 | - ///获取视频课程内容 | |
105 | - if (state.courseType == 1) { | |
106 | - AudioPlayerUtil.getInstance() | |
64 | + if (state.courseType == SectionType.song.value && | |
65 | + state.courseType == SectionType.video.value) { | |
66 | + var title = | |
67 | + state.courseType == SectionType.song.value ? 'song' : 'video'; | |
68 | + | |
69 | + ///儿歌/视频类型 | |
70 | + if (state.courseType == SectionType.song.value) { | |
71 | + await AudioPlayerUtil.getInstance() | |
107 | 72 | .playAudio(AudioPlayerUtilType.musicTime); |
108 | 73 | } else { |
109 | - AudioPlayerUtil.getInstance() | |
74 | + await AudioPlayerUtil.getInstance() | |
110 | 75 | .playAudio(AudioPlayerUtilType.videoTime); |
111 | 76 | } |
112 | - bloc.add(RequestVideoLessonEvent( | |
113 | - state.courseLessonId, state.courseType)); | |
114 | - | |
77 | + pushNamed(AppRouteName.lookVideo, arguments: { | |
78 | + 'videoUrl': "", | |
79 | + 'title': title, | |
80 | + 'courseLessonId': state.courseLessonId, | |
81 | + 'isTopic': true | |
82 | + }).then((value) { | |
83 | + if (value != null) { | |
84 | + Map<String, dynamic> dataMap = value as Map<String, dynamic>; | |
85 | + bloc.add(RequestEndClassEvent( | |
86 | + dataMap['courseLessonId']!, dataMap['isCompleted'], | |
87 | + currentTime: dataMap['currentTime'], | |
88 | + autoNextSection: dataMap['nextSection'])); | |
89 | + } | |
90 | + AudioPlayerUtil.getInstance() | |
91 | + .playAudio(AudioPlayerUtilType.countWithMe); | |
92 | + }); | |
115 | 93 | return; |
116 | 94 | } |
117 | 95 | ... | ... |
lib/pages/video/lookvideo/bloc/look_video_bloc.dart
... | ... | @@ -5,15 +5,19 @@ import 'package:wow_english/pages/section/subsection/base_section/bloc.dart'; |
5 | 5 | import 'package:wow_english/pages/section/subsection/base_section/event.dart'; |
6 | 6 | import 'package:wow_english/pages/section/subsection/base_section/state.dart'; |
7 | 7 | |
8 | +import '../../../../common/request/dao/listen_dao.dart'; | |
9 | +import '../../../../common/request/exception.dart'; | |
10 | +import '../../../../models/course_process_entity.dart'; | |
11 | +import '../../../../utils/loading.dart'; | |
12 | +import '../../../../utils/toast_util.dart'; | |
13 | + | |
8 | 14 | part 'look_video_event.dart'; |
9 | 15 | part 'look_video_state.dart'; |
10 | 16 | |
11 | 17 | class LookVideoBloc extends BaseSectionBloc<BaseSectionEvent, BaseSectionState> { |
12 | 18 | |
13 | - VideoPlayerController? _controller; | |
14 | - | |
15 | 19 | final String? _videoUrl; |
16 | - String? get videoUrl => _videoUrl; | |
20 | + String? get videoUrl => _videoUrl ?? _entity?.videos?.videoUrl ?? ''; | |
17 | 21 | final String? _typeTitle; |
18 | 22 | String? get typeTitle => _typeTitle; |
19 | 23 | final String? _courseLessonId; |
... | ... | @@ -21,12 +25,32 @@ class LookVideoBloc extends BaseSectionBloc<BaseSectionEvent, BaseSectionState> |
21 | 25 | final bool _isTopic; |
22 | 26 | bool get isTopic => _isTopic; |
23 | 27 | |
28 | + CourseProcessEntity? _entity; | |
29 | + | |
30 | + CourseProcessEntity? get entity => _entity; | |
31 | + | |
24 | 32 | LookVideoBloc(this._videoUrl, this._typeTitle, this._courseLessonId, this._isTopic) : super(LookVideoInitial()) { |
25 | 33 | on<LookVideoEvent>((event, emit) { |
26 | 34 | // TODO: implement event handler |
27 | 35 | }); |
36 | + on<RequestDataEvent>(_requestData); | |
28 | 37 | on<SectionAgainEvent>((event, emit) { |
29 | 38 | emit(SectionAgainState()); |
30 | 39 | }); |
31 | 40 | } |
41 | + | |
42 | + ///请求数据 | |
43 | + void _requestData( | |
44 | + RequestDataEvent event, Emitter<BaseSectionState> emitter) async { | |
45 | + try { | |
46 | + await loading(() async { | |
47 | + _entity = await ListenDao.process(courseLessonId); | |
48 | + emitter(RequestDataState()); | |
49 | + }); | |
50 | + } catch (e) { | |
51 | + if (e is ApiException) { | |
52 | + showToast(e.message ?? '请求失败,请检查网络连接'); | |
53 | + } | |
54 | + } | |
55 | + } | |
32 | 56 | } | ... | ... |
lib/pages/video/lookvideo/bloc/look_video_event.dart
lib/pages/video/lookvideo/bloc/look_video_state.dart
lib/pages/video/lookvideo/look_video_page.dart
... | ... | @@ -3,10 +3,15 @@ import 'package:flutter_bloc/flutter_bloc.dart'; |
3 | 3 | import 'package:wow_english/pages/section/subsection/base_section/state.dart'; |
4 | 4 | import 'package:wow_english/pages/video/lookvideo/bloc/look_video_bloc.dart'; |
5 | 5 | import 'package:wow_english/pages/video/lookvideo/widgets/video_widget.dart'; |
6 | +import 'package:wow_english/utils/log_util.dart'; | |
6 | 7 | |
7 | 8 | class LookVideoPage extends StatelessWidget { |
8 | 9 | const LookVideoPage( |
9 | - {super.key, this.videoUrl, this.typeTitle, this.courseLessonId, this.isTopic = false}); | |
10 | + {super.key, | |
11 | + this.videoUrl, | |
12 | + this.typeTitle, | |
13 | + this.courseLessonId, | |
14 | + this.isTopic = false}); | |
10 | 15 | |
11 | 16 | final String? videoUrl; |
12 | 17 | final String? typeTitle; |
... | ... | @@ -16,24 +21,34 @@ class LookVideoPage extends StatelessWidget { |
16 | 21 | @override |
17 | 22 | Widget build(BuildContext context) { |
18 | 23 | return BlocProvider( |
19 | - create: (BuildContext context) => LookVideoBloc(videoUrl, typeTitle, courseLessonId, isTopic), | |
24 | + create: (BuildContext context) => | |
25 | + LookVideoBloc(videoUrl, typeTitle, courseLessonId, isTopic) | |
26 | + ..add(RequestDataEvent()), | |
20 | 27 | child: Builder(builder: (context) => _buildPage(context)), |
21 | 28 | ); |
22 | 29 | } |
23 | 30 | } |
24 | 31 | |
25 | 32 | Widget _buildPage(BuildContext context) { |
26 | - return BlocBuilder<LookVideoBloc, BaseSectionState>(builder: (context, state) { | |
27 | - final bloc = BlocProvider.of<LookVideoBloc>(context); | |
28 | - return Container( | |
29 | - color: Colors.white, | |
30 | - child: VideoWidget( | |
31 | - videoUrl: bloc.videoUrl ?? '', | |
32 | - typeTitle: bloc.typeTitle ?? '', | |
33 | - courseLessonId: bloc.courseLessonId ?? '', | |
34 | - isTopic: bloc.isTopic, | |
35 | - ) | |
36 | - ); | |
37 | - } | |
38 | - ); | |
33 | + return BlocBuilder<LookVideoBloc, BaseSectionState>( | |
34 | + builder: (context, state) { | |
35 | + final bloc = BlocProvider.of<LookVideoBloc>(context); | |
36 | + Log.d("WQF lookvideo BlocBuilder bloc.videoUr=${bloc.videoUrl}"); | |
37 | + return Center( | |
38 | + child: bloc.videoUrl?.isNotEmpty == true | |
39 | + ? Container( | |
40 | + color: Colors.white, | |
41 | + child: VideoWidget( | |
42 | + videoUrl: bloc.videoUrl ?? '', | |
43 | + typeTitle: bloc.typeTitle ?? '', | |
44 | + courseLessonId: bloc.courseLessonId ?? '', | |
45 | + isTopic: bloc.isTopic, | |
46 | + )) | |
47 | + //todo 空了需要抽一个通用的loading组件 | |
48 | + : Container( | |
49 | + color: Colors.white, | |
50 | + child: const CircularProgressIndicator(), | |
51 | + ), | |
52 | + ); | |
53 | + }); | |
39 | 54 | } | ... | ... |
lib/pages/video/lookvideo/widgets/video_widget.dart
... | ... | @@ -12,11 +12,12 @@ import '../../../section/subsection/base_section/state.dart'; |
12 | 12 | import 'video_opera_widget.dart'; |
13 | 13 | |
14 | 14 | class VideoWidget extends StatefulWidget { |
15 | - const VideoWidget({super.key, | |
16 | - this.videoUrl = '', | |
17 | - this.typeTitle, | |
18 | - this.courseLessonId = '', | |
19 | - this.isTopic = false}); | |
15 | + const VideoWidget( | |
16 | + {super.key, | |
17 | + this.videoUrl = '', | |
18 | + this.typeTitle, | |
19 | + this.courseLessonId = '', | |
20 | + this.isTopic = false}); | |
20 | 21 | |
21 | 22 | final String videoUrl; |
22 | 23 | final String? typeTitle; |
... | ... | @@ -39,10 +40,10 @@ class _VideoWidgetState extends State<VideoWidget> { |
39 | 40 | |
40 | 41 | String formatDuration(Duration duration) { |
41 | 42 | String hours = duration.inHours.toString().padLeft(2, '0'); |
42 | - String minutes = duration.inMinutes.remainder(60).toString().padLeft( | |
43 | - 2, '0'); | |
44 | - String seconds = duration.inSeconds.remainder(60).toString().padLeft( | |
45 | - 2, '0'); | |
43 | + String minutes = | |
44 | + duration.inMinutes.remainder(60).toString().padLeft(2, '0'); | |
45 | + String seconds = | |
46 | + duration.inSeconds.remainder(60).toString().padLeft(2, '0'); | |
46 | 47 | return "$hours:$minutes:$seconds"; |
47 | 48 | } |
48 | 49 | |
... | ... | @@ -71,17 +72,17 @@ class _VideoWidgetState extends State<VideoWidget> { |
71 | 72 | _controller!.value.position.inSeconds == |
72 | 73 | _controller!.value.duration.inSeconds) { |
73 | 74 | final lookVideoBloc = context.read<LookVideoBloc>(); |
74 | - lookVideoBloc.sectionComplete(() { | |
75 | - popPage(data: { | |
76 | - 'courseLessonId': widget.courseLessonId, | |
77 | - 'currentTime': getCurrentPositionSeconds(), | |
78 | - 'isCompleted': true, | |
79 | - 'nextSection': widget.isTopic | |
80 | - }); | |
81 | - } as VoidCallback, | |
82 | - againSectionTap: (() { | |
83 | - lookVideoBloc.add(SectionAgainEvent()); | |
84 | - }), context: context); | |
75 | + lookVideoBloc.sectionComplete( | |
76 | + () { | |
77 | + popPage(data: { | |
78 | + 'courseLessonId': widget.courseLessonId, | |
79 | + 'currentTime': getCurrentPositionSeconds(), | |
80 | + 'isCompleted': true, | |
81 | + 'nextSection': widget.isTopic | |
82 | + }); | |
83 | + } as VoidCallback, againSectionTap: (() { | |
84 | + lookVideoBloc.add(SectionAgainEvent()); | |
85 | + }), context: context); | |
85 | 86 | } |
86 | 87 | } |
87 | 88 | }); |
... | ... | @@ -189,63 +190,63 @@ class _VideoWidgetState extends State<VideoWidget> { |
189 | 190 | child: Center( |
190 | 191 | child: _controller!.value.isInitialized |
191 | 192 | ? Stack( |
192 | - alignment: Alignment.center, | |
193 | - children: [ | |
194 | - SizedBox( | |
195 | - height: double.infinity, | |
196 | - width: double.infinity, | |
197 | - child: AspectRatio( | |
198 | - aspectRatio: _controller!.value.aspectRatio, | |
199 | - child: VideoPlayer(_controller!), | |
200 | - ), | |
201 | - ), | |
202 | - Offstage( | |
203 | - offstage: _hiddenTipView, | |
204 | - child: VideoOperaWidget( | |
205 | - title: widget.typeTitle ?? 'song', | |
206 | - degree: _playDegree, | |
207 | - totalTime: _totalTime, | |
208 | - currentTime: _currentTime, | |
209 | - isPlay: _controller!.value.isPlaying, | |
210 | - actionEvent: (OperationType type) { | |
211 | - actionType(type); | |
212 | - }, | |
213 | - sliderChangeEvent: (double degree) { | |
214 | - int totalSecond = _controller! | |
215 | - .value.duration.inMinutes | |
216 | - .remainder(60) * | |
217 | - 60 + | |
218 | - _controller!.value.duration.inSeconds | |
219 | - .remainder(60); | |
220 | - int positionSecond = (totalSecond * degree).toInt(); | |
221 | - _controller! | |
222 | - .seekTo(Duration(seconds: positionSecond)); | |
223 | - }, | |
224 | - ), | |
225 | - ), | |
226 | - Offstage( | |
227 | - offstage: _controller!.value.isPlaying, | |
228 | - child: IconButton( | |
229 | - onPressed: () { | |
230 | - _controller!.play(); | |
231 | - }, | |
232 | - icon: Image.asset( | |
233 | - 'video_stop'.assetPng, | |
234 | - width: 70.w, | |
235 | - height: 70.h, | |
236 | - ), | |
237 | - ), | |
238 | - ) | |
239 | - ], | |
240 | - ) | |
193 | + alignment: Alignment.center, | |
194 | + children: [ | |
195 | + SizedBox( | |
196 | + height: double.infinity, | |
197 | + width: double.infinity, | |
198 | + child: AspectRatio( | |
199 | + aspectRatio: _controller!.value.aspectRatio, | |
200 | + child: VideoPlayer(_controller!), | |
201 | + ), | |
202 | + ), | |
203 | + Offstage( | |
204 | + offstage: _hiddenTipView, | |
205 | + child: VideoOperaWidget( | |
206 | + title: widget.typeTitle ?? 'song', | |
207 | + degree: _playDegree, | |
208 | + totalTime: _totalTime, | |
209 | + currentTime: _currentTime, | |
210 | + isPlay: _controller!.value.isPlaying, | |
211 | + actionEvent: (OperationType type) { | |
212 | + actionType(type); | |
213 | + }, | |
214 | + sliderChangeEvent: (double degree) { | |
215 | + int totalSecond = _controller! | |
216 | + .value.duration.inMinutes | |
217 | + .remainder(60) * | |
218 | + 60 + | |
219 | + _controller!.value.duration.inSeconds | |
220 | + .remainder(60); | |
221 | + int positionSecond = (totalSecond * degree).toInt(); | |
222 | + _controller! | |
223 | + .seekTo(Duration(seconds: positionSecond)); | |
224 | + }, | |
225 | + ), | |
226 | + ), | |
227 | + Offstage( | |
228 | + offstage: _controller!.value.isPlaying, | |
229 | + child: IconButton( | |
230 | + onPressed: () { | |
231 | + _controller!.play(); | |
232 | + }, | |
233 | + icon: Image.asset( | |
234 | + 'video_stop'.assetPng, | |
235 | + width: 70.w, | |
236 | + height: 70.h, | |
237 | + ), | |
238 | + ), | |
239 | + ) | |
240 | + ], | |
241 | + ) | |
241 | 242 | : Container( |
242 | - color: Colors.white, | |
243 | - child: const CircularProgressIndicator(), | |
244 | - // Text( | |
245 | - // '视频加载中....', | |
246 | - // style: TextStyle(fontSize: 20.sp, color: Colors.black), | |
247 | - // ), | |
248 | - ), | |
243 | + color: Colors.white, | |
244 | + child: const CircularProgressIndicator(), | |
245 | + // Text( | |
246 | + // '视频加载中....', | |
247 | + // style: TextStyle(fontSize: 20.sp, color: Colors.black), | |
248 | + // ), | |
249 | + ), | |
249 | 250 | ), |
250 | 251 | ), |
251 | 252 | ); | ... | ... |