import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:wow_english/common/core/app_consts.dart'; import 'package:wow_english/common/core/user_util.dart'; import 'package:wow_english/common/extension/string_extension.dart'; import 'package:wow_english/common/widgets/ow_image_widget.dart'; import 'package:wow_english/models/course_process_entity.dart'; import 'package:wow_english/pages/practice/topic_type.dart'; import 'package:wow_english/route/route.dart'; import 'package:wow_english/utils/toast_util.dart'; import '../../common/widgets/throttledGesture_gesture_detector.dart'; import 'bloc/topic_picture_bloc.dart'; import 'widgets/practice_header_widget.dart'; class TopicPicturePage extends StatelessWidget { const TopicPicturePage({super.key, this.courseLessonId, this.moduleColor}); final String? courseLessonId; final Color? moduleColor; @override Widget build(BuildContext context) { return BlocProvider( create: (context) => TopicPictureBloc( context, PageController(), courseLessonId ?? '', moduleColor) ..add(InitBlocEvent()) ..add(RequestDataEvent()) ..add(XSVoiceInitEvent({ 'appKey': AppConsts.xsAppKey, 'service': AppConsts.xsAppService, 'secretKey': AppConsts.xsAppSecretKey, 'userId': UserUtil.getUser()!.id.toString(), })), child: _TopicPicturePage(), ); } } class _TopicPicturePage extends StatelessWidget { @override Widget build(BuildContext context) { return BlocListener( listener: (context, state) { if (state is RequestDataState) { context.read().add(CurrentPageIndexChangeEvent(0)); } if (state is XSVoiceTestState) {} }, child: _topicPictureView(), ); } Widget _topicPictureView() => BlocBuilder( builder: (context, state) { final bloc = BlocProvider.of(context); return Container( decoration: BoxDecoration( image: DecorationImage( image: AssetImage('read_background'.assetPng), // 背景图片路径 fit: BoxFit.cover, // 适应图片的方式 ), ), child: Stack( children: [ Column( children: [ PracticeHeaderWidget( color: bloc.moduleColor, progress: bloc.currentPage, total: bloc.entity?.topics?.length ?? 0, onTap: () { popPage(data: { 'currentStep': bloc.currentPage, 'courseLessonId': bloc.courseLessonId, 'isCompleted': bloc.isLastPage(), }); // Navigator.pop(context); }, ), 35.verticalSpace, Expanded( child: PageView.builder( itemCount: bloc.entity?.topics?.length, scrollDirection: Axis.horizontal, controller: bloc.pageController, onPageChanged: (int index) { bloc.add(CurrentPageIndexChangeEvent(index)); }, itemBuilder: (BuildContext context, int index) { CourseProcessTopics? topics = bloc.entity?.topics![index]; if (topics?.type == TopicType.audioImageSelect.value) { //听音选图 return _pageViewVoicePictureItemWidget(topics); } else if (topics?.type == TopicType.audioCharSelect.value) { //听音选字 return _pageViewVoiceWordItemWidget(topics); } else if (topics?.type == TopicType.questionCharSelect.value) { //看题选字 return _pageViewWordItemWidget(topics); } else if (topics?.type == TopicType.questionImageSelect.value) { //看题选图 return _pageViewItemWidget(topics); } else { //语音问答 return _voiceAnswerItem(topics); } }), ) ], ) ], ), ); }); ///看题选图 Widget _pageViewItemWidget(CourseProcessTopics? topics) => BlocBuilder( builder: (context, state) { return SafeArea( child: Column( children: [ Text(topics?.word ?? '', softWrap: true, style: TextStyle( fontSize: 21.sp, color: const Color(0xFF333333))), 26.verticalSpace, SizedBox( height: 143.h, width: 143.w * (topics?.topicAnswerList?.length ?? 0), child: ListView.builder( scrollDirection: Axis.horizontal, physics: const NeverScrollableScrollPhysics(), itemCount: topics?.topicAnswerList?.length ?? 0, itemBuilder: (context, index) { return _decodeImageWidget( index, topics?.topicAnswerList?[index]); }), ), ], ), ); }); Widget _decodeImageWidget( int index, CourseProcessTopicsTopicAnswerList? answerLis) => BlocBuilder( buildWhen: (_, s) => s is SelectItemChangeState, builder: (context, state) { final bloc = BlocProvider.of(context); return Container( padding: EdgeInsets.symmetric(horizontal: 10.w), child: GestureDetector( onTap: () => bloc.add(SelectItemEvent(index)), child: Container( padding: const EdgeInsets.all(4.5), decoration: BoxDecoration( color: bloc.selectItem == index ? const Color(0xFF00B6F1) : Colors.white, borderRadius: BorderRadius.circular(15), ), height: 143.h, width: 143.w, child: Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(15), border: Border.all( width: 1.0, color: const Color(0xFF140C10)), image: DecorationImage( fit: BoxFit.fitWidth, image: NetworkImage(answerLis?.picUrl ?? ''))), ), ), ), ); }); ///看题选字 Widget _pageViewWordItemWidget(CourseProcessTopics? topics) => BlocBuilder( builder: (context, state) { return SafeArea( child: Column( children: [ Text(topics?.word ?? '', softWrap: true, style: TextStyle( fontSize: 21.sp, color: const Color(0xFF333333))), 26.verticalSpace, SizedBox( height: 143.h, width: 143.w * (topics?.topicAnswerList?.length ?? 0), child: ListView.builder( scrollDirection: Axis.horizontal, itemCount: topics?.topicAnswerList?.length ?? 0, physics: const NeverScrollableScrollPhysics(), itemBuilder: (context, index) { return _decodeWordWidget( index, topics?.topicAnswerList?[index]); }), ), ], ), ); }); Widget _decodeWordWidget( int index, CourseProcessTopicsTopicAnswerList? answerLis) => BlocBuilder( buildWhen: (_, s) => s is SelectItemChangeState, builder: (context, state) { final bloc = BlocProvider.of(context); return Container( padding: EdgeInsets.symmetric(horizontal: 10.w), child: GestureDetector( onTap: () => bloc.add(SelectItemEvent(index)), child: Container( width: 143.w, height: 143.h, padding: EdgeInsets.only( left: 13.w, right: 13.w, top: 13.h, bottom: 13.h), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(15), border: Border.all(width: 1.0, color: const Color(0xFF140C10)), ), child: Column( mainAxisAlignment: MainAxisAlignment.end, children: [ Expanded( child: Container( alignment: Alignment.center, child: Text(answerLis?.word ?? '', style: TextStyle( fontSize: 20.sp, color: const Color(0xFF333333))), ), ), Container( height: 30.h, width: double.infinity, decoration: BoxDecoration( color: bloc.selectItem == index ? const Color(0xFF00B6F1) : Colors.white, borderRadius: BorderRadius.circular(15.r), border: Border.all( width: 1.5, color: const Color(0xFF140C10)), ), alignment: Alignment.center, child: Image.asset('choose'.assetPng), ) ], ), ), ), ); }); ///听音选图 Widget _pageViewVoicePictureItemWidget(CourseProcessTopics? topics) => BlocBuilder( builder: (context, state) { final bloc = BlocProvider.of(context); return SafeArea( child: Column( children: [ Row( mainAxisAlignment: MainAxisAlignment.center, children: [ GestureDetector( onTap: () { bloc.add(VoicePlayEvent()); }, child: Image.asset( bloc.voicePlayState == VoicePlayState.playing ? 'reade_answer'.assetGif : 'voice'.assetPng, height: 33.h, width: 30.w, ), ), 10.horizontalSpace, Text(topics?.word ?? '', style: TextStyle( fontSize: 20.sp, color: const Color(0xFF333333))) ], ), 26.verticalSpace, SizedBox( height: 143.h, width: 203.w * (topics?.topicAnswerList?.length ?? 0), child: ListView.builder( scrollDirection: Axis.horizontal, physics: const NeverScrollableScrollPhysics(), itemCount: topics?.topicAnswerList?.length ?? 0, itemBuilder: (BuildContext context, int index) { return _decodeVoiceImageWidget( index, topics?.topicAnswerList?[index]); }), ) ], ), ); }); Widget _decodeVoiceImageWidget( int index, CourseProcessTopicsTopicAnswerList? answerList) => BlocBuilder( buildWhen: (_, s) => s is SelectItemChangeState, builder: (context, state) { final bloc = BlocProvider.of(context); return Container( padding: EdgeInsets.symmetric(horizontal: 20.w), child: GestureDetector( onTap: () => bloc.add(SelectItemEvent(index)), child: Container( padding: const EdgeInsets.all(4.5), decoration: BoxDecoration( color: bloc.selectItem == index ? const Color(0xFF00B6F1) : Colors.white, borderRadius: BorderRadius.circular(15), ), height: 143.h, width: 163.w, child: Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(15), image: DecorationImage( fit: BoxFit.fill, image: NetworkImage(answerList?.picUrl ?? ''))), ), ), ), ); }); ///听音选字 Widget _pageViewVoiceWordItemWidget(CourseProcessTopics? topics) => BlocBuilder( builder: (context, state) { final bloc = BlocProvider.of(context); return SafeArea( child: Column( children: [ GestureDetector( onTap: () { bloc.add(VoicePlayEvent()); }, child: Image.asset( bloc.voicePlayState == VoicePlayState.playing ? 'reade_answer'.assetGif : 'voice'.assetPng, height: 33.h, width: 30.w)), 26.verticalSpace, SizedBox( width: 163.w * (topics?.topicAnswerList?.length ?? 0), height: 143.h, child: ListView.builder( scrollDirection: Axis.horizontal, itemCount: topics?.topicAnswerList?.length, physics: const NeverScrollableScrollPhysics(), itemBuilder: (BuildContext context, int index) { return _decodeVoiceWordImageWidget( index, topics!.topicAnswerList![index]); }), ), ], ), ); }); Widget _decodeVoiceWordImageWidget( int index, CourseProcessTopicsTopicAnswerList answerList) => BlocBuilder( buildWhen: (_, s) => s is SelectItemChangeState, builder: (context, state) { final bloc = BlocProvider.of(context); return GestureDetector( onTap: () => bloc.add(SelectItemEvent(index)), child: Container( width: 163.w, height: 143.h, padding: EdgeInsets.symmetric(horizontal: 10.w), child: Container( width: 143.w, height: 143.h, padding: EdgeInsets.only( left: 13.w, right: 13.w, top: 13.h, bottom: 13.h), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(15), border: Border.all(width: 1.0, color: const Color(0xFF140C10)), ), child: Column( mainAxisAlignment: MainAxisAlignment.end, children: [ Expanded( child: Container( alignment: Alignment.center, child: Text(answerList.word ?? '', style: TextStyle( fontSize: 20.sp, color: const Color(0xFF333333))), ), ), Container( height: 30.h, width: double.infinity, decoration: BoxDecoration( color: bloc.selectItem == index ? const Color(0xFF00B6F1) : Colors.white, borderRadius: BorderRadius.circular(15.r), border: Border.all( width: 1.5, color: const Color(0xFF140C10)), ), alignment: Alignment.center, child: Image.asset('choose'.assetPng), ) ], ), ), ), ); }); ///语音问答 Widget _voiceAnswerItem(CourseProcessTopics? topics) => BlocBuilder( builder: (context, state) { final bloc = BlocProvider.of(context); return Row( mainAxisAlignment: MainAxisAlignment.center, children: [ ClipRRect( borderRadius: BorderRadius.circular(20), child: Container( color: Colors.white, child: OwImageWidget( name: topics?.picUrl ?? '', height: 186.h, width: 186.w, ), ), ), 120.horizontalSpace, Column( mainAxisAlignment: MainAxisAlignment.center, children: [ GestureDetector( onTap: () { if (bloc.isVoicing) { showToast('正在录音,不能终止'); return; } bloc.add(VoicePlayEvent()); }, child: Row( children: [ Image.asset( bloc.voicePlayState == VoicePlayState.playing ? 'reade_answer'.assetGif : 'voice'.assetPng, height: 45.h, width: 45.w, ), 10.horizontalSpace, Text(topics?.word ?? '') ], ), ), 70.verticalSpace, ThrottledGestureDetector( throttleTime: 1000, onTap: () { if (bloc.voicePlayState == VoicePlayState.playing) { showToast('正在播放音频,不能终止'); return; } if (bloc.isVoicing) { bloc.add(XSVoiceStopEvent()); return; } if (topics?.type == TopicType.voiceQuestion.value || topics?.type == TopicType.voiceWord.value) { bloc.add(XSVoiceStartEvent(topics?.keyWord ?? '', '0', UserUtil.getUser()!.id.toString())); } else { bloc.add(XSVoiceStartEvent(topics?.word ?? '', '0', UserUtil.getUser()!.id.toString())); } }, child: Image.asset( bloc.isVoicing ? 'micro_phone'.assetGif : 'micro_phone'.assetPng, height: 46.h, width: 46.w, ), ) ], ) ], ); }); }