Commit 45c862fdec0ed25a4763590ebfe64a352007dbeb

Authored by 吴启风
1 parent 8a556f76

feat:闯关交互优化-答错晃动、音效替换

assets/sounds/right.mp3 0 → 100644
No preview for this file type
assets/sounds/wrong.mp3 0 → 100644
No preview for this file type
lib/pages/practice/bloc/topic_picture_bloc.dart
  1 +import 'dart:async';
  2 +
1 import 'package:audioplayers/audioplayers.dart'; 3 import 'package:audioplayers/audioplayers.dart';
2 import 'package:flutter/cupertino.dart'; 4 import 'package:flutter/cupertino.dart';
3 import 'package:flutter/foundation.dart'; 5 import 'package:flutter/foundation.dart';
@@ -196,10 +198,8 @@ class TopicPictureBloc @@ -196,10 +198,8 @@ class TopicPictureBloc
196 void _requestData( 198 void _requestData(
197 RequestDataEvent event, Emitter<TopicPictureState> emitter) async { 199 RequestDataEvent event, Emitter<TopicPictureState> emitter) async {
198 try { 200 try {
199 - await loading(() async {  
200 - _entity = await ListenDao.process(courseLessonId);  
201 - emitter(RequestDataState());  
202 - }); 201 + _entity = await ListenDao.process(courseLessonId);
  202 + emitter(RequestDataState());
203 } catch (e) { 203 } catch (e) {
204 if (e is ApiException) { 204 if (e is ApiException) {
205 showToast(e.message ?? '请求失败,请检查网络连接'); 205 showToast(e.message ?? '请求失败,请检查网络连接');
@@ -237,19 +237,27 @@ class TopicPictureBloc @@ -237,19 +237,27 @@ class TopicPictureBloc
237 return; 237 return;
238 } 238 }
239 _selectItem = event.selectIndex; 239 _selectItem = event.selectIndex;
240 - CourseProcessTopics? topics = _entity?.topics?[_currentPage];  
241 - CourseProcessTopicsTopicAnswerList? answerList =  
242 - topics?.topicAnswerList?[_selectItem];  
243 - if (answerList?.correct == 0) {  
244 - _playResultSound(false);  
245 - // showToast('继续加油哦',duration: const Duration(seconds: 2));  
246 - } else { 240 + if (checkAnswerRight(_selectItem) == true) {
247 _playResultSound(true); 241 _playResultSound(true);
248 // showToast('恭喜你,答对啦!',duration: const Duration(seconds: 2)); 242 // showToast('恭喜你,答对啦!',duration: const Duration(seconds: 2));
  243 + } else {
  244 + _playResultSound(false);
  245 + // showToast('继续加油哦',duration: const Duration(seconds: 2));
249 } 246 }
250 emitter(SelectItemChangeState()); 247 emitter(SelectItemChangeState());
251 } 248 }
252 249
  250 + ///为空则数据异常,用于是否晃动时需要
  251 + bool? checkAnswerRight(int selectIndex) {
  252 + CourseProcessTopics? topics = _entity?.topics?[_currentPage];
  253 + if (topics == null || topics.topicAnswerList == null || selectIndex < 0 || selectIndex >= topics.topicAnswerList!.length) {
  254 + return null;
  255 + }
  256 + CourseProcessTopicsTopicAnswerList? answerList =
  257 + topics.topicAnswerList?[selectIndex];
  258 + return answerList?.correct != 0;
  259 + }
  260 +
253 ///初始化SDK 261 ///初始化SDK
254 _initVoiceSdk( 262 _initVoiceSdk(
255 XSVoiceInitEvent event, Emitter<TopicPictureState> emitter) async { 263 XSVoiceInitEvent event, Emitter<TopicPictureState> emitter) async {
@@ -338,7 +346,7 @@ class TopicPictureBloc @@ -338,7 +346,7 @@ class TopicPictureBloc
338 if (isCorrect) { 346 if (isCorrect) {
339 await audioPlayer.play(AssetSource('correct_voice'.assetMp3)); 347 await audioPlayer.play(AssetSource('correct_voice'.assetMp3));
340 } else { 348 } else {
341 - await audioPlayer.play(AssetSource('incorrect_voice'.assetMp3)); 349 + await audioPlayer.play(AssetSource('wrong'.assetMp3));
342 } 350 }
343 } 351 }
344 352
lib/pages/practice/topic_picture_page.dart
@@ -7,6 +7,7 @@ import &#39;package:wow_english/common/extension/string_extension.dart&#39;; @@ -7,6 +7,7 @@ import &#39;package:wow_english/common/extension/string_extension.dart&#39;;
7 import 'package:wow_english/common/widgets/ow_image_widget.dart'; 7 import 'package:wow_english/common/widgets/ow_image_widget.dart';
8 import 'package:wow_english/models/course_process_entity.dart'; 8 import 'package:wow_english/models/course_process_entity.dart';
9 import 'package:wow_english/pages/practice/topic_type.dart'; 9 import 'package:wow_english/pages/practice/topic_type.dart';
  10 +import 'package:wow_english/pages/practice/widgets/shake_widget.dart';
10 import 'package:wow_english/route/route.dart'; 11 import 'package:wow_english/route/route.dart';
11 import 'package:wow_english/utils/toast_util.dart'; 12 import 'package:wow_english/utils/toast_util.dart';
12 13
@@ -82,39 +83,45 @@ class _TopicPicturePage extends StatelessWidget { @@ -82,39 +83,45 @@ class _TopicPicturePage extends StatelessWidget {
82 }, 83 },
83 ), 84 ),
84 35.verticalSpace, 85 35.verticalSpace,
85 - Expanded(  
86 - child: PageView.builder(  
87 - itemCount: bloc.entity?.topics?.length,  
88 - scrollDirection: Axis.horizontal,  
89 - controller: bloc.pageController,  
90 - onPageChanged: (int index) {  
91 - bloc.add(CurrentPageIndexChangeEvent(index));  
92 - },  
93 - itemBuilder: (BuildContext context, int index) {  
94 - CourseProcessTopics? topics =  
95 - bloc.entity?.topics![index];  
96 - if (topics?.type ==  
97 - TopicType.audioImageSelect.value) {  
98 - //听音选图  
99 - return _pageViewVoicePictureItemWidget(topics);  
100 - } else if (topics?.type ==  
101 - TopicType.audioCharSelect.value) {  
102 - //听音选字  
103 - return _pageViewVoiceWordItemWidget(topics);  
104 - } else if (topics?.type ==  
105 - TopicType.questionCharSelect.value) {  
106 - //看题选字  
107 - return _pageViewWordItemWidget(topics);  
108 - } else if (topics?.type ==  
109 - TopicType.questionImageSelect.value) {  
110 - //看题选图  
111 - return _pageViewItemWidget(topics);  
112 - } else {  
113 - //语音问答  
114 - return _voiceAnswerItem(topics);  
115 - }  
116 - }),  
117 - ) 86 + bloc.entity != null
  87 + ? Expanded(
  88 + child: PageView.builder(
  89 + itemCount: bloc.entity?.topics?.length,
  90 + scrollDirection: Axis.horizontal,
  91 + controller: bloc.pageController,
  92 + onPageChanged: (int index) {
  93 + bloc.add(CurrentPageIndexChangeEvent(index));
  94 + },
  95 + itemBuilder: (BuildContext context, int index) {
  96 + CourseProcessTopics? topics =
  97 + bloc.entity?.topics![index];
  98 + if (topics?.type ==
  99 + TopicType.audioImageSelect.value) {
  100 + //听音选图
  101 + return _pageViewVoicePictureItemWidget(
  102 + topics);
  103 + } else if (topics?.type ==
  104 + TopicType.audioCharSelect.value) {
  105 + //听音选字
  106 + return _pageViewVoiceWordItemWidget(topics);
  107 + } else if (topics?.type ==
  108 + TopicType.questionCharSelect.value) {
  109 + //看题选字
  110 + return _pageViewWordItemWidget(topics);
  111 + } else if (topics?.type ==
  112 + TopicType.questionImageSelect.value) {
  113 + //看题选图
  114 + return _pageViewItemWidget(topics);
  115 + } else {
  116 + //语音问答
  117 + return _voiceAnswerItem(topics);
  118 + }
  119 + }),
  120 + )
  121 + : Container(
  122 + color: Colors.transparent,
  123 + child: const CircularProgressIndicator(),
  124 + ),
