Commit 2512b58cfb93b0db16705ff0f2cc99cb6e84b76e
1 parent
0ebc6186
feat:性能优化-练习页PageView根据是否是当前页来决定build以及SpeakerWidget组件isPlaying
Showing
1 changed file
with
161 additions
and
145 deletions
lib/pages/practice/topic_picture_page.dart
| @@ -93,28 +93,36 @@ class _TopicPicturePage extends StatelessWidget { | @@ -93,28 +93,36 @@ class _TopicPicturePage extends StatelessWidget { | ||
| 93 | bloc.add(CurrentPageIndexChangeEvent(index)); | 93 | bloc.add(CurrentPageIndexChangeEvent(index)); |
| 94 | }, | 94 | }, |
| 95 | itemBuilder: (BuildContext context, int index) { | 95 | itemBuilder: (BuildContext context, int index) { |
| 96 | + final bloc = | ||
| 97 | + BlocProvider.of<TopicPictureBloc>(context); | ||
| 96 | CourseProcessTopics? topics = | 98 | CourseProcessTopics? topics = |
| 97 | bloc.entity?.topics![index]; | 99 | bloc.entity?.topics![index]; |
| 100 | + bool isCurrentPage = | ||
| 101 | + index == bloc.currentPage - 1; | ||
| 98 | if (topics?.type == | 102 | if (topics?.type == |
| 99 | TopicType.audioImageSelect.value) { | 103 | TopicType.audioImageSelect.value) { |
| 100 | //听音选图 | 104 | //听音选图 |
| 101 | return _pageViewVoicePictureItemWidget( | 105 | return _pageViewVoicePictureItemWidget( |
| 102 | - topics); | 106 | + topics, isCurrentPage); |
| 103 | } else if (topics?.type == | 107 | } else if (topics?.type == |
| 104 | TopicType.audioCharSelect.value) { | 108 | TopicType.audioCharSelect.value) { |
| 105 | //听音选字 | 109 | //听音选字 |
| 106 | - return _pageViewVoiceWordItemWidget(topics); | 110 | + return _pageViewVoiceWordItemWidget( |
| 111 | + topics, isCurrentPage); | ||
| 107 | } else if (topics?.type == | 112 | } else if (topics?.type == |
| 108 | TopicType.questionCharSelect.value) { | 113 | TopicType.questionCharSelect.value) { |
| 109 | //看题选字 | 114 | //看题选字 |
| 110 | - return _pageViewWordItemWidget(topics); | 115 | + return _pageViewWordItemWidget( |
| 116 | + topics, isCurrentPage); | ||
| 111 | } else if (topics?.type == | 117 | } else if (topics?.type == |
| 112 | TopicType.questionImageSelect.value) { | 118 | TopicType.questionImageSelect.value) { |
| 113 | //看题选图 | 119 | //看题选图 |
| 114 | - return _pageViewItemWidget(topics); | 120 | + return _pageViewItemWidget( |
| 121 | + topics, isCurrentPage); | ||
| 115 | } else { | 122 | } else { |
| 116 | //语音问答 | 123 | //语音问答 |
| 117 | - return _voiceAnswerItem(topics); | 124 | + return _voiceAnswerItem( |
| 125 | + topics, isCurrentPage); | ||
| 118 | } | 126 | } |
| 119 | }), | 127 | }), |
| 120 | ) | 128 | ) |
| @@ -130,33 +138,34 @@ class _TopicPicturePage extends StatelessWidget { | @@ -130,33 +138,34 @@ class _TopicPicturePage extends StatelessWidget { | ||
| 130 | }); | 138 | }); |
| 131 | 139 | ||
| 132 | ///看题选图 | 140 | ///看题选图 |
| 133 | - Widget _pageViewItemWidget(CourseProcessTopics? topics) => | 141 | + Widget _pageViewItemWidget(CourseProcessTopics? topics, bool isCurrentPage) => |
| 134 | BlocBuilder<TopicPictureBloc, TopicPictureState>( | 142 | BlocBuilder<TopicPictureBloc, TopicPictureState>( |
| 143 | + buildWhen: (_, s) => isCurrentPage, | ||
| 135 | builder: (context, state) { | 144 | builder: (context, state) { |
| 136 | - return SafeArea( | ||
| 137 | - child: Column( | ||
| 138 | - children: [ | ||
| 139 | - Text(topics?.word ?? '', | ||
| 140 | - softWrap: true, | ||
| 141 | - style: TextStyle( | ||
| 142 | - fontSize: 21.sp, color: const Color(0xFF333333))), | ||
| 143 | - 26.verticalSpace, | ||
| 144 | - SizedBox( | ||
| 145 | - height: 143.h, | ||
| 146 | - width: 143.w * (topics?.topicAnswerList?.length ?? 0), | ||
| 147 | - child: ListView.builder( | ||
| 148 | - scrollDirection: Axis.horizontal, | ||
| 149 | - physics: const NeverScrollableScrollPhysics(), | ||
| 150 | - itemCount: topics?.topicAnswerList?.length ?? 0, | ||
| 151 | - itemBuilder: (context, index) { | ||
| 152 | - return _decodeImageWidget( | ||
| 153 | - index, topics?.topicAnswerList?[index]); | ||
| 154 | - }), | 145 | + return SafeArea( |
| 146 | + child: Column( | ||
| 147 | + children: [ | ||
| 148 | + Text(topics?.word ?? '', | ||
| 149 | + softWrap: true, | ||
| 150 | + style: TextStyle( | ||
| 151 | + fontSize: 21.sp, color: const Color(0xFF333333))), | ||
| 152 | + 26.verticalSpace, | ||
| 153 | + SizedBox( | ||
| 154 | + height: 143.h, | ||
| 155 | + width: 143.w * (topics?.topicAnswerList?.length ?? 0), | ||
| 156 | + child: ListView.builder( | ||
| 157 | + scrollDirection: Axis.horizontal, | ||
| 158 | + physics: const NeverScrollableScrollPhysics(), | ||
| 159 | + itemCount: topics?.topicAnswerList?.length ?? 0, | ||
| 160 | + itemBuilder: (context, index) { | ||
| 161 | + return _decodeImageWidget( | ||
| 162 | + index, topics?.topicAnswerList?[index]); | ||
| 163 | + }), | ||
| 164 | + ), | ||
| 165 | + ], | ||
| 155 | ), | 166 | ), |
| 156 | - ], | ||
| 157 | - ), | ||
| 158 | - ); | ||
| 159 | - }); | 167 | + ); |
| 168 | + }); | ||
| 160 | 169 | ||
| 161 | Widget _decodeImageWidget( | 170 | Widget _decodeImageWidget( |
| 162 | int index, CourseProcessTopicsTopicAnswerList? answerLis) => | 171 | int index, CourseProcessTopicsTopicAnswerList? answerLis) => |
| @@ -198,33 +207,35 @@ class _TopicPicturePage extends StatelessWidget { | @@ -198,33 +207,35 @@ class _TopicPicturePage extends StatelessWidget { | ||
| 198 | }); | 207 | }); |
| 199 | 208 | ||
| 200 | ///看题选字 | 209 | ///看题选字 |
| 201 | - Widget _pageViewWordItemWidget(CourseProcessTopics? topics) => | 210 | + Widget _pageViewWordItemWidget( |
| 211 | + CourseProcessTopics? topics, bool isCurrentPage) => | ||
| 202 | BlocBuilder<TopicPictureBloc, TopicPictureState>( | 212 | BlocBuilder<TopicPictureBloc, TopicPictureState>( |
| 213 | + buildWhen: (_, s) => isCurrentPage, | ||
| 203 | builder: (context, state) { | 214 | builder: (context, state) { |
| 204 | - return SafeArea( | ||
| 205 | - child: Column( | ||
| 206 | - children: [ | ||
| 207 | - Text(topics?.word ?? '', | ||
| 208 | - softWrap: true, | ||
| 209 | - style: TextStyle( | ||
| 210 | - fontSize: 21.sp, color: const Color(0xFF333333))), | ||
| 211 | - 26.verticalSpace, | ||
| 212 | - SizedBox( | ||
| 213 | - height: 143.h, | ||
| 214 | - width: 143.w * (topics?.topicAnswerList?.length ?? 0), | ||
| 215 | - child: ListView.builder( | ||
| 216 | - scrollDirection: Axis.horizontal, | ||
| 217 | - itemCount: topics?.topicAnswerList?.length ?? 0, | ||
| 218 | - physics: const NeverScrollableScrollPhysics(), | ||
| 219 | - itemBuilder: (context, index) { | ||
| 220 | - return _decodeWordWidget( | ||
| 221 | - index, topics?.topicAnswerList?[index]); | ||
| 222 | - }), | 215 | + return SafeArea( |
| 216 | + child: Column( | ||
| 217 | + children: [ | ||
| 218 | + Text(topics?.word ?? '', | ||
| 219 | + softWrap: true, | ||
| 220 | + style: TextStyle( | ||
| 221 | + fontSize: 21.sp, color: const Color(0xFF333333))), | ||
| 222 | + 26.verticalSpace, | ||
| 223 | + SizedBox( | ||
| 224 | + height: 143.h, | ||
| 225 | + width: 143.w * (topics?.topicAnswerList?.length ?? 0), | ||
| 226 | + child: ListView.builder( | ||
| 227 | + scrollDirection: Axis.horizontal, | ||
| 228 | + itemCount: topics?.topicAnswerList?.length ?? 0, | ||
| 229 | + physics: const NeverScrollableScrollPhysics(), | ||
| 230 | + itemBuilder: (context, index) { | ||
| 231 | + return _decodeWordWidget( | ||
| 232 | + index, topics?.topicAnswerList?[index]); | ||
| 233 | + }), | ||
| 234 | + ), | ||
| 235 | + ], | ||
| 223 | ), | 236 | ), |
| 224 | - ], | ||
| 225 | - ), | ||
| 226 | - ); | ||
| 227 | - }); | 237 | + ); |
| 238 | + }); | ||
| 228 | 239 | ||
| 229 | Widget _decodeWordWidget( | 240 | Widget _decodeWordWidget( |
| 230 | int index, CourseProcessTopicsTopicAnswerList? answerLis) => | 241 | int index, CourseProcessTopicsTopicAnswerList? answerLis) => |
| @@ -285,9 +296,12 @@ class _TopicPicturePage extends StatelessWidget { | @@ -285,9 +296,12 @@ class _TopicPicturePage extends StatelessWidget { | ||
| 285 | }); | 296 | }); |
| 286 | 297 | ||
| 287 | ///听音选图 | 298 | ///听音选图 |
| 288 | - Widget _pageViewVoicePictureItemWidget(CourseProcessTopics? topics) => | 299 | + Widget _pageViewVoicePictureItemWidget( |
| 300 | + CourseProcessTopics? topics, bool isCurrentPage) => | ||
| 289 | BlocBuilder<TopicPictureBloc, TopicPictureState>( | 301 | BlocBuilder<TopicPictureBloc, TopicPictureState>( |
| 290 | - builder: (context, state) { | 302 | + buildWhen: (previous, current) { |
| 303 | + return isCurrentPage; | ||
| 304 | + }, builder: (context, state) { | ||
| 291 | final bloc = BlocProvider.of<TopicPictureBloc>(context); | 305 | final bloc = BlocProvider.of<TopicPictureBloc>(context); |
| 292 | return SafeArea( | 306 | return SafeArea( |
| 293 | child: Column( | 307 | child: Column( |
| @@ -296,10 +310,9 @@ class _TopicPicturePage extends StatelessWidget { | @@ -296,10 +310,9 @@ class _TopicPicturePage extends StatelessWidget { | ||
| 296 | mainAxisAlignment: MainAxisAlignment.center, | 310 | mainAxisAlignment: MainAxisAlignment.center, |
| 297 | children: [ | 311 | children: [ |
| 298 | SpeakerWidget( | 312 | SpeakerWidget( |
| 299 | - isPlaying: bloc.voicePlayState == VoicePlayState.playing, | 313 | + isPlaying: isCurrentPage && |
| 314 | + bloc.voicePlayState == VoicePlayState.playing, | ||
| 300 | // 控制动画播放 | 315 | // 控制动画播放 |
| 301 | - isClickable: true, | ||
| 302 | - // 控制是否可点击 | ||
| 303 | width: 32.w, | 316 | width: 32.w, |
| 304 | height: 32.w, | 317 | height: 32.w, |
| 305 | onTap: () { | 318 | onTap: () { |
| @@ -368,41 +381,41 @@ class _TopicPicturePage extends StatelessWidget { | @@ -368,41 +381,41 @@ class _TopicPicturePage extends StatelessWidget { | ||
| 368 | }); | 381 | }); |
| 369 | 382 | ||
| 370 | ///听音选字 | 383 | ///听音选字 |
| 371 | - Widget _pageViewVoiceWordItemWidget(CourseProcessTopics? topics) => | 384 | + Widget _pageViewVoiceWordItemWidget( |
| 385 | + CourseProcessTopics? topics, bool isCurrentPage) => | ||
| 372 | BlocBuilder<TopicPictureBloc, TopicPictureState>( | 386 | BlocBuilder<TopicPictureBloc, TopicPictureState>( |
| 387 | + buildWhen: (_, s) => isCurrentPage, | ||
| 373 | builder: (context, state) { | 388 | builder: (context, state) { |
| 374 | - final bloc = BlocProvider.of<TopicPictureBloc>(context); | ||
| 375 | - return SafeArea( | ||
| 376 | - child: Column( | ||
| 377 | - children: [ | ||
| 378 | - SpeakerWidget( | ||
| 379 | - isPlaying: bloc.voicePlayState == VoicePlayState.playing, | ||
| 380 | - // 控制动画播放 | ||
| 381 | - isClickable: true, | ||
| 382 | - // 控制是否可点击 | ||
| 383 | - width: 32.w, | ||
| 384 | - height: 32.w, | ||
| 385 | - onTap: () { | ||
| 386 | - bloc.add(VoicePlayEvent()); | ||
| 387 | - }, | ||
| 388 | - ), | ||
| 389 | - 26.verticalSpace, | ||
| 390 | - SizedBox( | ||
| 391 | - width: 163.w * (topics?.topicAnswerList?.length ?? 0), | ||
| 392 | - height: 143.h, | ||
| 393 | - child: ListView.builder( | ||
| 394 | - scrollDirection: Axis.horizontal, | ||
| 395 | - itemCount: topics?.topicAnswerList?.length, | ||
| 396 | - physics: const NeverScrollableScrollPhysics(), | ||
| 397 | - itemBuilder: (BuildContext context, int index) { | ||
| 398 | - return _decodeVoiceWordImageWidget( | ||
| 399 | - index, topics!.topicAnswerList![index]); | ||
| 400 | - }), | 389 | + final bloc = BlocProvider.of<TopicPictureBloc>(context); |
| 390 | + return SafeArea( | ||
| 391 | + child: Column( | ||
| 392 | + children: [ | ||
| 393 | + SpeakerWidget( | ||
| 394 | + isPlaying: isCurrentPage && | ||
| 395 | + bloc.voicePlayState == VoicePlayState.playing, | ||
| 396 | + width: 32.w, | ||
| 397 | + height: 32.w, | ||
| 398 | + onTap: () { | ||
| 399 | + bloc.add(VoicePlayEvent()); | ||
| 400 | + }, | ||
| 401 | + ), | ||
| 402 | + 26.verticalSpace, | ||
| 403 | + SizedBox( | ||
| 404 | + width: 163.w * (topics?.topicAnswerList?.length ?? 0), | ||
| 405 | + height: 143.h, | ||
| 406 | + child: ListView.builder( | ||
| 407 | + scrollDirection: Axis.horizontal, | ||
| 408 | + itemCount: topics?.topicAnswerList?.length, | ||
| 409 | + physics: const NeverScrollableScrollPhysics(), | ||
| 410 | + itemBuilder: (BuildContext context, int index) { | ||
| 411 | + return _decodeVoiceWordImageWidget( | ||
| 412 | + index, topics!.topicAnswerList![index]); | ||
| 413 | + }), | ||
| 414 | + ), | ||
| 415 | + ], | ||
| 401 | ), | 416 | ), |
| 402 | - ], | ||
| 403 | - ), | ||
| 404 | - ); | ||
| 405 | - }); | 417 | + ); |
| 418 | + }); | ||
| 406 | 419 | ||
| 407 | Widget _decodeVoiceWordImageWidget( | 420 | Widget _decodeVoiceWordImageWidget( |
| 408 | int index, CourseProcessTopicsTopicAnswerList answerList) => | 421 | int index, CourseProcessTopicsTopicAnswerList answerList) => |
| @@ -465,71 +478,74 @@ class _TopicPicturePage extends StatelessWidget { | @@ -465,71 +478,74 @@ class _TopicPicturePage extends StatelessWidget { | ||
| 465 | }); | 478 | }); |
| 466 | 479 | ||
| 467 | ///语音问答 | 480 | ///语音问答 |
| 468 | - Widget _voiceAnswerItem(CourseProcessTopics? topics) => | 481 | + Widget _voiceAnswerItem(CourseProcessTopics? topics, bool isCurrentPage) => |
| 469 | BlocBuilder<TopicPictureBloc, TopicPictureState>( | 482 | BlocBuilder<TopicPictureBloc, TopicPictureState>( |
| 483 | + buildWhen: (_, s) => isCurrentPage, | ||
| 470 | builder: (context, state) { | 484 | builder: (context, state) { |
| 471 | - final bloc = BlocProvider.of<TopicPictureBloc>(context); | ||
| 472 | - return Row( | ||
| 473 | - mainAxisAlignment: MainAxisAlignment.center, | ||
| 474 | - children: [ | ||
| 475 | - ClipRRect( | ||
| 476 | - borderRadius: BorderRadius.circular(20), | ||
| 477 | - child: Container( | ||
| 478 | - color: Colors.white, | ||
| 479 | - child: OwImageWidget( | ||
| 480 | - name: topics?.picUrl ?? '', | ||
| 481 | - height: 186.h, | ||
| 482 | - width: 186.w, | ||
| 483 | - ), | ||
| 484 | - ), | ||
| 485 | - ), | ||
| 486 | - 120.horizontalSpace, | ||
| 487 | - Column( | 485 | + final bloc = BlocProvider.of<TopicPictureBloc>(context); |
| 486 | + return Row( | ||
| 488 | mainAxisAlignment: MainAxisAlignment.center, | 487 | mainAxisAlignment: MainAxisAlignment.center, |
| 489 | children: [ | 488 | children: [ |
| 490 | - Row( | 489 | + ClipRRect( |
| 490 | + borderRadius: BorderRadius.circular(20), | ||
| 491 | + child: Container( | ||
| 492 | + color: Colors.white, | ||
| 493 | + child: OwImageWidget( | ||
| 494 | + name: topics?.picUrl ?? '', | ||
| 495 | + height: 186.h, | ||
| 496 | + width: 186.w, | ||
| 497 | + ), | ||
| 498 | + ), | ||
| 499 | + ), | ||
| 500 | + 120.horizontalSpace, | ||
| 501 | + Column( | ||
| 502 | + mainAxisAlignment: MainAxisAlignment.center, | ||
| 491 | children: [ | 503 | children: [ |
| 492 | - SpeakerWidget( | ||
| 493 | - isPlaying: bloc.voicePlayState == VoicePlayState.playing, | ||
| 494 | - // 控制动画播放 | ||
| 495 | - isClickable: !bloc.isRecording, | ||
| 496 | - // 控制是否可点击 | ||
| 497 | - width: 45.w, | ||
| 498 | - height: 45.w, | 504 | + Row( |
| 505 | + children: [ | ||
| 506 | + SpeakerWidget( | ||
| 507 | + isPlaying: isCurrentPage && | ||
| 508 | + bloc.voicePlayState == VoicePlayState.playing, | ||
| 509 | + // 控制动画播放 | ||
| 510 | + isClickable: !bloc.isRecording, | ||
| 511 | + // 控制是否可点击 | ||
| 512 | + width: 45.w, | ||
| 513 | + height: 45.w, | ||
| 514 | + onTap: () { | ||
| 515 | + bloc.add(VoicePlayEvent()); | ||
| 516 | + }, | ||
| 517 | + ), | ||
| 518 | + 10.horizontalSpace, | ||
| 519 | + Text(topics?.word ?? '') | ||
| 520 | + ], | ||
| 521 | + ), | ||
| 522 | + 70.verticalSpace, | ||
| 523 | + RecorderWidget( | ||
| 524 | + isPlaying: bloc.isRecording, | ||
| 525 | + isClickable: | ||
| 526 | + bloc.voicePlayState != VoicePlayState.playing, | ||
| 527 | + width: 72.w, | ||
| 528 | + height: 72.w, | ||
| 499 | onTap: () { | 529 | onTap: () { |
| 500 | - bloc.add(VoicePlayEvent()); | 530 | + if (bloc.isRecording) { |
| 531 | + bloc.add(XSVoiceStopEvent()); | ||
| 532 | + return; | ||
| 533 | + } | ||
| 534 | + if (topics?.type == TopicType.voiceQuestion.value || | ||
| 535 | + topics?.type == TopicType.voiceWord.value) { | ||
| 536 | + bloc.add(XSVoiceStartEvent(topics?.keyWord ?? '', '0', | ||
| 537 | + UserUtil.getUser()!.id.toString())); | ||
| 538 | + } else { | ||
| 539 | + bloc.add(XSVoiceStartEvent(topics?.word ?? '', '0', | ||
| 540 | + UserUtil.getUser()!.id.toString())); | ||
| 541 | + } | ||
| 501 | }, | 542 | }, |
| 502 | ), | 543 | ), |
| 503 | - 10.horizontalSpace, | ||
| 504 | - Text(topics?.word ?? '') | ||
| 505 | ], | 544 | ], |
| 506 | - ), | ||
| 507 | - 70.verticalSpace, | ||
| 508 | - RecorderWidget( | ||
| 509 | - isPlaying: bloc.isRecording, | ||
| 510 | - isClickable: bloc.voicePlayState != VoicePlayState.playing, | ||
| 511 | - width: 72.w, | ||
| 512 | - height: 72.w, | ||
| 513 | - onTap: () { | ||
| 514 | - if (bloc.isRecording) { | ||
| 515 | - bloc.add(XSVoiceStopEvent()); | ||
| 516 | - return; | ||
| 517 | - } | ||
| 518 | - if (topics?.type == TopicType.voiceQuestion.value || | ||
| 519 | - topics?.type == TopicType.voiceWord.value) { | ||
| 520 | - bloc.add(XSVoiceStartEvent(topics?.keyWord ?? '', '0', | ||
| 521 | - UserUtil.getUser()!.id.toString())); | ||
| 522 | - } else { | ||
| 523 | - bloc.add(XSVoiceStartEvent(topics?.word ?? '', '0', | ||
| 524 | - UserUtil.getUser()!.id.toString())); | ||
| 525 | - } | ||
| 526 | - }, | ||
| 527 | - ), | 545 | + ) |
| 528 | ], | 546 | ], |
| 529 | - ) | ||
| 530 | - ], | ||
| 531 | - ); | ||
| 532 | - }); | 547 | + ); |
| 548 | + }); | ||
| 533 | 549 | ||
| 534 | Color getResultColor(bool correct) { | 550 | Color getResultColor(bool correct) { |
| 535 | if (correct) { | 551 | if (correct) { |