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 83 on<XSVoiceInitEvent>(_initVoiceSdk);
84 84 on<SelectItemEvent>(_selectItemLoad);
85 85 on<RequestDataEvent>(_requestData);
86   - on<XSVoiceTestEvent>(_voiceXsTest);
  86 + on<XSVoiceStartEvent>(_voiceXsStart);
87 87 on<XSVoiceStopEvent>(_voiceXsStop);
88 88 on<VoicePlayEvent>(_questionVoicePlay);
89 89 on<InitBlocEvent>((event, emit) {
... ... @@ -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 235 await audioPlayer.stop();
236 236 // 调用封装好的权限检查和请求方法
237 237 bool result = await permissionCheckAndRequest(
... ...
lib/pages/practice/bloc/topic_picture_event.dart
... ... @@ -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 18 final String testWord;
19 19 final String type;
20 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 10 import 'package:wow_english/route/route.dart';
11 11 import 'package:wow_english/utils/toast_util.dart';
12 12  
  13 +import '../../common/widgets/throttledGesture_gesture_detector.dart';
13 14 import 'bloc/topic_picture_bloc.dart';
14 15 import 'widgets/practice_header_widget.dart';
15 16  
... ... @@ -479,20 +480,23 @@ class _TopicPicturePage extends StatelessWidget {
479 480 ),
480 481 ),
481 482 70.verticalSpace,
482   - GestureDetector(
  483 + ThrottledGestureDetector(
  484 + throttleTime: 1000,
483 485 onTap: () {
484 486 if (bloc.voicePlayState == VoicePlayState.playing) {
485   - showToast('正在播放音,不能终止');
  487 + showToast('正在播放音,不能终止');
486 488 return;
487 489 }
488 490  
489 491 if (bloc.isVoicing) {
  492 + bloc.add(XSVoiceStopEvent());
490 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 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 502 child: Image.asset(
... ...
lib/pages/practice/topic_type.dart
... ... @@ -13,7 +13,10 @@ enum TopicType {
13 13 questionImageSelect,
14 14  
15 15 ///语音问答
16   - voiceQuestion
  16 + voiceQuestion,
  17 +
  18 + ///跟读单词(目前没实现,但是有一处判断,就先把类型定义出来)
  19 + voiceWord
17 20 }
18 21  
19 22 extension TopicTypeExtension on TopicType {
... ... @@ -29,6 +32,8 @@ extension TopicTypeExtension on TopicType {
29 32 return 4;
30 33 case TopicType.voiceQuestion:
31 34 return 5;
  35 + case TopicType.voiceWord:
  36 + return 7;
32 37 default:
33 38 throw ArgumentError('Unknown topic type');
34 39 }
... ...
lib/pages/reading/bloc/reading_bloc.dart
... ... @@ -179,7 +179,9 @@ class ReadingPageBloc
179 179 void _pageControllerChange(CurrentPageIndexChangeEvent event,
180 180 Emitter<ReadingPageState> emitter) async {
181 181 _currentPage = event.pageIndex;
  182 + debugPrint("WQF _playOriginalAudioInner begin");
182 183 _playOriginalAudioInner(null);
  184 + debugPrint("WQF _playOriginalAudioInner end");
183 185 emitter(CurrentPageIndexState());
184 186 }
185 187  
... ... @@ -227,6 +229,7 @@ class ReadingPageBloc
227 229 audioPlayer.stop();
228 230 } else {
229 231 _isOriginAudioPlaying = true;
  232 + debugPrint("WQF _playOriginalAudioInner _isOriginAudioPlaying: true");
230 233 audioUrl ??= currentPageData()?.audioUrl ?? '';
231 234 _playAudio(audioUrl);
232 235 }
... ...
lib/pages/section/section_page.dart
... ... @@ -158,15 +158,19 @@ class _SectionPageView extends StatelessWidget {
158 158 bloc.add(CurrentUnitIndexChangeEvent(index));
159 159 },
160 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 175 ), // 设置外部padding,
172 176 )),
... ...