118 ], 125 ],
119 ) 126 )
120 ], 127 ],
@@ -157,29 +164,34 @@ class _TopicPicturePage extends StatelessWidget { @@ -157,29 +164,34 @@ class _TopicPicturePage extends StatelessWidget {
157 buildWhen: (_, s) => s is SelectItemChangeState, 164 buildWhen: (_, s) => s is SelectItemChangeState,
158 builder: (context, state) { 165 builder: (context, state) {
159 final bloc = BlocProvider.of<TopicPictureBloc>(context); 166 final bloc = BlocProvider.of<TopicPictureBloc>(context);
  167 + final shouldShake = (bloc.selectItem == index &&
  168 + bloc.checkAnswerRight(index) == false);
160 return Container( 169 return Container(
161 padding: EdgeInsets.symmetric(horizontal: 10.w), 170 padding: EdgeInsets.symmetric(horizontal: 10.w),
162 child: GestureDetector( 171 child: GestureDetector(
163 onTap: () => bloc.add(SelectItemEvent(index)), 172 onTap: () => bloc.add(SelectItemEvent(index)),
164 - child: Container(  
165 - padding: const EdgeInsets.all(4.5),  
166 - decoration: BoxDecoration(  
167 - color: bloc.selectItem == index  
168 - ? const Color(0xFF00B6F1)  
169 - : Colors.white,  
170 - borderRadius: BorderRadius.circular(15),  
171 - ),  
172 - height: 143.h,  
173 - width: 143.w, 173 + child: ShakeWidget(
  174 + shouldShake: shouldShake,
174 child: Container( 175 child: Container(
  176 + padding: const EdgeInsets.all(4.5),
175 decoration: BoxDecoration( 177 decoration: BoxDecoration(
176 - color: Colors.white,  
177 - borderRadius: BorderRadius.circular(15),  
178 - border: Border.all(  
179 - width: 1.0, color: const Color(0xFF140C10)),  
180 - image: DecorationImage(  
181 - fit: BoxFit.fitWidth,  
182 - image: NetworkImage(answerLis?.picUrl ?? ''))), 178 + color: bloc.selectItem == index
  179 + ? const Color(0xFF00B6F1)
  180 + : Colors.white,
  181 + borderRadius: BorderRadius.circular(15),
  182 + ),
  183 + height: 143.h,
  184 + width: 143.w,
  185 + child: Container(
  186 + decoration: BoxDecoration(
  187 + color: Colors.white,
  188 + borderRadius: BorderRadius.circular(15),
  189 + border: Border.all(
  190 + width: 1.0, color: const Color(0xFF140C10)),
  191 + image: DecorationImage(
  192 + fit: BoxFit.fitWidth,
  193 + image: NetworkImage(answerLis?.picUrl ?? ''))),
  194 + ),
183 ), 195 ),
184 ), 196 ),
185 ), 197 ),
@@ -221,48 +233,53 @@ class _TopicPicturePage extends StatelessWidget { @@ -221,48 +233,53 @@ class _TopicPicturePage extends StatelessWidget {
221 buildWhen: (_, s) => s is SelectItemChangeState, 233 buildWhen: (_, s) => s is SelectItemChangeState,
222 builder: (context, state) { 234 builder: (context, state) {
223 final bloc = BlocProvider.of<TopicPictureBloc>(context); 235 final bloc = BlocProvider.of<TopicPictureBloc>(context);
  236 + final shouldShake = (bloc.selectItem == index &&
  237 + bloc.checkAnswerRight(index) == false);
224 return Container( 238 return Container(
225 padding: EdgeInsets.symmetric(horizontal: 10.w), 239 padding: EdgeInsets.symmetric(horizontal: 10.w),
226 child: GestureDetector( 240 child: GestureDetector(
227 onTap: () => bloc.add(SelectItemEvent(index)), 241 onTap: () => bloc.add(SelectItemEvent(index)),
228 - child: Container(  
229 - width: 143.w,  
230 - height: 143.h,  
231 - padding: EdgeInsets.only(  
232 - left: 13.w, right: 13.w, top: 13.h, bottom: 13.h),  
233 - decoration: BoxDecoration(  
234 - color: Colors.white,  
235 - borderRadius: BorderRadius.circular(15),  
236 - border:  
237 - Border.all(width: 1.0, color: const Color(0xFF140C10)),  
238 - ),  
239 - child: Column(  
240 - mainAxisAlignment: MainAxisAlignment.end,  
241 - children: [  
242 - Expanded(  
243 - child: Container(  
244 - alignment: Alignment.center,  
245 - child: Text(answerLis?.word ?? '',  
246 - style: TextStyle(  
247 - fontSize: 20.sp,  
248 - color: const Color(0xFF333333))),  
249 - ),  
250 - ),  
251 - Container(  
252 - height: 30.h,  
253 - width: double.infinity,  
254 - decoration: BoxDecoration(  
255 - color: bloc.selectItem == index  
256 - ? const Color(0xFF00B6F1)  
257 - : Colors.white,  
258 - borderRadius: BorderRadius.circular(15.r),  
259 - border: Border.all(  
260 - width: 1.5, color: const Color(0xFF140C10)), 242 + child: ShakeWidget(
  243 + shouldShake: shouldShake,
  244 + child: Container(
  245 + width: 143.w,
  246 + height: 143.h,
  247 + padding: EdgeInsets.only(
  248 + left: 13.w, right: 13.w, top: 13.h, bottom: 13.h),
  249 + decoration: BoxDecoration(
  250 + color: Colors.white,
  251 + borderRadius: BorderRadius.circular(15),
  252 + border: Border.all(
  253 + width: 1.0, color: const Color(0xFF140C10)),
  254 + ),
  255 + child: Column(
  256 + mainAxisAlignment: MainAxisAlignment.end,
  257 + children: [
  258 + Expanded(
  259 + child: Container(
  260 + alignment: Alignment.center,
  261 + child: Text(answerLis?.word ?? '',
  262 + style: TextStyle(
  263 + fontSize: 20.sp,
  264 + color: const Color(0xFF333333))),
  265 + ),
261 ), 266 ),
262 - alignment: Alignment.center,  
263 - child: Image.asset('choose'.assetPng),  
264 - )  
265 - ], 267 + Container(
  268 + height: 30.h,
  269 + width: double.infinity,
  270 + decoration: BoxDecoration(
  271 + color: bloc.selectItem == index
  272 + ? const Color(0xFF00B6F1)
  273 + : Colors.white,
  274 + borderRadius: BorderRadius.circular(15.r),
  275 + border: Border.all(
  276 + width: 1.5, color: const Color(0xFF140C10)),
  277 + ),
  278 + alignment: Alignment.center,
  279 + child: Image.asset('choose'.assetPng),
  280 + )
  281 + ],
  282 + ),
266 ), 283 ),
267 ), 284 ),
268 ), 285 ),
@@ -322,27 +339,32 @@ class _TopicPicturePage extends StatelessWidget { @@ -322,27 +339,32 @@ class _TopicPicturePage extends StatelessWidget {
322 buildWhen: (_, s) => s is SelectItemChangeState, 339 buildWhen: (_, s) => s is SelectItemChangeState,
323 builder: (context, state) { 340 builder: (context, state) {
324 final bloc = BlocProvider.of<TopicPictureBloc>(context); 341 final bloc = BlocProvider.of<TopicPictureBloc>(context);
325 - return Container(  
326 - padding: EdgeInsets.symmetric(horizontal: 20.w),  
327 - child: GestureDetector(  
328 - onTap: () => bloc.add(SelectItemEvent(index)),  
329 - child: Container(  
330 - padding: const EdgeInsets.all(4.5),  
331 - decoration: BoxDecoration(  
332 - color: bloc.selectItem == index  
333 - ? const Color(0xFF00B6F1)  
334 - : Colors.white,  
335 - borderRadius: BorderRadius.circular(15),  
336 - ),  
337 - height: 143.h,  
338 - width: 163.w, 342 + final shouldShake = (bloc.selectItem == index &&
  343 + bloc.checkAnswerRight(index) == false);
  344 + return ShakeWidget(
  345 + shouldShake: shouldShake,
  346 + child: Container(
  347 + padding: EdgeInsets.symmetric(horizontal: 20.w),
  348 + child: GestureDetector(
  349 + onTap: () => bloc.add(SelectItemEvent(index)),
339 child: Container( 350 child: Container(
  351 + padding: const EdgeInsets.all(4.5),
340 decoration: BoxDecoration( 352 decoration: BoxDecoration(
341 - color: Colors.white,  
342 - borderRadius: BorderRadius.circular(15),  
343 - image: DecorationImage(  
344 - fit: BoxFit.fill,  
345 - image: NetworkImage(answerList?.picUrl ?? ''))), 353 + color: bloc.selectItem == index
  354 + ? const Color(0xFF00B6F1)
  355 + : Colors.white,
  356 + borderRadius: BorderRadius.circular(15),
  357 + ),
  358 + height: 143.h,
  359 + width: 163.w,
  360 + child: Container(
  361 + decoration: BoxDecoration(
  362 + color: Colors.white,
  363 + borderRadius: BorderRadius.circular(15),
  364 + image: DecorationImage(
  365 + fit: BoxFit.fill,
  366 + image: NetworkImage(answerList?.picUrl ?? ''))),
  367 + ),
346 ), 368 ),
347 ), 369 ),
348 ), 370 ),
@@ -391,50 +413,55 @@ class _TopicPicturePage extends StatelessWidget { @@ -391,50 +413,55 @@ class _TopicPicturePage extends StatelessWidget {
391 buildWhen: (_, s) => s is SelectItemChangeState, 413 buildWhen: (_, s) => s is SelectItemChangeState,
392 builder: (context, state) { 414 builder: (context, state) {
393 final bloc = BlocProvider.of<TopicPictureBloc>(context); 415 final bloc = BlocProvider.of<TopicPictureBloc>(context);
  416 + final shouldShake = (bloc.selectItem == index &&
  417 + bloc.checkAnswerRight(index) == false);
394 return GestureDetector( 418 return GestureDetector(
395 onTap: () => bloc.add(SelectItemEvent(index)), 419 onTap: () => bloc.add(SelectItemEvent(index)),
396 - child: Container(  
397 - width: 163.w,  
398 - height: 143.h,  
399 - padding: EdgeInsets.symmetric(horizontal: 10.w), 420 + child: ShakeWidget(
  421 + shouldShake: shouldShake,
400 child: Container( 422 child: Container(
401 - width: 143.w, 423 + width: 163.w,
402 height: 143.h, 424 height: 143.h,
403 - padding: EdgeInsets.only(  
404 - left: 13.w, right: 13.w, top: 13.h, bottom: 13.h),  
405 - decoration: BoxDecoration(  
406 - color: Colors.white,  
407 - borderRadius: BorderRadius.circular(15),  
408 - border:  
409 - Border.all(width: 1.0, color: const Color(0xFF140C10)),  
410 - ),  
411 - child: Column(  
412 - mainAxisAlignment: MainAxisAlignment.end,  
413 - children: [  
414 - Expanded(  
415 - child: Container(  
416 - alignment: Alignment.center,  
417 - child: Text(answerList.word ?? '',  
418 - style: TextStyle(  
419 - fontSize: 20.sp,  
420 - color: const Color(0xFF333333))),  
421 - ),  
422 - ),  
423 - Container(  
424 - height: 30.h,  
425 - width: double.infinity,  
426 - decoration: BoxDecoration(  
427 - color: bloc.selectItem == index  
428 - ? const Color(0xFF00B6F1)  
429 - : Colors.white,  
430 - borderRadius: BorderRadius.circular(15.r),  
431 - border: Border.all(  
432 - width: 1.5, color: const Color(0xFF140C10)), 425 + padding: EdgeInsets.symmetric(horizontal: 10.w),
  426 + child: Container(
  427 + width: 143.w,
  428 + height: 143.h,
  429 + padding: EdgeInsets.only(
  430 + left: 13.w, right: 13.w, top: 13.h, bottom: 13.h),
  431 + decoration: BoxDecoration(
  432 + color: Colors.white,
  433 + borderRadius: BorderRadius.circular(15),
  434 + border: Border.all(
  435 + width: 1.0, color: const Color(0xFF140C10)),
  436 + ),
  437 + child: Column(
  438 + mainAxisAlignment: MainAxisAlignment.end,
  439 + children: [
  440 + Expanded(
  441 + child: Container(
  442 + alignment: Alignment.center,
  443 + child: Text(answerList.word ?? '',
  444 + style: TextStyle(
  445 + fontSize: 20.sp,
  446 + color: const Color(0xFF333333))),
  447 + ),
433 ), 448 ),
434 - alignment: Alignment.center,  
435 - child: Image.asset('choose'.assetPng),  
436 - )  
437 - ], 449 + Container(
  450 + height: 30.h,
  451 + width: double.infinity,
  452 + decoration: BoxDecoration(
  453 + color: bloc.selectItem == index
  454 + ? const Color(0xFF00B6F1)
  455 + : Colors.white,
  456 + borderRadius: BorderRadius.circular(15.r),
  457 + border: Border.all(
  458 + width: 1.5, color: const Color(0xFF140C10)),
  459 + ),
  460 + alignment: Alignment.center,
  461 + child: Image.asset('choose'.assetPng),
  462 + )
  463 + ],
  464 + ),
438 ), 465 ),
439 ), 466 ),
440 ), 467 ),
lib/pages/practice/widgets/shake_widget.dart 0 → 100644
  1 +import 'package:flutter/material.dart';
  2 +
  3 +import '../../../utils/log_util.dart';
  4 +
  5 +class ShakeWidget extends StatefulWidget {
  6 + final Widget child;
  7 + final int shakeCount;
  8 + final double shakeOffset;
  9 + final Duration duration;
  10 + final bool shouldShake;
  11 +
  12 + const ShakeWidget({
  13 + Key? key,
  14 + required this.child,
  15 + this.shakeCount = 2,
  16 + this.shakeOffset = 10.0,
  17 + this.duration = const Duration(milliseconds: 500),
  18 + this.shouldShake = false,
  19 + }) : super(key: key);
  20 +
  21 + @override
  22 + _ShakeWidgetState createState() => _ShakeWidgetState();
  23 +}
  24 +
  25 +class _ShakeWidgetState extends State<ShakeWidget> with SingleTickerProviderStateMixin {
  26 + late AnimationController _controller;
  27 + late Animation<double> _animation;
  28 +
  29 + @override
  30 + void initState() {
  31 + super.initState();
  32 + _controller = AnimationController(
  33 + vsync: this,
  34 + duration: widget.duration,
  35 + );
  36 +
  37 + _animation = TweenSequence([
  38 + TweenSequenceItem(
  39 + tween: Tween(begin: 0.0, end: widget.shakeOffset)
  40 + .chain(CurveTween(curve: Curves.easeInOut)),
  41 + weight: 1,
  42 + ),
  43 + TweenSequenceItem(
  44 + tween: Tween(begin: widget.shakeOffset, end: -widget.shakeOffset)
  45 + .chain(CurveTween(curve: Curves.easeInOut)),
  46 + weight: 1,
  47 + ),
  48 + TweenSequenceItem(
  49 + tween: Tween(begin: -widget.shakeOffset, end: widget.shakeOffset)
  50 + .chain(CurveTween(curve: Curves.easeInOut)),
  51 + weight: 1,
  52 + ),
  53 + TweenSequenceItem(
  54 + tween: Tween(begin: widget.shakeOffset, end: -widget.shakeOffset)
  55 + .chain(CurveTween(curve: Curves.easeInOut)),
  56 + weight: 1,
  57 + ),
  58 + TweenSequenceItem(
  59 + tween: Tween(begin: -widget.shakeOffset, end: 0.0)
  60 + .chain(CurveTween(curve: Curves.easeInOut)),
  61 + weight: 1,
  62 + ),
  63 + ]).animate(_controller);
  64 + }
  65 +
  66 + @override
  67 + void didUpdateWidget(covariant ShakeWidget oldWidget) {
  68 + super.didUpdateWidget(oldWidget);
  69 + Log.d("WQF didUpdateWidget widget.shouldShake=${widget.shouldShake} oldWidget.shouldShake=${oldWidget.shouldShake}");
  70 + // if (widget.shouldShake && !oldWidget.shouldShake) {
  71 + if (widget.shouldShake) {
  72 + _controller.forward(from: 0.0);
  73 + }
  74 + }
  75 +
  76 + @override
  77 + void dispose() {
  78 + _controller.dispose();
  79 + super.dispose();
  80 + }
  81 +
  82 + @override
  83 + Widget build(BuildContext context) {
  84 + return AnimatedBuilder(
  85 + animation: _animation,
  86 + builder: (context, child) {
  87 + return Transform.translate(
  88 + offset: Offset(_animation.value, 0),
  89 + child: widget.child,
  90 + );
  91 + },
  92 + child: widget.child,
  93 + );
  94 + }
  95 +}
0 \ No newline at end of file 96 \ No newline at end of file