Commit 842b7132f392105f396d8d52fba4d9bb321abe8f

Authored by liangchengyou
1 parent c95453ce

feat:磨耳朵/练习页面调整

Showing 37 changed files with 526 additions and 1038 deletions
lib/pages/home/bloc/home_bloc.dart
... ... @@ -21,23 +21,10 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> {
21 21 on<RequestDataEvent>(_requestData);
22 22 }
23 23  
24   - Future<void> requestData() async {
25   - try {
26   - await loading(() async {
27   - _modelData = await HomeDao.courseLesson(moduleId: moduleId??'');
28   - emit(HomeDataLoadState());
29   - });
30   - } catch (e) {
31   - if (e is ApiException) {
32   - EasyLoading.showToast(e.message.toString());
33   - }
34   - }
35   - }
36   -
37 24 void _requestData(RequestDataEvent event, Emitter<HomeState> emitter) async {
38 25 try {
39 26 await loading(() async {
40   - HomeDao.courseLesson();
  27 + _modelData = await HomeDao.courseLesson(moduleId: moduleId??'');
41 28 emitter(HomeDataLoadState());
42 29 });
43 30 } catch (e) {
... ...
lib/pages/home/home_page.dart
... ... @@ -20,7 +20,7 @@ class HomePage extends StatelessWidget {
20 20 @override
21 21 Widget build(BuildContext context) {
22 22 return BlocProvider(
23   - create: (context) => HomeBloc(moduleId)..requestData(),
  23 + create: (context) => HomeBloc(moduleId)..add(RequestDataEvent()),
24 24 child: _HomePageView(),
25 25 );
26 26 }
... ... @@ -37,7 +37,8 @@ class _HomePageView extends StatelessWidget {
37 37 } else if (type == HeaderActionType.shop) {
38 38 Navigator.of(AppRouter.context).pushNamed(AppRouteName.shop);
39 39 } else if (type == HeaderActionType.user) {
40   - Navigator.of(AppRouter.context).pushNamed(AppRouteName.user);
  40 + Navigator.of(AppRouter.context).pushNamed(AppRouteName.topicPic);
  41 + // Navigator.of(AppRouter.context).pushNamed(AppRouteName.user);
41 42 } else {
42 43 // Navigator.of(AppRouter.context).pushNamed(AppRouteName.topicPic);
43 44 // Navigator.of(AppRouter.context).pushNamed(AppRouteName.topicWord);
... ... @@ -132,6 +133,7 @@ class _HomePageView extends StatelessWidget {
132 133 'blue-positive'.assetPng,
133 134 height: 47.h,
134 135 width: 80.w,
  136 + // color: Colors.red,
135 137 ),
136 138 ],
137 139 ),
... ...
lib/pages/lessons/bloc/lesson_bloc.dart
1 1 import 'package:flutter/cupertino.dart';
2 2 import 'package:flutter_bloc/flutter_bloc.dart';
  3 +import 'package:flutter_easyloading/flutter_easyloading.dart';
3 4 import 'package:wow_english/common/request/dao/home_dao.dart';
4 5 import 'package:wow_english/common/request/exception.dart';
5 6 import 'package:wow_english/models/course_module_entity.dart';
... ... @@ -25,26 +26,28 @@ class LessonBloc extends Bloc&lt;LessonEvent, LessonState&gt; {
25 26 LessonBloc(this.pageIndex,this.pageController) : super(LessonInitial()) {
26 27 _currentPageIndex = pageIndex;
27 28 on<PageViewChangeIndexEvent>(_pageIndexChange);
  29 + on<RequestDataEvent>(_requestData);
28 30 }
29 31  
30   - Future<void> requestData() async {
  32 +
  33 + void _pageIndexChange(PageViewChangeIndexEvent event,Emitter<LessonState> emitter) async {
  34 + _currentPageIndex = event.index;
  35 + emitter(PageIndexChangeState());
  36 + }
  37 +
  38 + void _requestData(RequestDataEvent event, Emitter<LessonState> emitter) async {
31 39 try {
32 40 await loading(() async {
33 41 _listData = await HomeDao.courseModule()??[];
34   - emit(LessonDataLoadState());
  42 + emitter(LessonDataLoadState());
35 43 });
36 44 } catch (e) {
37 45 if (e is ApiException) {
38   -
  46 + EasyLoading.showToast(e.message??'请求失败,请检查网络连接');
39 47 }
40 48 }
41 49 }
42 50  
43   - void _pageIndexChange(PageViewChangeIndexEvent event,Emitter<LessonState> emitter) async {
44   - _currentPageIndex = event.index;
45   - emitter(PageIndexChangeState());
46   - }
47   -
48 51 @override
49 52 Future<void> close() {
50 53 pageController.dispose();
... ...
lib/pages/lessons/bloc/lesson_event.dart
... ... @@ -7,3 +7,5 @@ class PageViewChangeIndexEvent extends LessonEvent {
7 7 final int index;
8 8 PageViewChangeIndexEvent(this.index);
9 9 }
  10 +
  11 +class RequestDataEvent extends LessonEvent {}
... ...
lib/pages/lessons/lesson_page.dart
1 1 import 'package:flutter/material.dart';
2 2 import 'package:flutter_bloc/flutter_bloc.dart';
3   -import 'package:flutter_easyloading/flutter_easyloading.dart';
4 3 import 'package:flutter_screenutil/flutter_screenutil.dart';
5 4 import 'package:wow_english/common/extension/string_extension.dart';
6 5 import 'package:wow_english/common/widgets/we_app_bar.dart';
... ... @@ -24,7 +23,7 @@ class LessonPage extends StatelessWidget {
24 23 initialPage: starPageIndex??0,
25 24 viewportFraction: 0.3
26 25 ),
27   - )..requestData(),
  26 + )..add(RequestDataEvent()),
28 27 child: _LessonPageView(),
29 28 );
30 29 }
... ...
lib/pages/listen/bloc/listen_bloc.dart
... ... @@ -13,20 +13,19 @@ part &#39;listen_state.dart&#39;;
13 13  
14 14 class ListenBloc extends Bloc<ListenEvent, ListenState> {
15 15  
16   - List<ListenEntity?>? _listData;
17   - List<ListenEntity?>? get listData => _listData;
  16 + List<ListenEntity?> _listData = [];
  17 + List<ListenEntity?> get listData => _listData;
18 18  
19 19 ListenBloc() : super(ListenInitial()) {
20   - on<ListenEvent>((event, emit) {
21   - // TODO: implement event handler
22   - });
  20 + on<RequestDataEvent>(_requestData);
23 21 }
24 22  
25   - Future<void> requestData() async {
  23 +
  24 + void _requestData(RequestDataEvent event,Emitter<ListenState> emitter) async {
26 25 try {
27 26 await loading(() async {
28 27 _listData = await ListenDao.listen()??[];
29   - emit(RequestListenDataState());
  28 + emitter(RequestListenDataState());
30 29 });
31 30 } catch (e) {
32 31 if (e is ApiException) {
... ...
lib/pages/listen/bloc/listen_event.dart
... ... @@ -2,3 +2,5 @@ part of &#39;listen_bloc.dart&#39;;
2 2  
3 3 @immutable
4 4 abstract class ListenEvent {}
  5 +
  6 +class RequestDataEvent extends ListenEvent {}
... ...
lib/pages/listen/listen_page.dart
... ... @@ -13,7 +13,7 @@ class ListenPage extends StatelessWidget {
13 13 @override
14 14 Widget build(BuildContext context) {
15 15 return BlocProvider(
16   - create: (context) => ListenBloc()..requestData(),
  16 + create: (context) => ListenBloc()..add(RequestDataEvent()),
17 17 child: _ListenPageView(),
18 18 );
19 19 }
... ... @@ -40,14 +40,15 @@ class _ListenPageView extends StatelessWidget {
40 40 builder: (context, state) {
41 41 final bloc = BlocProvider.of<ListenBloc>(context);
42 42 return ListView.builder(
43   - itemCount: bloc.listData?.length,
  43 + itemCount: bloc.listData.length,
44 44 scrollDirection: Axis.horizontal,
45 45 padding: EdgeInsets.symmetric(horizontal: 30.w,vertical: 36.h),
46 46 itemBuilder: (BuildContext context,int index){
  47 + final entity = bloc.listData[index];
47 48 return ListenItemWidget(
48   - entity: bloc.listData?[index],
  49 + entity: entity,
49 50 clickEvent: (){
50   - Navigator.of(context).pushNamed(AppRouteName.lookVideo,arguments: {'videoUrl':'https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/7194236f31b2e1e3da0fe06cfed4ba2b.mp4'});
  51 + Navigator.of(context).pushNamed(AppRouteName.lookVideo,arguments: {'videoUrl':entity?.videoUrl,'title':'listen'});
51 52 });
52 53 });
53 54 });
... ...
lib/pages/listen/widgets/listen_item_widget.dart
1   -import 'package:cached_network_image/cached_network_image.dart';
2 1 import 'package:flutter/material.dart';
3 2 import 'package:flutter_screenutil/flutter_screenutil.dart';
4 3 import 'package:wow_english/common/extension/string_extension.dart';
... ...
lib/pages/practice/chosetopic/topicpicture/bloc/topic_picture_bloc.dart renamed to lib/pages/practice/bloc/topic_picture_bloc.dart
lib/pages/practice/chosetopic/topicpicture/bloc/topic_picture_event.dart renamed to lib/pages/practice/bloc/topic_picture_event.dart
lib/pages/practice/chosetopic/topicpicture/bloc/topic_picture_state.dart renamed to lib/pages/practice/bloc/topic_picture_state.dart
lib/pages/practice/chosetopic/topicpicture/topic_picture_page.dart deleted
1   -import 'package:flutter/material.dart';
2   -import 'package:flutter_bloc/flutter_bloc.dart';
3   -import 'package:flutter_screenutil/flutter_screenutil.dart';
4   -import 'package:wow_english/common/extension/string_extension.dart';
5   -
6   -import '../../widgets/practice_header_widget.dart';
7   -import 'bloc/topic_picture_bloc.dart';
8   -
9   -class TopicPicturePage extends StatelessWidget {
10   - const TopicPicturePage({super.key});
11   -
12   - @override
13   - Widget build(BuildContext context) {
14   - return BlocProvider(
15   - create: (context) => TopicPictureBloc(PageController(),3),
16   - child: _TopicPicturePage(),
17   - );
18   - }
19   -}
20   -
21   -class _TopicPicturePage extends StatelessWidget {
22   - @override
23   - Widget build(BuildContext context) {
24   - return BlocListener<TopicPictureBloc,TopicPictureState>(
25   - listener: (context, state){},
26   - child: _topicPictureView(),
27   - );
28   - }
29   -
30   - Widget _topicPictureView() => BlocBuilder<TopicPictureBloc,TopicPictureState>(
31   - buildWhen: (_,s) => s is CurrentPageIndexState,
32   - builder: (context,state){
33   - final bloc = BlocProvider.of<TopicPictureBloc>(context);
34   - return Container(
35   - color: Colors.white,
36   - child: Stack(
37   - children: [
38   - Column(
39   - children: [
40   - PracticeHeaderWidget(
41   - title: '${bloc.currentPage}/8',
42   - onTap: (){Navigator.pop(context);},
43   - ),
44   - Expanded(
45   - child: PageView.builder(
46   - itemCount: 8,
47   - scrollDirection: Axis.horizontal,
48   - controller: bloc.pageController,
49   - onPageChanged: (int index) {
50   - bloc.add(CurrentPageIndexChangeEvent(index));
51   - },
52   - itemBuilder: (BuildContext context,int index){
53   - return _pageViewItemWidget();
54   - }),
55   - )
56   - ],
57   - ),
58   - Positioned(
59   - left: 0,
60   - right: 0,
61   - bottom: 0,
62   - child: Image.asset('bottom_grass'.assetPng)
63   - )
64   - ],
65   - ),
66   - );
67   - });
68   -
69   - Widget _pageViewItemWidget() => BlocBuilder<TopicPictureBloc,TopicPictureState>(
70   - builder: (context, state){
71   - final bloc = BlocProvider.of<TopicPictureBloc>(context);
72   - return SafeArea(
73   - child: Column(
74   - children: [
75   - Text(
76   - 'What to do when the sentence question is very long and needs a line break',
77   - softWrap: true,
78   - style: TextStyle(
79   - fontSize: 21.sp,
80   - color: const Color(0xFF333333)
81   - )
82   - ),
83   - 26.verticalSpace,
84   - Row(
85   - mainAxisAlignment: MainAxisAlignment.center,
86   - children: [
87   - Offstage(
88   - offstage: (bloc.modelCount < 1),
89   - child: _decodeImageWidget(1),
90   - ),
91   - Offstage(
92   - offstage: (bloc.modelCount < 2),
93   - child: _decodeImageWidget(2),
94   - ),
95   - Offstage(
96   - offstage: (bloc.modelCount < 3),
97   - child: _decodeImageWidget(3),
98   - ),
99   - Offstage(
100   - offstage: (bloc.modelCount < 4),
101   - child: _decodeImageWidget(4),
102   - )
103   - ],
104   - )
105   - ],
106   - ),
107   - );
108   - });
109   -
110   - Widget _decodeImageWidget(int index) => BlocBuilder<TopicPictureBloc,TopicPictureState>(
111   - buildWhen: (_, s) => s is SelectItemChangeState,
112   - builder: (context,state){
113   - final bloc = BlocProvider.of<TopicPictureBloc>(context);
114   - return GestureDetector(
115   - onTap: () => bloc.add(SelectItemEvent(index)),
116   - child: Container(
117   - padding: const EdgeInsets.all(4.5),
118   - decoration: BoxDecoration(
119   - color: bloc.selectItem == index?const Color(0xFF00B6F1):Colors.white,
120   - borderRadius: BorderRadius.circular(15),
121   - ),
122   - height: 143.h,
123   - width: 143.w,
124   - child: Container(
125   - decoration: BoxDecoration(
126   - color: Colors.white,
127   - borderRadius: BorderRadius.circular(15),
128   - border: Border.all(
129   - width: 1.0,
130   - color: const Color(0xFF140C10)
131   - ),
132   - image: const DecorationImage(
133   - fit: BoxFit.fitWidth,
134   - image: NetworkImage('https://img1.baidu.com/it/u=3392591833,1640391553&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=714')
135   - )
136   - ),
137   - ),
138   - ),
139   - );
140   - });
141   -}
142 0 \ No newline at end of file
lib/pages/practice/chosetopic/topicword/bloc/topic_word_bloc.dart deleted
1   -
2   -import 'package:flutter/cupertino.dart';
3   -import 'package:flutter_bloc/flutter_bloc.dart';
4   -
5   -part 'topic_word_event.dart';
6   -part 'topic_word_state.dart';
7   -
8   -class TopicWordBloc extends Bloc<TopicWordEvent, TopicWordState> {
9   - final PageController pageController;
10   -
11   - final int modelCount;
12   -
13   - int _currentPage = 0;
14   -
15   - int _selectItem = 0;
16   -
17   - int get currentPage => _currentPage + 1;
18   -
19   - int get selectItem => _selectItem;
20   -
21   - TopicWordBloc(this.pageController, this.modelCount) : super(TopicWordInitial()) {
22   - on<CurrentPageIndexChangeEvent>(_pageControllerChange);
23   - on<SelectItemEvent>(_selectItemLoad);
24   - }
25   -
26   - @override
27   - Future<void> close() {
28   - pageController.dispose();
29   - return super.close();
30   - }
31   -
32   - void _pageControllerChange(CurrentPageIndexChangeEvent event,Emitter<TopicWordState> emitter) async {
33   - _currentPage = event.pageIndex;
34   - emitter(CurrentPageIndexState());
35   - }
36   -
37   - void _selectItemLoad(SelectItemEvent event,Emitter<TopicWordState> emitter) async {
38   - _selectItem = event.selectIndex;
39   - emitter(SelectItemChangeState());
40   - }
41   -}
lib/pages/practice/chosetopic/topicword/bloc/topic_word_event.dart deleted
1   -part of 'topic_word_bloc.dart';
2   -
3   -@immutable
4   -abstract class TopicWordEvent {}
5   -
6   -class CurrentPageIndexChangeEvent extends TopicWordEvent {
7   - final int pageIndex;
8   - CurrentPageIndexChangeEvent(this.pageIndex);
9   -}
10   -
11   -class SelectItemEvent extends TopicWordEvent {
12   - final int selectIndex;
13   - SelectItemEvent(this.selectIndex);
14   -}
15 0 \ No newline at end of file
lib/pages/practice/chosetopic/topicword/bloc/topic_word_state.dart deleted
1   -part of 'topic_word_bloc.dart';
2   -
3   -@immutable
4   -abstract class TopicWordState {}
5   -
6   -class TopicWordInitial extends TopicWordState {}
7   -
8   -class CurrentPageIndexState extends TopicWordState {}
9   -
10   -class SelectItemChangeState extends TopicWordState {}
11 0 \ No newline at end of file
lib/pages/practice/chosetopic/topicword/topic_word_page.dart deleted
1   -import 'package:flutter/material.dart';
2   -import 'package:flutter_bloc/flutter_bloc.dart';
3   -import 'package:flutter_screenutil/flutter_screenutil.dart';
4   -import 'package:wow_english/common/extension/string_extension.dart';
5   -import 'package:wow_english/pages/practice/widgets/practice_header_widget.dart';
6   -
7   -import 'bloc/topic_word_bloc.dart';
8   -
9   -class TopicWordPage extends StatelessWidget {
10   - const TopicWordPage({super.key});
11   -
12   - @override
13   - Widget build(BuildContext context) {
14   - return BlocProvider(
15   - create: (context) => TopicWordBloc(PageController(), 4),
16   - child: _TopicWordPage(),
17   - );
18   - }
19   -}
20   -
21   -class _TopicWordPage extends StatelessWidget {
22   - @override
23   - Widget build(BuildContext context) {
24   - return BlocListener<TopicWordBloc,TopicWordState>(
25   - listener: (context, state) {
26   -
27   - },
28   - child: _topicWordView(),
29   - );
30   - }
31   -
32   - Widget _topicWordView() => BlocBuilder<TopicWordBloc,TopicWordState>(
33   - builder: (context,state){
34   - final bloc = BlocProvider.of<TopicWordBloc>(context);
35   - return Container(
36   - color: Colors.white,
37   - child: Stack(
38   - children: [
39   - Positioned(
40   - left: 0,
41   - right: 0,
42   - bottom: 0,
43   - child: Image.asset('background_grass'.assetPng,fit: BoxFit.fitWidth,)
44   - ),
45   - Column(
46   - children: [
47   - PracticeHeaderWidget(
48   - title: '${bloc.currentPage}/8',
49   - onTap: (){Navigator.pop(context);},
50   - ),
51   - Expanded(
52   - child: PageView.builder(
53   - itemCount: 8,
54   - scrollDirection: Axis.horizontal,
55   - controller: bloc.pageController,
56   - onPageChanged: (int index) {
57   - bloc.add(CurrentPageIndexChangeEvent(index));
58   - },
59   - itemBuilder: (BuildContext context,int index){
60   - return _pageViewItemWidget();
61   - }),
62   - )
63   - ],
64   - ),
65   - ],
66   - ),
67   - );
68   - });
69   -
70   - Widget _pageViewItemWidget() => BlocBuilder<TopicWordBloc,TopicWordState>(
71   - builder: (context, state){
72   - final bloc = BlocProvider.of<TopicWordBloc>(context);
73   - return SafeArea(
74   - child: Column(
75   - children: [
76   - Text(
77   - 'What to do when the sentence question is very long and needs a line break',
78   - softWrap: true,
79   - style: TextStyle(
80   - fontSize: 21.sp,
81   - color: const Color(0xFF333333)
82   - )
83   - ),
84   - 26.verticalSpace,
85   - Row(
86   - mainAxisAlignment: MainAxisAlignment.spaceBetween,
87   - children: [
88   - Offstage(
89   - offstage: (bloc.modelCount < 1),
90   - child: _decodeImageWidget(1),
91   - ),
92   - Offstage(
93   - offstage: (bloc.modelCount < 2),
94   - child: _decodeImageWidget(2),
95   - ),
96   - Offstage(
97   - offstage: (bloc.modelCount < 3),
98   - child: _decodeImageWidget(3),
99   - ),
100   - Offstage(
101   - offstage: (bloc.modelCount < 4),
102   - child: _decodeImageWidget(4),
103   - )
104   - ],
105   - )
106   - ],
107   - ),
108   - );
109   - });
110   -
111   - Widget _decodeImageWidget(int index) => BlocBuilder<TopicWordBloc,TopicWordState>(
112   - buildWhen: (_, s) => s is SelectItemChangeState,
113   - builder: (context,state){
114   - final bloc = BlocProvider.of<TopicWordBloc>(context);
115   - return GestureDetector(
116   - onTap: () => bloc.add(SelectItemEvent(index)),
117   - child: Container(
118   - width: 143.w,
119   - height: 143.h,
120   - padding: EdgeInsets.only(left: 13.w,right: 13.w,top: 13.h,bottom: 13.h),
121   - decoration: BoxDecoration(
122   - color: Colors.white,
123   - borderRadius: BorderRadius.circular(15),
124   - border: Border.all(
125   - width: 1.0,
126   - color: const Color(0xFF140C10)
127   - ),
128   - ),
129   - child: Column(
130   - mainAxisAlignment: MainAxisAlignment.end,
131   - children: [
132   - Expanded(
133   - child: Container(
134   - alignment: Alignment.center,
135   - child: Text(
136   - 'yellow',
137   - style: TextStyle(
138   - fontSize: 20.sp,
139   - color: const Color(0xFF333333)
140   - )
141   - ),
142   - ),
143   - ),
144   - Container(
145   - height: 30.h,
146   - width: double.infinity,
147   - decoration: BoxDecoration(
148   - color: bloc.selectItem == index?const Color(0xFF00B6F1):Colors.white,
149   - borderRadius: BorderRadius.circular(15.r),
150   - border: Border.all(
151   - width: 1.5,
152   - color: const Color(0xFF140C10)
153   - ),
154   - ),
155   - alignment: Alignment.center,
156   - child: Image.asset('choose'.assetPng),
157   - )
158   - ],
159   - ),
160   - ),
161   - );
162   - });
163   -}
164 0 \ No newline at end of file
lib/pages/practice/topic_picture_page.dart 0 → 100644
  1 +import 'package:flutter/material.dart';
  2 +import 'package:flutter_bloc/flutter_bloc.dart';
  3 +import 'package:flutter_screenutil/flutter_screenutil.dart';
  4 +import 'package:wow_english/common/extension/string_extension.dart';
  5 +import 'package:wow_english/common/widgets/ow_image_widget.dart';
  6 +
  7 +import 'bloc/topic_picture_bloc.dart';
  8 +import 'widgets/practice_header_widget.dart';
  9 +
  10 +class TopicPicturePage extends StatelessWidget {
  11 + const TopicPicturePage({super.key});
  12 +
  13 + @override
  14 + Widget build(BuildContext context) {
  15 + return BlocProvider(
  16 + create: (context) => TopicPictureBloc(PageController(),3),
  17 + child: _TopicPicturePage(),
  18 + );
  19 + }
  20 +}
  21 +
  22 +class _TopicPicturePage extends StatelessWidget {
  23 + @override
  24 + Widget build(BuildContext context) {
  25 + return BlocListener<TopicPictureBloc,TopicPictureState>(
  26 + listener: (context, state){},
  27 + child: _topicPictureView(),
  28 + );
  29 + }
  30 +
  31 + Widget _topicPictureView() => BlocBuilder<TopicPictureBloc,TopicPictureState>(
  32 + buildWhen: (_,s) => s is CurrentPageIndexState,
  33 + builder: (context,state){
  34 + final bloc = BlocProvider.of<TopicPictureBloc>(context);
  35 + return Container(
  36 + color: Colors.white,
  37 + child: Stack(
  38 + children: [
  39 + Column(
  40 + children: [
  41 + PracticeHeaderWidget(
  42 + title: '${bloc.currentPage}/8',
  43 + onTap: (){Navigator.pop(context);},
  44 + ),
  45 + Expanded(
  46 + child: PageView.builder(
  47 + itemCount: 8,
  48 + scrollDirection: Axis.horizontal,
  49 + controller: bloc.pageController,
  50 + onPageChanged: (int index) {
  51 + bloc.add(CurrentPageIndexChangeEvent(index));
  52 + },
  53 + itemBuilder: (BuildContext context,int index){
  54 + if (index % 5 == 0) {
  55 + return _pageViewWordItemWidget();
  56 + } else if (index % 5 == 1) {
  57 + return _pageViewItemWidget();
  58 + } else if (index % 5 == 2){
  59 + return _pageViewVoicePictureItemWidget();
  60 + } else if (index % 5 == 3){
  61 + return _voiceAnswerItem();
  62 + } else {
  63 + return _pageViewVoiceWordItemWidget();
  64 + }
  65 + }),
  66 + )
  67 + ],
  68 + ),
  69 + Positioned(
  70 + left: 0,
  71 + right: 0,
  72 + bottom: 0,
  73 + child: Image.asset('bottom_grass'.assetPng)
  74 + )
  75 + ],
  76 + ),
  77 + );
  78 + });
  79 +
  80 + ///看题选图
  81 + Widget _pageViewItemWidget() => BlocBuilder<TopicPictureBloc,TopicPictureState>(
  82 + builder: (context, state){
  83 + final bloc = BlocProvider.of<TopicPictureBloc>(context);
  84 + return SafeArea(
  85 + child: Column(
  86 + children: [
  87 + Text(
  88 + 'What to do when the sentence question is very long and needs a line break',
  89 + softWrap: true,
  90 + style: TextStyle(
  91 + fontSize: 21.sp,
  92 + color: const Color(0xFF333333)
  93 + )
  94 + ),
  95 + 26.verticalSpace,
  96 + Row(
  97 + mainAxisAlignment: MainAxisAlignment.center,
  98 + children: [
  99 + Offstage(
  100 + offstage: (bloc.modelCount < 1),
  101 + child: _decodeImageWidget(1),
  102 + ),
  103 + Offstage(
  104 + offstage: (bloc.modelCount < 2),
  105 + child: _decodeImageWidget(2),
  106 + ),
  107 + Offstage(
  108 + offstage: (bloc.modelCount < 3),
  109 + child: _decodeImageWidget(3),
  110 + ),
  111 + Offstage(
  112 + offstage: (bloc.modelCount < 4),
  113 + child: _decodeImageWidget(4),
  114 + )
  115 + ],
  116 + )
  117 + ],
  118 + ),
  119 + );
  120 + });
  121 +
  122 + Widget _decodeImageWidget(int index) => BlocBuilder<TopicPictureBloc,TopicPictureState>(
  123 + buildWhen: (_, s) => s is SelectItemChangeState,
  124 + builder: (context,state){
  125 + final bloc = BlocProvider.of<TopicPictureBloc>(context);
  126 + return GestureDetector(
  127 + onTap: () => bloc.add(SelectItemEvent(index)),
  128 + child: Container(
  129 + padding: const EdgeInsets.all(4.5),
  130 + decoration: BoxDecoration(
  131 + color: bloc.selectItem == index?const Color(0xFF00B6F1):Colors.white,
  132 + borderRadius: BorderRadius.circular(15),
  133 + ),
  134 + height: 143.h,
  135 + width: 143.w,
  136 + child: Container(
  137 + decoration: BoxDecoration(
  138 + color: Colors.white,
  139 + borderRadius: BorderRadius.circular(15),
  140 + border: Border.all(
  141 + width: 1.0,
  142 + color: const Color(0xFF140C10)
  143 + ),
  144 + image: const DecorationImage(
  145 + fit: BoxFit.fitWidth,
  146 + image: NetworkImage('https://img1.baidu.com/it/u=3392591833,1640391553&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=714')
  147 + )
  148 + ),
  149 + ),
  150 + ),
  151 + );
  152 + });
  153 +
  154 + ///看题选字
  155 + Widget _pageViewWordItemWidget() => BlocBuilder<TopicPictureBloc,TopicPictureState>(
  156 + builder: (context, state){
  157 + final bloc = BlocProvider.of<TopicPictureBloc>(context);
  158 + return SafeArea(
  159 + child: Column(
  160 + children: [
  161 + Text(
  162 + 'What to do when the sentence question is very long and needs a line break',
  163 + softWrap: true,
  164 + style: TextStyle(
  165 + fontSize: 21.sp,
  166 + color: const Color(0xFF333333)
  167 + )
  168 + ),
  169 + 26.verticalSpace,
  170 + Row(
  171 + mainAxisAlignment: MainAxisAlignment.spaceBetween,
  172 + children: [
  173 + Offstage(
  174 + offstage: (bloc.modelCount < 1),
  175 + child: _decodeWordWidget(1),
  176 + ),
  177 + Offstage(
  178 + offstage: (bloc.modelCount < 2),
  179 + child: _decodeWordWidget(2),
  180 + ),
  181 + Offstage(
  182 + offstage: (bloc.modelCount < 3),
  183 + child: _decodeWordWidget(3),
  184 + ),
  185 + Offstage(
  186 + offstage: (bloc.modelCount < 4),
  187 + child: _decodeWordWidget(4),
  188 + )
  189 + ],
  190 + )
  191 + ],
  192 + ),
  193 + );
  194 + });
  195 +
  196 + Widget _decodeWordWidget(int index) => BlocBuilder<TopicPictureBloc,TopicPictureState>(
  197 + buildWhen: (_, s) => s is SelectItemChangeState,
  198 + builder: (context,state){
  199 + final bloc = BlocProvider.of<TopicPictureBloc>(context);
  200 + return GestureDetector(
  201 + onTap: () => bloc.add(SelectItemEvent(index)),
  202 + child: Container(
  203 + width: 143.w,
  204 + height: 143.h,
  205 + padding: EdgeInsets.only(left: 13.w,right: 13.w,top: 13.h,bottom: 13.h),
  206 + decoration: BoxDecoration(
  207 + color: Colors.white,
  208 + borderRadius: BorderRadius.circular(15),
  209 + border: Border.all(
  210 + width: 1.0,
  211 + color: const Color(0xFF140C10)
  212 + ),
  213 + ),
  214 + child: Column(
  215 + mainAxisAlignment: MainAxisAlignment.end,
  216 + children: [
  217 + Expanded(
  218 + child: Container(
  219 + alignment: Alignment.center,
  220 + child: Text(
  221 + 'yellow',
  222 + style: TextStyle(
  223 + fontSize: 20.sp,
  224 + color: const Color(0xFF333333)
  225 + )
  226 + ),
  227 + ),
  228 + ),
  229 + Container(
  230 + height: 30.h,
  231 + width: double.infinity,
  232 + decoration: BoxDecoration(
  233 + color: bloc.selectItem == index?const Color(0xFF00B6F1):Colors.white,
  234 + borderRadius: BorderRadius.circular(15.r),
  235 + border: Border.all(
  236 + width: 1.5,
  237 + color: const Color(0xFF140C10)
  238 + ),
  239 + ),
  240 + alignment: Alignment.center,
  241 + child: Image.asset('choose'.assetPng),
  242 + )
  243 + ],
  244 + ),
  245 + ),
  246 + );
  247 + });
  248 +
  249 + ///听音选图
  250 + Widget _pageViewVoicePictureItemWidget() => BlocBuilder<TopicPictureBloc,TopicPictureState>(
  251 + builder: (context, state){
  252 + final bloc = BlocProvider.of<TopicPictureBloc>(context);
  253 + return SafeArea(
  254 + child: Column(
  255 + children: [
  256 + Row(
  257 + mainAxisAlignment: MainAxisAlignment.center,
  258 + children: [
  259 + Image.asset('voice'.assetPng,height: 33.h,width: 30.w,),
  260 + 10.horizontalSpace,
  261 + Text(
  262 + 'yellow',
  263 + style: TextStyle(
  264 + fontSize: 20.sp,
  265 + color: const Color(0xFF333333)
  266 + )
  267 + )
  268 + ],
  269 + ),
  270 + 26.verticalSpace,
  271 + Row(
  272 + mainAxisAlignment: MainAxisAlignment.spaceBetween,
  273 + children: [
  274 + Offstage(
  275 + offstage: (bloc.modelCount < 1),
  276 + child: _decodeVoiceImageWidget(1),
  277 + ),
  278 + Offstage(
  279 + offstage: (bloc.modelCount < 2),
  280 + child: _decodeVoiceImageWidget(2),
  281 + ),
  282 + Offstage(
  283 + offstage: (bloc.modelCount < 3),
  284 + child: _decodeVoiceImageWidget(3),
  285 + ),
  286 + Offstage(
  287 + offstage: (bloc.modelCount < 4),
  288 + child: _decodeVoiceImageWidget(4),
  289 + )
  290 + ],
  291 + )
  292 + ],
  293 + ),
  294 + );
  295 + });
  296 +
  297 + Widget _decodeVoiceImageWidget(int index) => BlocBuilder<TopicPictureBloc,TopicPictureState>(
  298 + buildWhen: (_, s) => s is SelectItemChangeState,
  299 + builder: (context,state){
  300 + final bloc = BlocProvider.of<TopicPictureBloc>(context);
  301 + return GestureDetector(
  302 + onTap: () => bloc.add(SelectItemEvent(index)),
  303 + child: Container(
  304 + padding: const EdgeInsets.all(4.5),
  305 + decoration: BoxDecoration(
  306 + color: bloc.selectItem == index?const Color(0xFF00B6F1):Colors.white,
  307 + borderRadius: BorderRadius.circular(15),
  308 + ),
  309 + height: 143.h,
  310 + width: 143.w,
  311 + child: Container(
  312 + decoration: BoxDecoration(
  313 + color: Colors.white,
  314 + borderRadius: BorderRadius.circular(15),
  315 + border: Border.all(
  316 + width: 1.0,
  317 + color: const Color(0xFF140C10)
  318 + ),
  319 + image: const DecorationImage(
  320 + fit: BoxFit.fitWidth,
  321 + image: NetworkImage('https://img1.baidu.com/it/u=3392591833,1640391553&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=714')
  322 + )
  323 + ),
  324 + ),
  325 + ),
  326 + );
  327 + });
  328 +
  329 + ///听音选字
  330 + Widget _pageViewVoiceWordItemWidget() => BlocBuilder<TopicPictureBloc,TopicPictureState>(
  331 + builder: (context, state){
  332 + final bloc = BlocProvider.of<TopicPictureBloc>(context);
  333 + return SafeArea(
  334 + child: Column(
  335 + children: [
  336 + Image.asset('voice'.assetPng,height: 33.h,width: 30.w,),
  337 + 26.verticalSpace,
  338 + Row(
  339 + mainAxisAlignment: MainAxisAlignment.spaceBetween,
  340 + children: [
  341 + Offstage(
  342 + offstage: (bloc.modelCount < 1),
  343 + child: _decodeVoiceWordImageWidget(1),
  344 + ),
  345 + Offstage(
  346 + offstage: (bloc.modelCount < 2),
  347 + child: _decodeVoiceWordImageWidget(2),
  348 + ),
  349 + Offstage(
  350 + offstage: (bloc.modelCount < 3),
  351 + child: _decodeVoiceWordImageWidget(3),
  352 + ),
  353 + Offstage(
  354 + offstage: (bloc.modelCount < 4),
  355 + child: _decodeVoiceWordImageWidget(4),
  356 + )
  357 + ],
  358 + )
  359 + ],
  360 + ),
  361 + );
  362 + });
  363 +
  364 + Widget _decodeVoiceWordImageWidget(int index) => BlocBuilder<TopicPictureBloc,TopicPictureState>(
  365 + buildWhen: (_, s) => s is SelectItemChangeState,
  366 + builder: (context,state){
  367 + final bloc = BlocProvider.of<TopicPictureBloc>(context);
  368 + return GestureDetector(
  369 + onTap: () => bloc.add(SelectItemEvent(index)),
  370 + child: Container(
  371 + width: 143.w,
  372 + height: 143.h,
  373 + padding: EdgeInsets.only(left: 13.w,right: 13.w,top: 13.h,bottom: 13.h),
  374 + decoration: BoxDecoration(
  375 + color: Colors.white,
  376 + borderRadius: BorderRadius.circular(15),
  377 + border: Border.all(
  378 + width: 1.0,
  379 + color: const Color(0xFF140C10)
  380 + ),
  381 + ),
  382 + child: Column(
  383 + mainAxisAlignment: MainAxisAlignment.end,
  384 + children: [
  385 + Expanded(
  386 + child: Container(
  387 + alignment: Alignment.center,
  388 + child: Text(
  389 + 'yellow',
  390 + style: TextStyle(
  391 + fontSize: 20.sp,
  392 + color: const Color(0xFF333333)
  393 + )
  394 + ),
  395 + ),
  396 + ),
  397 + Container(
  398 + height: 30.h,
  399 + width: double.infinity,
  400 + decoration: BoxDecoration(
  401 + color: bloc.selectItem == index?const Color(0xFF00B6F1):Colors.white,
  402 + borderRadius: BorderRadius.circular(15.r),
  403 + border: Border.all(
  404 + width: 1.5,
  405 + color: const Color(0xFF140C10)
  406 + ),
  407 + ),
  408 + alignment: Alignment.center,
  409 + child: Image.asset('choose'.assetPng),
  410 + )
  411 + ],
  412 + ),
  413 + ),
  414 + );
  415 + });
  416 +
  417 + ///语音问答
  418 + Widget _voiceAnswerItem() => BlocBuilder<TopicPictureBloc,TopicPictureState>(
  419 + builder: (context, state) {
  420 + return Row(
  421 + mainAxisAlignment: MainAxisAlignment.center,
  422 + children: [
  423 + OwImageWidget(
  424 + name:'https://up.enterdesk.com/edpic_source/16/e7/0d/16e70d550daff77cbac31fae5e1651d4.jpg',
  425 + height: 186.h,
  426 + width: 186.w,
  427 + ),
  428 + 160.horizontalSpace,
  429 + Column(
  430 + mainAxisAlignment: MainAxisAlignment.center,
  431 + children: [
  432 + Image.asset(
  433 + 'voice'.assetPng,
  434 + height: 52.h,
  435 + width: 46.w,
  436 + ),
  437 + 70.verticalSpace,
  438 + Image.asset(
  439 + 'micro_phone'.assetPng,
  440 + height: 75.w,
  441 + width: 75.w,
  442 + )
  443 + ],
  444 + )
  445 + ],
  446 + );
  447 + });
  448 +}
0 449 \ No newline at end of file
... ...
lib/pages/practice/voicetopic/voicepicture/bloc/voice_pic_bloc.dart deleted
1   -import 'package:flutter/cupertino.dart';
2   -import 'package:flutter_bloc/flutter_bloc.dart';
3   -
4   -part 'voice_pic_event.dart';
5   -part 'voice_pic_state.dart';
6   -
7   -class VoicePicBloc extends Bloc<VoicePicEvent, VoicePicState> {
8   - final PageController pageController;
9   -
10   - final int modelCount;
11   -
12   - int _currentPage = 0;
13   -
14   - int _selectItem = 0;
15   -
16   - int get currentPage => _currentPage + 1;
17   -
18   - int get selectItem => _selectItem;
19   - VoicePicBloc(this.pageController, this.modelCount) : super(VoicePicInitial()) {
20   - on<CurrentPageIndexChangeEvent>(_pageControllerChange);
21   - on<SelectItemEvent>(_selectItemLoad);
22   - }
23   -
24   - @override
25   - Future<void> close() {
26   - pageController.dispose();
27   - return super.close();
28   - }
29   -
30   - void _pageControllerChange(CurrentPageIndexChangeEvent event,Emitter<VoicePicState> emitter) async {
31   - _currentPage = event.pageIndex;
32   - emitter(CurrentPageIndexState());
33   - }
34   -
35   - void _selectItemLoad(SelectItemEvent event,Emitter<VoicePicState> emitter) async {
36   - _selectItem = event.selectIndex;
37   - emitter(SelectItemChangeState());
38   - }
39   -}
lib/pages/practice/voicetopic/voicepicture/bloc/voice_pic_event.dart deleted
1   -part of 'voice_pic_bloc.dart';
2   -
3   -@immutable
4   -abstract class VoicePicEvent {}
5   -
6   -class CurrentPageIndexChangeEvent extends VoicePicEvent {
7   - final int pageIndex;
8   - CurrentPageIndexChangeEvent(this.pageIndex);
9   -}
10   -
11   -class SelectItemEvent extends VoicePicEvent {
12   - final int selectIndex;
13   - SelectItemEvent(this.selectIndex);
14   -}
15 0 \ No newline at end of file
lib/pages/practice/voicetopic/voicepicture/bloc/voice_pic_state.dart deleted
1   -part of 'voice_pic_bloc.dart';
2   -
3   -@immutable
4   -abstract class VoicePicState {}
5   -
6   -class VoicePicInitial extends VoicePicState {}
7   -
8   -class CurrentPageIndexState extends VoicePicState {}
9   -
10   -class SelectItemChangeState extends VoicePicState {}
11 0 \ No newline at end of file
lib/pages/practice/voicetopic/voicepicture/voice_pic_page.dart deleted
1   -import 'package:flutter/material.dart';
2   -import 'package:flutter_bloc/flutter_bloc.dart';
3   -import 'package:flutter_screenutil/flutter_screenutil.dart';
4   -import 'package:wow_english/common/extension/string_extension.dart';
5   -import 'package:wow_english/pages/practice/widgets/practice_header_widget.dart';
6   -
7   -import 'bloc/voice_pic_bloc.dart';
8   -
9   -class VoicePicPage extends StatelessWidget {
10   - const VoicePicPage({super.key});
11   -
12   - @override
13   - Widget build(BuildContext context) {
14   - return BlocProvider(
15   - create: (context) => VoicePicBloc(PageController(),4),
16   - child: _VoicePicPage(),
17   - );
18   - }
19   -}
20   -
21   -class _VoicePicPage extends StatelessWidget {
22   - @override
23   - Widget build(BuildContext context) {
24   - return BlocListener<VoicePicBloc, VoicePicState>(
25   - listener: (context, state){},
26   - child: _voicePicView(),
27   - );
28   - }
29   -
30   - Widget _voicePicView() => BlocBuilder<VoicePicBloc, VoicePicState>(
31   - builder: (context, state){
32   - return _voicePictureView();
33   - });
34   -
35   - Widget _voicePictureView() => BlocBuilder<VoicePicBloc, VoicePicState>(
36   - buildWhen: (_,s) => s is CurrentPageIndexState,
37   - builder: (context,state){
38   - final bloc = BlocProvider.of<VoicePicBloc>(context);
39   - return Container(
40   - color: Colors.white,
41   - child: Stack(
42   - children: [
43   - Image.asset(
44   - 'road_bg'.assetPng,
45   - height: double.infinity,
46   - width: double.infinity
47   - ),
48   - Column(
49   - children: [
50   - PracticeHeaderWidget(
51   - title: '${bloc.currentPage}/8',
52   - onTap: (){Navigator.pop(context);},
53   - ),
54   - Row(
55   - mainAxisAlignment: MainAxisAlignment.center,
56   - children: [
57   - Image.asset('voice'.assetPng,height: 33.h,width: 30.w,),
58   - 10.horizontalSpace,
59   - Text(
60   - 'yellow',
61   - style: TextStyle(
62   - fontSize: 20.sp,
63   - color: const Color(0xFF333333)
64   - )
65   - )
66   - ],
67   - ),
68   - 26.verticalSpace,
69   - Expanded(
70   - child: PageView.builder(
71   - itemCount: 8,
72   - scrollDirection: Axis.horizontal,
73   - controller: bloc.pageController,
74   - onPageChanged: (int index) {
75   - bloc.add(CurrentPageIndexChangeEvent(index));
76   - },
77   - itemBuilder: (BuildContext context,int index){
78   - return _pageViewItemWidget();
79   - }),
80   - )
81   - ],
82   - )
83   - ],
84   - ),
85   - );
86   - });
87   -
88   - Widget _pageViewItemWidget() => BlocBuilder<VoicePicBloc, VoicePicState>(
89   - builder: (context, state){
90   - final bloc = BlocProvider.of<VoicePicBloc>(context);
91   - return SafeArea(
92   - child: Column(
93   - children: [
94   - Row(
95   - mainAxisAlignment: MainAxisAlignment.spaceBetween,
96   - children: [
97   - Offstage(
98   - offstage: (bloc.modelCount < 1),
99   - child: _decodeImageWidget(1),
100   - ),
101   - Offstage(
102   - offstage: (bloc.modelCount < 2),
103   - child: _decodeImageWidget(2),
104   - ),
105   - Offstage(
106   - offstage: (bloc.modelCount < 3),
107   - child: _decodeImageWidget(3),
108   - ),
109   - Offstage(
110   - offstage: (bloc.modelCount < 4),
111   - child: _decodeImageWidget(4),
112   - )
113   - ],
114   - )
115   - ],
116   - ),
117   - );
118   - });
119   -
120   - Widget _decodeImageWidget(int index) => BlocBuilder<VoicePicBloc, VoicePicState>(
121   - buildWhen: (_, s) => s is SelectItemChangeState,
122   - builder: (context,state){
123   - final bloc = BlocProvider.of<VoicePicBloc>(context);
124   - return GestureDetector(
125   - onTap: () => bloc.add(SelectItemEvent(index)),
126   - child: Container(
127   - padding: const EdgeInsets.all(4.5),
128   - decoration: BoxDecoration(
129   - color: bloc.selectItem == index?const Color(0xFF00B6F1):Colors.white,
130   - borderRadius: BorderRadius.circular(15),
131   - ),
132   - height: 143.h,
133   - width: 143.w,
134   - child: Container(
135   - decoration: BoxDecoration(
136   - color: Colors.white,
137   - borderRadius: BorderRadius.circular(15),
138   - border: Border.all(
139   - width: 1.0,
140   - color: const Color(0xFF140C10)
141   - ),
142   - image: const DecorationImage(
143   - fit: BoxFit.fitWidth,
144   - image: NetworkImage('https://img1.baidu.com/it/u=3392591833,1640391553&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=714')
145   - )
146   - ),
147   - ),
148   - ),
149   - );
150   - });
151   -}
152 0 \ No newline at end of file
lib/pages/practice/voicetopic/voiceword/bloc/voice_word_bloc.dart deleted
1   -
2   -import 'package:flutter/cupertino.dart';
3   -import 'package:flutter_bloc/flutter_bloc.dart';
4   -
5   -part 'voice_word_event.dart';
6   -part 'voice_word_state.dart';
7   -
8   -class VoiceWordBloc extends Bloc<VoiceWordEvent, VoiceWordState> {
9   - final PageController pageController;
10   -
11   - final int modelCount;
12   -
13   - int _currentPage = 0;
14   -
15   - int _selectItem = 0;
16   -
17   - int get currentPage => _currentPage + 1;
18   -
19   - int get selectItem => _selectItem;
20   - VoiceWordBloc(this.pageController, this.modelCount) : super(VoiceWordInitial()) {
21   - on<CurrentPageIndexChangeEvent>(_pageControllerChange);
22   - on<SelectItemEvent>(_selectItemLoad);
23   - }
24   -
25   - @override
26   - Future<void> close() {
27   - pageController.dispose();
28   - return super.close();
29   - }
30   -
31   - void _pageControllerChange(CurrentPageIndexChangeEvent event,Emitter<VoiceWordState> emitter) async {
32   - _currentPage = event.pageIndex;
33   - emitter(CurrentPageIndexState());
34   - }
35   -
36   - void _selectItemLoad(SelectItemEvent event,Emitter<VoiceWordState> emitter) async {
37   - _selectItem = event.selectIndex;
38   - emitter(SelectItemChangeState());
39   - }
40   -}
41   -
lib/pages/practice/voicetopic/voiceword/bloc/voice_word_event.dart deleted
1   -part of 'voice_word_bloc.dart';
2   -
3   -@immutable
4   -abstract class VoiceWordEvent {}
5   -
6   -class CurrentPageIndexChangeEvent extends VoiceWordEvent {
7   - final int pageIndex;
8   - CurrentPageIndexChangeEvent(this.pageIndex);
9   -}
10   -
11   -class SelectItemEvent extends VoiceWordEvent {
12   - final int selectIndex;
13   - SelectItemEvent(this.selectIndex);
14   -}
15 0 \ No newline at end of file
lib/pages/practice/voicetopic/voiceword/bloc/voice_word_state.dart deleted
1   -part of 'voice_word_bloc.dart';
2   -
3   -@immutable
4   -abstract class VoiceWordState {}
5   -
6   -class VoiceWordInitial extends VoiceWordState {}
7   -
8   -class CurrentPageIndexState extends VoiceWordState {}
9   -
10   -class SelectItemChangeState extends VoiceWordState {}
lib/pages/practice/voicetopic/voiceword/voice_word_page.dart deleted
1   -import 'package:flutter/material.dart';
2   -import 'package:flutter_bloc/flutter_bloc.dart';
3   -import 'package:flutter_screenutil/flutter_screenutil.dart';
4   -import 'package:wow_english/common/extension/string_extension.dart';
5   -import 'package:wow_english/pages/practice/widgets/practice_header_widget.dart';
6   -
7   -import 'bloc/voice_word_bloc.dart';
8   -
9   -class VoiceWordPage extends StatelessWidget {
10   - const VoiceWordPage({super.key});
11   -
12   -
13   - @override
14   - Widget build(BuildContext context) {
15   - return BlocProvider(
16   - create: (context) => VoiceWordBloc(PageController(),4),
17   - child: _VoiceWordPage(),
18   - );
19   - }
20   -}
21   -
22   -class _VoiceWordPage extends StatelessWidget {
23   - @override
24   - Widget build(BuildContext context) {
25   - return BlocListener<VoiceWordBloc, VoiceWordState>(
26   - listener: (context, state){},
27   - child: _voiceWorView(),
28   - );
29   - }
30   -
31   - Widget _voiceWorView() => BlocBuilder<VoiceWordBloc, VoiceWordState>(
32   - builder: (context, state){
33   - return _voiceWordView();
34   - });
35   -
36   - Widget _voiceWordView() => BlocBuilder<VoiceWordBloc, VoiceWordState>(
37   - buildWhen: (_,s) => s is CurrentPageIndexState,
38   - builder: (context,state){
39   - final bloc = BlocProvider.of<VoiceWordBloc>(context);
40   - return Container(
41   - color: Colors.white,
42   - child: Stack(
43   - children: [
44   - Image.asset(
45   - 'road_bg'.assetPng,
46   - height: double.infinity,
47   - width: double.infinity
48   - ),
49   - Column(
50   - children: [
51   - PracticeHeaderWidget(
52   - title: '${bloc.currentPage}/8',
53   - onTap: (){Navigator.pop(context);},
54   - ),
55   - Image.asset('voice'.assetPng,height: 33.h,width: 30.w,),
56   - 26.verticalSpace,
57   - Expanded(
58   - child: PageView.builder(
59   - itemCount: 8,
60   - scrollDirection: Axis.horizontal,
61   - controller: bloc.pageController,
62   - onPageChanged: (int index) {
63   - bloc.add(CurrentPageIndexChangeEvent(index));
64   - },
65   - itemBuilder: (BuildContext context,int index){
66   - return _pageViewItemWidget();
67   - }),
68   - )
69   - ],
70   - )
71   - ],
72   - ),
73   - );
74   - });
75   -
76   - Widget _pageViewItemWidget() => BlocBuilder<VoiceWordBloc, VoiceWordState>(
77   - builder: (context, state){
78   - final bloc = BlocProvider.of<VoiceWordBloc>(context);
79   - return SafeArea(
80   - child: Column(
81   - children: [
82   - Row(
83   - mainAxisAlignment: MainAxisAlignment.spaceBetween,
84   - children: [
85   - Offstage(
86   - offstage: (bloc.modelCount < 1),
87   - child: _decodeImageWidget(1),
88   - ),
89   - Offstage(
90   - offstage: (bloc.modelCount < 2),
91   - child: _decodeImageWidget(2),
92   - ),
93   - Offstage(
94   - offstage: (bloc.modelCount < 3),
95   - child: _decodeImageWidget(3),
96   - ),
97   - Offstage(
98   - offstage: (bloc.modelCount < 4),
99   - child: _decodeImageWidget(4),
100   - )
101   - ],
102   - )
103   - ],
104   - ),
105   - );
106   - });
107   -
108   - Widget _decodeImageWidget(int index) => BlocBuilder<VoiceWordBloc,VoiceWordState>(
109   - buildWhen: (_, s) => s is SelectItemChangeState,
110   - builder: (context,state){
111   - final bloc = BlocProvider.of<VoiceWordBloc>(context);
112   - return GestureDetector(
113   - onTap: () => bloc.add(SelectItemEvent(index)),
114   - child: Container(
115   - width: 143.w,
116   - height: 143.h,
117   - padding: EdgeInsets.only(left: 13.w,right: 13.w,top: 13.h,bottom: 13.h),
118   - decoration: BoxDecoration(
119   - color: Colors.white,
120   - borderRadius: BorderRadius.circular(15),
121   - border: Border.all(
122   - width: 1.0,
123   - color: const Color(0xFF140C10)
124   - ),
125   - ),
126   - child: Column(
127   - mainAxisAlignment: MainAxisAlignment.end,
128   - children: [
129   - Expanded(
130   - child: Container(
131   - alignment: Alignment.center,
132   - child: Text(
133   - 'yellow',
134   - style: TextStyle(
135   - fontSize: 20.sp,
136   - color: const Color(0xFF333333)
137   - )
138   - ),
139   - ),
140   - ),
141   - Container(
142   - height: 30.h,
143   - width: double.infinity,
144   - decoration: BoxDecoration(
145   - color: bloc.selectItem == index?const Color(0xFF00B6F1):Colors.white,
146   - borderRadius: BorderRadius.circular(15.r),
147   - border: Border.all(
148   - width: 1.5,
149   - color: const Color(0xFF140C10)
150   - ),
151   - ),
152   - alignment: Alignment.center,
153   - child: Image.asset('choose'.assetPng),
154   - )
155   - ],
156   - ),
157   - ),
158   - );
159   - });
160   -}
161 0 \ No newline at end of file
lib/pages/repeatafter/bloc/repeat_after_bloc.dart
... ... @@ -15,17 +15,15 @@ class RepeatAfterBloc extends Bloc&lt;RepeatAfterEvent, RepeatAfterState&gt; {
15 15 List<FollowReadEntity?> get listData => _listData;
16 16  
17 17 RepeatAfterBloc() : super(RepeatAfterInitial()) {
18   - on<RepeatAfterEvent>((event, emit) {
19   - // TODO: implement event handler
20   - });
  18 + on<RequestDataEvent>(_requestData);
21 19 }
22 20  
23 21  
24   - Future<void> requestData() async {
  22 + void _requestData(RequestDataEvent event, Emitter<RepeatAfterState> emitter) async {
25 23 try {
26 24 await loading(() async {
27 25 _listData = await ListenDao.followRead()??[];
28   - emit(RequestDataState());
  26 + emitter(RequestDataState());
29 27 });
30 28 } catch (e) {
31 29 if (e is ApiException) {
... ...
lib/pages/repeatafter/bloc/repeat_after_event.dart
... ... @@ -2,3 +2,5 @@ part of &#39;repeat_after_bloc.dart&#39;;
2 2  
3 3 @immutable
4 4 abstract class RepeatAfterEvent {}
  5 +
  6 +class RequestDataEvent extends RepeatAfterEvent {}
... ...
lib/pages/repeatafter/repeat_after_page.dart
... ... @@ -13,7 +13,7 @@ class RepeatAfterPage extends StatelessWidget {
13 13 @override
14 14 Widget build(BuildContext context) {
15 15 return BlocProvider(
16   - create: (context) => RepeatAfterBloc()..requestData(),
  16 + create: (context) => RepeatAfterBloc()..add(RequestDataEvent()),
17 17 child: _RepeatAfterPageView(),
18 18 );
19 19 }
... ...
lib/pages/video/lookvideo/look_video_page.dart
1 1 import 'package:flutter/material.dart';
2   -import 'package:flutter_bloc/flutter_bloc.dart';
3 2 import 'package:wow_english/pages/video/lookvideo/widgets/video_widget.dart';
4 3  
5   -import 'bloc/look_video_bloc.dart';
6   -
7 4 class LookVideoPage extends StatefulWidget {
8   - const LookVideoPage({super.key, this.videoUrl});
  5 + const LookVideoPage({super.key, this.videoUrl, this.typeTitle});
9 6  
10 7 final String? videoUrl;
  8 + final String? typeTitle;
11 9  
12 10 @override
13 11 State<StatefulWidget> createState() {
... ... @@ -20,23 +18,7 @@ class _LookVideoPageState extends State&lt;LookVideoPage&gt; {
20 18 Widget build(BuildContext context) {
21 19 return VideoWidget(
22 20 videoUrl: widget.videoUrl??'',
  21 + typeTitle: widget.typeTitle,
23 22 );
24 23 }
25   -}
26   -
27   -class _LookVideoPage extends StatelessWidget {
28   - @override
29   - Widget build(BuildContext context) {
30   - return BlocListener<LookVideoBloc, LookVideoState>(
31   - listener: (context,state){},
32   - child: _lookVideoView(),
33   - );
34   - }
35   -
36   - Widget _lookVideoView() => BlocBuilder<LookVideoBloc, LookVideoState>(
37   - builder: (context,state){
38   - return const VideoWidget(
39   - videoUrl: 'https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/7194236f31b2e1e3da0fe06cfed4ba2b.mp4',
40   - );
41   - });
42 24 }
43 25 \ No newline at end of file
... ...
lib/pages/video/lookvideo/widgets/video_opera_widget.dart
... ... @@ -20,7 +20,8 @@ class VideoOperaWidget extends StatefulWidget {
20 20 this.degree = 0.0,
21 21 this.actionEvent,
22 22 this.sliderChangeEvent,
23   - this.isPlay = true
  23 + this.isPlay = true,
  24 + this.title = 'song',
24 25 });
25 26 //当前播放时间
26 27 final String currentTime;
... ... @@ -28,6 +29,7 @@ class VideoOperaWidget extends StatefulWidget {
28 29 final String totalTime;
29 30 final double degree;
30 31 final bool isPlay;
  32 + final String title;
31 33 final Function(OperationType type)? actionEvent;
32 34 final Function(double degree)? sliderChangeEvent;
33 35  
... ... @@ -90,7 +92,7 @@ class _VideoOperaWidgetState extends State&lt;VideoOperaWidget&gt; {
90 92 ),
91 93 padding: EdgeInsets.symmetric(horizontal: 10.w),
92 94 child: Text(
93   - 'song',
  95 + widget.title,
94 96 textAlign: TextAlign.center,
95 97 style: TextStyle(
96 98 fontSize: 20.sp,
... ... @@ -100,31 +102,31 @@ class _VideoOperaWidgetState extends State&lt;VideoOperaWidget&gt; {
100 102 )
101 103 ],
102 104 ),
103   - GestureDetector(
104   - onTap: () {
105   - widget.actionEvent?.call(OperationType.subtitlesState);
106   - },
107   - child: Container(
108   - height: 40.h,
109   - alignment: Alignment.center,
110   - decoration: BoxDecoration(
111   - color: Colors.white,
112   - borderRadius: BorderRadius.circular(6.r),
113   - border: Border.all(
114   - width: 1.5,
115   - color: const Color(0xFF140C10)
116   - )
117   - ),
118   - padding: EdgeInsets.symmetric(horizontal: 10.w),
119   - child: Text(
120   - '中/英',
121   - style: TextStyle(
122   - fontSize: 20.sp,
123   - color: const Color(0xFF333333),
124   - ),
125   - ),
126   - ),
127   - )
  105 + // GestureDetector(
  106 + // onTap: () {
  107 + // widget.actionEvent?.call(OperationType.subtitlesState);
  108 + // },
  109 + // child: Container(
  110 + // height: 40.h,
  111 + // alignment: Alignment.center,
  112 + // decoration: BoxDecoration(
  113 + // color: Colors.white,
  114 + // borderRadius: BorderRadius.circular(6.r),
  115 + // border: Border.all(
  116 + // width: 1.5,
  117 + // color: const Color(0xFF140C10)
  118 + // )
  119 + // ),
  120 + // padding: EdgeInsets.symmetric(horizontal: 10.w),
  121 + // child: Text(
  122 + // '中/英',
  123 + // style: TextStyle(
  124 + // fontSize: 20.sp,
  125 + // color: const Color(0xFF333333),
  126 + // ),
  127 + // ),
  128 + // ),
  129 + // )
128 130 ],
129 131 ),
130 132 ),
... ...
lib/pages/video/lookvideo/widgets/video_widget.dart
... ... @@ -7,9 +7,10 @@ import &#39;package:wow_english/common/extension/string_extension.dart&#39;;
7 7 import 'video_opera_widget.dart';
8 8  
9 9 class VideoWidget extends StatefulWidget {
10   - const VideoWidget({super.key, this.videoUrl = ''});
  10 + const VideoWidget({super.key, this.videoUrl = '',this.typeTitle});
11 11  
12 12 final String videoUrl;
  13 + final String? typeTitle;
13 14  
14 15 @override
15 16 State<StatefulWidget> createState() {
... ... @@ -53,9 +54,6 @@ class _VideoWidgetState extends State&lt;VideoWidget&gt; {
53 54 timerUtil = TimerUtil(mInterval: 1000,mTotalTime: 1000*10);
54 55 timerUtil!.setOnTimerTickCallback((int tick) {
55 56 double currentTick = tick / 1000;
56   - if (kDebugMode) {
57   - print(currentTick);
58   - }
59 57 if (currentTick.toInt() == 0) {//倒计时结束
60 58 setState(() {
61 59 _hiddenTipView = true;
... ... @@ -148,9 +146,10 @@ class _VideoWidgetState extends State&lt;VideoWidget&gt; {
148 146 Offstage(
149 147 offstage: _hiddenTipView,
150 148 child: VideoOperaWidget(
151   - currentTime: _currentTime,
152   - totalTime: _totalTime,
  149 + title: widget.typeTitle??'song',
153 150 degree: _playDegree,
  151 + totalTime: _totalTime,
  152 + currentTime: _currentTime,
154 153 isPlay: _controller!.value.isPlaying,
155 154 actionEvent: (OperationType type) {
156 155 actionType(type);
... ...
lib/pages/voiceanswer/bloc/voice_answer_bloc.dart deleted
1   -import 'package:flutter/cupertino.dart';
2   -import 'package:flutter_bloc/flutter_bloc.dart';
3   -
4   -part 'voice_answer_event.dart';
5   -part 'voice_answer_state.dart';
6   -
7   -class VoiceAnswerBloc extends Bloc<VoiceAnswerEvent, VoiceAnswerState> {
8   - VoiceAnswerBloc() : super(VoiceAnswerInitial()) {
9   - on<VoiceAnswerEvent>((event, emit) {
10   - // TODO: implement event handler
11   - });
12   - }
13   -}
lib/pages/voiceanswer/bloc/voice_answer_event.dart deleted
1   -part of 'voice_answer_bloc.dart';
2   -
3   -@immutable
4   -abstract class VoiceAnswerEvent {}
lib/pages/voiceanswer/bloc/voice_answer_state.dart deleted
1   -part of 'voice_answer_bloc.dart';
2   -
3   -@immutable
4   -abstract class VoiceAnswerState {}
5   -
6   -class VoiceAnswerInitial extends VoiceAnswerState {}
lib/pages/voiceanswer/voice_answer_page.dart deleted
1   -import 'package:flutter/material.dart';
2   -import 'package:flutter_bloc/flutter_bloc.dart';
3   -import 'package:flutter_screenutil/flutter_screenutil.dart';
4   -import 'package:wow_english/common/extension/string_extension.dart';
5   -import 'package:wow_english/pages/practice/widgets/practice_header_widget.dart';
6   -
7   -import 'bloc/voice_answer_bloc.dart';
8   -
9   -class VoiceAnswerPage extends StatelessWidget {
10   - const VoiceAnswerPage({super.key});
11   -
12   - @override
13   - Widget build(BuildContext context) {
14   - return BlocProvider(
15   - create: (_) => VoiceAnswerBloc(),
16   - child: _VoiceAnswerPage(),
17   - );
18   - }
19   -}
20   -
21   -class _VoiceAnswerPage extends StatelessWidget {
22   - @override
23   - Widget build(BuildContext context) {
24   - return BlocListener<VoiceAnswerBloc,VoiceAnswerState>(
25   - listener: (context, state) {},
26   - child: _voiceAnswerView(),
27   - );
28   - }
29   -
30   - Widget _voiceAnswerView() => BlocBuilder<VoiceAnswerBloc,VoiceAnswerState>(
31   - builder: (context, state) {
32   - final bloc = BlocProvider.of<VoiceAnswerBloc>(context);
33   - return Container(
34   - color: Colors.white,
35   - child: Stack(
36   - children: [
37   - Positioned(
38   - left: 0,
39   - right: 0,
40   - bottom: 0,
41   - child: Image.asset(
42   - 'bottom_grass'.assetPng,
43   - fit: BoxFit.fitWidth,
44   - )),
45   - Column(
46   - children: [
47   - PracticeHeaderWidget(
48   - title: '1/8',
49   - onTap: () {
50   - Navigator.pop(context);
51   - },
52   - ),
53   - Expanded(
54   - child: PageView.builder(
55   - itemCount: 10,
56   - itemBuilder: (context, int index) {
57   - return _voiceAnswerItem();
58   - }))
59   - ],
60   - )
61   - ],
62   - ),
63   - );
64   - });
65   -
66   - Widget _voiceAnswerItem() => BlocBuilder<VoiceAnswerBloc,VoiceAnswerState>(builder: (context, state) {
67   - return Row(
68   - mainAxisAlignment: MainAxisAlignment.center,
69   - children: [
70   - Image.network(
71   - 'https://img.liblibai.com/web/648331d5a2cb5.png?image_process=format,webp&x-oss-process=image/resize,w_2980,m_lfit/format,webp',
72   - height: 186.h,
73   - width: 186.w,
74   - ),
75   - 160.horizontalSpace,
76   - Column(
77   - mainAxisAlignment: MainAxisAlignment.center,
78   - children: [
79   - Image.asset(
80   - 'voice'.assetPng,
81   - height: 52.h,
82   - width: 46.w,
83   - ),
84   - 70.verticalSpace,
85   - Image.asset(
86   - 'micro_phone'.assetPng,
87   - height: 75.w,
88   - width: 75.w,
89   - )
90   - ],
91   - )
92   - ],
93   - );
94   - });
95   -}
lib/route/route.dart
... ... @@ -8,10 +8,7 @@ import &#39;package:wow_english/pages/listen/listen_page.dart&#39;;
8 8 import 'package:wow_english/pages/login/forgetpwd/forget_password_home_page.dart';
9 9 import 'package:wow_english/pages/login/loginpage/login_page.dart';
10 10 import 'package:wow_english/pages/login/setpwd/set_pwd_page.dart';
11   -import 'package:wow_english/pages/practice/chosetopic/topicpicture/topic_picture_page.dart';
12   -import 'package:wow_english/pages/practice/chosetopic/topicword/topic_word_page.dart';
13   -import 'package:wow_english/pages/practice/voicetopic/voicepicture/voice_pic_page.dart';
14   -import 'package:wow_english/pages/practice/voicetopic/voiceword/voice_word_page.dart';
  11 +import 'package:wow_english/pages/practice/topic_picture_page.dart';
15 12 import 'package:wow_english/pages/repeatafter/repeat_after_page.dart';
16 13 import 'package:wow_english/pages/shop/exchane/exchange_lesson_page.dart';
17 14 import 'package:wow_english/pages/shop/exchangelist/exchange_lesson_list_page.dart';
... ... @@ -19,7 +16,6 @@ import &#39;package:wow_english/pages/shop/home/shop_home_page.dart&#39;;
19 16 import 'package:wow_english/pages/tab/tab_page.dart';
20 17 import 'package:wow_english/pages/user/user_page.dart';
21 18 import 'package:wow_english/pages/video/lookvideo/look_video_page.dart';
22   -import 'package:wow_english/pages/voiceanswer/voice_answer_page.dart';
23 19  
24 20 import '../pages/reading/reading_page.dart';
25 21  
... ... @@ -87,17 +83,10 @@ class AppRouter {
87 83 return CupertinoPageRoute(builder: (_) => const UserPage());
88 84 case AppRouteName.topicPic:
89 85 return CupertinoPageRoute(builder: (_) => const TopicPicturePage());
90   - case AppRouteName.topicWord:
91   - return CupertinoPageRoute(builder: (_) => const TopicWordPage());
92   - case AppRouteName.voicePic:
93   - return CupertinoPageRoute(builder: (_) => const VoicePicPage());
94   - case AppRouteName.voiceWord:
95   - return CupertinoPageRoute(builder: (_) => const VoiceWordPage());
96   - case AppRouteName.voiceAnswer:
97   - return CupertinoPageRoute(builder: (_) => const VoiceAnswerPage());
98 86 case AppRouteName.lookVideo:
99 87 final videoUrl = (settings.arguments as Map)['videoUrl'] as String;
100   - return CupertinoPageRoute(builder: (_) => LookVideoPage(videoUrl: videoUrl,));
  88 + final title = (settings.arguments as Map)['title'] as String?;
  89 + return CupertinoPageRoute(builder: (_) => LookVideoPage(videoUrl: videoUrl,typeTitle: title,));
101 90 case AppRouteName.setPwd:
102 91 final phoneNum = (settings.arguments as Map)['phoneNumber'] as String;
103 92 return CupertinoPageRoute(builder: (_) => SetPassWordPage(phoneNum: phoneNum));
... ...