Commit ae77d87f712af52159b6f8c06f665bd7a02a8e5b

Authored by 吴启风
1 parent 5b923179

feat:fix语音题无法手动停止问题;优化录音按钮点击响应

lib/common/widgets/throttledGesture_gesture_detector.dart 0 → 100644
  1 +import 'dart:async';
  2 +import 'package:flutter/material.dart';
  3 +
  4 +///带节流功能的GestureDetector
  5 +class ThrottledGestureDetector extends StatefulWidget {
  6 + final Widget child;
  7 + final VoidCallback onTap;
  8 + final int throttleTime;
  9 +
  10 + const ThrottledGestureDetector({
  11 + super.key,
  12 + required this.child,
  13 + required this.onTap,
  14 + this.throttleTime = 500, // 默认节流时间为500毫秒
  15 + });
  16 +
  17 + @override
  18 + _ThrottledGestureDetectorState createState() =>
  19 + _ThrottledGestureDetectorState();
  20 +}
  21 +
  22 +class _ThrottledGestureDetectorState extends State<ThrottledGestureDetector> {
  23 + bool _isThrottled = false;
  24 +
  25 + void _handleTap() {
  26 + if (!_isThrottled) {
  27 + widget.onTap();
  28 + _isThrottled = true;
  29 + Timer(Duration(milliseconds: widget.throttleTime), () {
  30 + _isThrottled = false;
  31 + });
  32 + }
  33 + }
  34 +
  35 + @override
  36 + Widget build(BuildContext context) {
  37 + return GestureDetector(
  38 + onTap: _handleTap,
  39 + child: widget.child,
  40 + );
  41 + }
  42 +}
lib/pages/practice/bloc/topic_picture_bloc.dart
@@ -83,7 +83,7 @@ class TopicPictureBloc extends BaseSectionBloc&lt;TopicPictureEvent, TopicPictureSt @@ -83,7 +83,7 @@ class TopicPictureBloc extends BaseSectionBloc&lt;TopicPictureEvent, TopicPictureSt
83 on<XSVoiceInitEvent>(_initVoiceSdk); 83 on<XSVoiceInitEvent>(_initVoiceSdk);
84 on<SelectItemEvent>(_selectItemLoad); 84 on<SelectItemEvent>(_selectItemLoad);
85 on<RequestDataEvent>(_requestData); 85 on<RequestDataEvent>(_requestData);
86 - on<XSVoiceTestEvent>(_voiceXsTest); 86 + on<XSVoiceStartEvent>(_voiceXsStart);
87 on<XSVoiceStopEvent>(_voiceXsStop); 87 on<XSVoiceStopEvent>(_voiceXsStop);
88 on<VoicePlayEvent>(_questionVoicePlay); 88 on<VoicePlayEvent>(_questionVoicePlay);
89 on<InitBlocEvent>((event, emit) { 89 on<InitBlocEvent>((event, emit) {
@@ -231,7 +231,7 @@ class TopicPictureBloc extends BaseSectionBloc&lt;TopicPictureEvent, TopicPictureSt @@ -231,7 +231,7 @@ class TopicPictureBloc extends BaseSectionBloc&lt;TopicPictureEvent, TopicPictureSt
231 } 231 }
232 232
233 ///先声测试 233 ///先声测试
234 - void _voiceXsTest(XSVoiceTestEvent event,Emitter<TopicPictureState> emitter) async { 234 + void _voiceXsStart(XSVoiceStartEvent event,Emitter<TopicPictureState> emitter) async {
235 await audioPlayer.stop(); 235 await audioPlayer.stop();
236 // 调用封装好的权限检查和请求方法 236 // 调用封装好的权限检查和请求方法
237 bool result = await permissionCheckAndRequest( 237 bool result = await permissionCheckAndRequest(
lib/pages/practice/bloc/topic_picture_event.dart
@@ -14,11 +14,11 @@ class XSVoiceInitEvent extends TopicPictureEvent { @@ -14,11 +14,11 @@ class XSVoiceInitEvent extends TopicPictureEvent {
14 } 14 }
15 15
16 ///开始评测 16 ///开始评测
17 -class XSVoiceTestEvent extends TopicPictureEvent { 17 +class XSVoiceStartEvent extends TopicPictureEvent {
18 final String testWord; 18 final String testWord;
19 final String type; 19 final String type;
20 final String userId; 20 final String userId;
21 - XSVoiceTestEvent(this.testWord,this.type,this.userId); 21 + XSVoiceStartEvent(this.testWord,this.type,this.userId);
22 } 22 }
23 23
24 ///终止评测 24 ///终止评测
lib/pages/practice/topic_picture_page.dart
@@ -10,6 +10,7 @@ import &#39;package:wow_english/pages/practice/topic_type.dart&#39;; @@ -10,6 +10,7 @@ import &#39;package:wow_english/pages/practice/topic_type.dart&#39;;
10 import 'package:wow_english/route/route.dart'; 10 import 'package:wow_english/route/route.dart';
11 import 'package:wow_english/utils/toast_util.dart'; 11 import 'package:wow_english/utils/toast_util.dart';
12 12
  13 +import '../../common/widgets/throttledGesture_gesture_detector.dart';
13 import 'bloc/topic_picture_bloc.dart'; 14 import 'bloc/topic_picture_bloc.dart';
14 import 'widgets/practice_header_widget.dart'; 15 import 'widgets/practice_header_widget.dart';
15 16
@@ -479,20 +480,23 @@ class _TopicPicturePage extends StatelessWidget { @@ -479,20 +480,23 @@ class _TopicPicturePage extends StatelessWidget {
479 ), 480 ),
480 ), 481 ),
481 70.verticalSpace, 482 70.verticalSpace,
482 - GestureDetector( 483 + ThrottledGestureDetector(
  484 + throttleTime: 1000,
483 onTap: () { 485 onTap: () {
484 if (bloc.voicePlayState == VoicePlayState.playing) { 486 if (bloc.voicePlayState == VoicePlayState.playing) {
485 - showToast('正在播放音,不能终止'); 487 + showToast('正在播放音,不能终止');
486 return; 488 return;
487 } 489 }
488 490
489 if (bloc.isVoicing) { 491 if (bloc.isVoicing) {
  492 + bloc.add(XSVoiceStopEvent());
490 return; 493 return;
491 } 494 }
492 - if (topics?.type == 5 || topics?.type == 7) {  
493 - bloc.add(XSVoiceTestEvent(topics?.keyWord??'', '0',UserUtil.getUser()!.id.toString())); 495 + if (topics?.type == TopicType.voiceQuestion.value ||
  496 + topics?.type == TopicType.voiceWord.value) {
  497 + bloc.add(XSVoiceStartEvent(topics?.keyWord??'', '0',UserUtil.getUser()!.id.toString()));
494 } else { 498 } else {
495 - bloc.add(XSVoiceTestEvent(topics?.word??'', '0',UserUtil.getUser()!.id.toString())); 499 + bloc.add(XSVoiceStartEvent(topics?.word??'', '0',UserUtil.getUser()!.id.toString()));
496 } 500 }
497 }, 501 },
498 child: Image.asset( 502 child: Image.asset(
lib/pages/practice/topic_type.dart
@@ -13,7 +13,10 @@ enum TopicType { @@ -13,7 +13,10 @@ enum TopicType {
13 questionImageSelect, 13 questionImageSelect,
14 14
15 ///语音问答 15 ///语音问答
16 - voiceQuestion 16 + voiceQuestion,
  17 +
  18 + ///跟读单词(目前没实现,但是有一处判断,就先把类型定义出来)
  19 + voiceWord
17 } 20 }
18 21
19 extension TopicTypeExtension on TopicType { 22 extension TopicTypeExtension on TopicType {
@@ -29,6 +32,8 @@ extension TopicTypeExtension on TopicType { @@ -29,6 +32,8 @@ extension TopicTypeExtension on TopicType {
29 return 4; 32 return 4;
30 case TopicType.voiceQuestion: 33 case TopicType.voiceQuestion:
31 return 5; 34 return 5;
  35 + case TopicType.voiceWord:
  36 + return 7;
32 default: 37 default:
33 throw ArgumentError('Unknown topic type'); 38 throw ArgumentError('Unknown topic type');
34 } 39 }
lib/pages/reading/bloc/reading_bloc.dart
@@ -179,7 +179,9 @@ class ReadingPageBloc @@ -179,7 +179,9 @@ class ReadingPageBloc
179 void _pageControllerChange(CurrentPageIndexChangeEvent event, 179 void _pageControllerChange(CurrentPageIndexChangeEvent event,
180 Emitter<ReadingPageState> emitter) async { 180 Emitter<ReadingPageState> emitter) async {
181 _currentPage = event.pageIndex; 181 _currentPage = event.pageIndex;
  182 + debugPrint("WQF _playOriginalAudioInner begin");
182 _playOriginalAudioInner(null); 183 _playOriginalAudioInner(null);
  184 + debugPrint("WQF _playOriginalAudioInner end");
183 emitter(CurrentPageIndexState()); 185 emitter(CurrentPageIndexState());
184 } 186 }
185 187
@@ -227,6 +229,7 @@ class ReadingPageBloc @@ -227,6 +229,7 @@ class ReadingPageBloc
227 audioPlayer.stop(); 229 audioPlayer.stop();
228 } else { 230 } else {
229 _isOriginAudioPlaying = true; 231 _isOriginAudioPlaying = true;
  232 + debugPrint("WQF _playOriginalAudioInner _isOriginAudioPlaying: true");
230 audioUrl ??= currentPageData()?.audioUrl ?? ''; 233 audioUrl ??= currentPageData()?.audioUrl ?? '';
231 _playAudio(audioUrl); 234 _playAudio(audioUrl);
232 } 235 }
lib/pages/section/section_page.dart
@@ -158,15 +158,19 @@ class _SectionPageView extends StatelessWidget { @@ -158,15 +158,19 @@ class _SectionPageView extends StatelessWidget {
158 bloc.add(CurrentUnitIndexChangeEvent(index)); 158 bloc.add(CurrentUnitIndexChangeEvent(index));
159 }, 159 },
160 itemBuilder: (context, index) { 160 itemBuilder: (context, index) {
161 - return ScrollConfiguration(  
162 - ///去掉 Android 上默认的边缘拖拽效果  
163 - behavior: ScrollConfiguration.of(context)  
164 - .copyWith(overscroll: false),  
165 - child: _itemTransCard(  
166 - bloc.getCourseUnitDetail(pageIndex: index),  
167 - index,  
168 - context),  
169 - ); 161 + // return ScrollConfiguration(
  162 + // ///去掉 Android 上默认的边缘拖拽效果
  163 + // behavior: ScrollConfiguration.of(context)
  164 + // .copyWith(overscroll: false),
  165 + // child: _itemTransCard(
  166 + // bloc.getCourseUnitDetail(pageIndex: index),
  167 + // index,
  168 + // context),
  169 + // );
  170 + return _itemTransCard(
  171 + bloc.getCourseUnitDetail(pageIndex: index),
  172 + index,
  173 + context);
170 }), 174 }),
171 ), // 设置外部padding, 175 ), // 设置外部padding,
172 )), 176 )),