Commit 9d080046d04cf46c1d3c8429f72e0c760893b5c1

Authored by liangchengyou
1 parent d1d32220

feat:视频跟读逻辑

assets/images/gendubeij.png 0 → 100644

48.7 KB

assets/images/gendubeij_mengban.png 0 → 100644

23.5 KB

assets/images/star_dark.png 0 → 100644

2.88 KB

assets/images/star_light.png 0 → 100644

2.08 KB

lib/home/home_page.dart
@@ -25,7 +25,7 @@ class HomePage extends StatelessWidget { @@ -25,7 +25,7 @@ class HomePage extends StatelessWidget {
25 class _HomePageView extends StatelessWidget { 25 class _HomePageView extends StatelessWidget {
26 void _headerActionEvent(HeaderActionType type) { 26 void _headerActionEvent(HeaderActionType type) {
27 if (type == HeaderActionType.video) { 27 if (type == HeaderActionType.video) {
28 - 28 + Navigator.of(AppRouter.context).pushNamed(AppRouteName.reAfter);
29 } else if (type == HeaderActionType.phase) { 29 } else if (type == HeaderActionType.phase) {
30 Navigator.of(AppRouter.context).pushNamed(AppRouteName.lesson); 30 Navigator.of(AppRouter.context).pushNamed(AppRouteName.lesson);
31 } else if (type == HeaderActionType.listen) { 31 } else if (type == HeaderActionType.listen) {
lib/repeatafter/bloc/repeat_after_bloc.dart 0 → 100644
  1 +import 'package:flutter/cupertino.dart';
  2 +import 'package:flutter_bloc/flutter_bloc.dart';
  3 +import 'package:flutter_easyloading/flutter_easyloading.dart';
  4 +
  5 +part 'repeat_after_event.dart';
  6 +part 'repeat_after_state.dart';
  7 +
  8 +class RepeatAfterBloc extends Bloc<RepeatAfterEvent, RepeatAfterState> {
  9 + RepeatAfterBloc() : super(RepeatAfterInitial()) {
  10 + on<RepeatAfterEvent>((event, emit) {
  11 + // TODO: implement event handler
  12 + });
  13 + }
  14 +
  15 +
  16 + Future<void> requestData() async {
  17 + EasyLoading.show();
  18 + Future.delayed(const Duration(milliseconds: 2000),(){
  19 + EasyLoading.dismiss();
  20 + emit(RequestDataState());
  21 + });
  22 + }
  23 +}
lib/repeatafter/bloc/repeat_after_event.dart 0 → 100644
  1 +part of 'repeat_after_bloc.dart';
  2 +
  3 +@immutable
  4 +abstract class RepeatAfterEvent {}
lib/repeatafter/bloc/repeat_after_state.dart 0 → 100644
  1 +part of 'repeat_after_bloc.dart';
  2 +
  3 +@immutable
  4 +abstract class RepeatAfterState {}
  5 +
  6 +class RepeatAfterInitial extends RepeatAfterState {}
  7 +
  8 +class RequestDataState extends RepeatAfterState {}
lib/repeatafter/repeat_after_page.dart 0 → 100644
  1 +import 'dart:math';
  2 +
  3 +import 'package:flutter/material.dart';
  4 +import 'package:flutter_bloc/flutter_bloc.dart';
  5 +import 'package:flutter_easyloading/flutter_easyloading.dart';
  6 +import 'package:wow_english/common/widgets/we_app_bar.dart';
  7 +import 'package:wow_english/repeatafter/widgets/repeat_after_item.dart';
  8 +
  9 +import 'bloc/repeat_after_bloc.dart';
  10 +
  11 +class RepeatAfterPage extends StatelessWidget {
  12 + const RepeatAfterPage({super.key});
  13 +
  14 + @override
  15 + Widget build(BuildContext context) {
  16 + return BlocProvider(
  17 + create: (context) => RepeatAfterBloc()..requestData(),
  18 + child: _RepeatAfterPageView(),
  19 + );
  20 + }
  21 +}
  22 +
  23 +class _RepeatAfterPageView extends StatelessWidget {
  24 + @override
  25 + Widget build(BuildContext context) {
  26 + return BlocListener<RepeatAfterBloc, RepeatAfterState>(
  27 + listener: (context, state) {
  28 + if (state is RequestDataState) {
  29 + EasyLoading.showToast('网络请求结束');
  30 + }
  31 + },
  32 + child: _repeatAfterView(),
  33 + );
  34 + }
  35 +
  36 + Widget _repeatAfterView() => BlocBuilder<RepeatAfterBloc, RepeatAfterState>(
  37 + builder: (context, state) {
  38 + return Scaffold(
  39 + appBar: const WEAppBar(
  40 + titleText: '视频跟读',
  41 + centerTitle: false,
  42 + ),
  43 + body: SafeArea(
  44 + child: Container(
  45 + alignment: Alignment.center,
  46 + child: ListView.builder(
  47 + itemCount: 10,
  48 + scrollDirection: Axis.horizontal,
  49 + itemBuilder: (BuildContext context,int index){
  50 + bool unLock = index%3==0;
  51 + return RepeatAfterItem(
  52 + unLock: unLock,
  53 + tapEvent: () {
  54 +
  55 + },
  56 + starNumber: !unLock?0:Random().nextInt(5)
  57 + );
  58 + }),
  59 + ),
  60 + ),
  61 + );
  62 + },
  63 + );
  64 +}
  65 +
lib/repeatafter/widgets/repeat_after_item.dart 0 → 100644
  1 +import 'package:flutter/material.dart';
  2 +import 'package:flutter_screenutil/flutter_screenutil.dart';
  3 +import 'package:wow_english/common/extension/string_extension.dart';
  4 +
  5 +class RepeatAfterItem extends StatelessWidget {
  6 + const RepeatAfterItem({super.key, required this.starNumber, required this.unLock, required this.tapEvent});
  7 + //分数
  8 + final int starNumber;
  9 + //是否解锁
  10 + final bool unLock;
  11 +
  12 + final Function() tapEvent;
  13 +
  14 + @override
  15 + Widget build(BuildContext context) {
  16 + return Padding(
  17 + padding: EdgeInsets.symmetric(
  18 + horizontal: 10.w
  19 + ),
  20 + child: GestureDetector(
  21 + onTap: (){
  22 + if(unLock) {
  23 + tapEvent();
  24 + }
  25 + },
  26 + child: Stack(
  27 + children: [
  28 + _modelInfoWidget(context),
  29 + _lockWidget()
  30 + ],
  31 + ),
  32 + ),
  33 + );
  34 + }
  35 +
  36 + Widget _modelInfoWidget(BuildContext context) {
  37 + return Container(
  38 + width: 162.w,
  39 + height: 235.h,
  40 + decoration: BoxDecoration(
  41 + image: DecorationImage(
  42 + image: AssetImage(
  43 + 'gendubeij'.assetPng
  44 + ),
  45 + fit: BoxFit.fill
  46 + )
  47 + ),
  48 + padding: EdgeInsets.symmetric(horizontal: 11.w,vertical: 13.h),
  49 + alignment: Alignment.center,
  50 + child: Column(
  51 + mainAxisAlignment: MainAxisAlignment.spaceBetween,
  52 + children: [
  53 + Image.network(
  54 + 'https://img.liblibai.com/web/648331d033b41.png?image_process=format,webp&x-oss-process=image/resize,w_2980,m_lfit/format,webp',
  55 + height: 100.h,
  56 + width: 140.w,
  57 + fit: BoxFit.fitWidth,
  58 + ),
  59 + Row(
  60 + mainAxisAlignment: MainAxisAlignment.spaceBetween,
  61 + children: [
  62 + Image.asset(
  63 + starNumber >= 1 ? 'star_light'.assetPng:'star_dark'.assetPng,
  64 + width: 23.w,
  65 + height: 21.h,
  66 + ),
  67 + Image.asset(
  68 + starNumber >= 2 ? 'star_light'.assetPng:'star_dark'.assetPng,
  69 + width: 23.w,
  70 + height: 21.h,
  71 + ),
  72 + Image.asset(
  73 + starNumber >= 3 ? 'star_light'.assetPng:'star_dark'.assetPng,
  74 + width: 23.w,
  75 + height: 21.h,
  76 + ),
  77 + Image.asset(
  78 + starNumber >= 4 ? 'star_light'.assetPng:'star_dark'.assetPng,
  79 + width: 23.w,
  80 + height: 21.h,
  81 + ),
  82 + Image.asset(
  83 + starNumber >= 5 ? 'star_light'.assetPng:'star_dark'.assetPng,
  84 + width: 23.w,
  85 + height: 21.h,
  86 + ),
  87 + ],
  88 + ),
  89 + Container(
  90 + height: 35.h,
  91 + width: double.infinity,
  92 + decoration: BoxDecoration(
  93 + color: const Color(0xFFFFCC00),
  94 + borderRadius: BorderRadius.circular(5.r),
  95 + border: Border.all(
  96 + width: 1.0,
  97 + color: const Color(0xFF333333),
  98 + ),
  99 + ),
  100 + alignment: Alignment.center,
  101 + child: Text(
  102 + 'video title',
  103 + style: TextStyle(
  104 + fontSize: 16.sp,
  105 + color: const Color(0xFF333333)
  106 + ),
  107 + ),
  108 + )
  109 + ],
  110 + ),
  111 + );
  112 + }
  113 +
  114 + Widget _lockWidget() {
  115 + return Offstage(
  116 + offstage: unLock,
  117 + child: Container(
  118 + width: 162.w,
  119 + height: 235.h,
  120 + decoration: BoxDecoration(
  121 + image: DecorationImage(
  122 + image: AssetImage(
  123 + 'gendubeij_mengban'.assetPng
  124 + ),
  125 + fit: BoxFit.fill
  126 + )
  127 + ),
  128 + alignment: Alignment.center,
  129 + child: Image.asset(
  130 + 'listen_lock'.assetPng,
  131 + height: 36.h,
  132 + width: 41.w,
  133 + ),
  134 + ),
  135 + );
  136 + }
  137 +}
0 \ No newline at end of file 138 \ No newline at end of file
lib/route/route.dart
@@ -8,6 +8,7 @@ import &#39;package:wow_english/listen/listen_page.dart&#39;; @@ -8,6 +8,7 @@ import &#39;package:wow_english/listen/listen_page.dart&#39;;
8 import 'package:wow_english/login/forgetpwd/forget_password_home_page.dart'; 8 import 'package:wow_english/login/forgetpwd/forget_password_home_page.dart';
9 import 'package:wow_english/login/loginpage/login_page.dart'; 9 import 'package:wow_english/login/loginpage/login_page.dart';
10 import 'package:wow_english/login/setpwd/set_pwd_page.dart'; 10 import 'package:wow_english/login/setpwd/set_pwd_page.dart';
  11 +import 'package:wow_english/repeatafter/repeat_after_page.dart';
11 import 'package:wow_english/shop/exchane/exchange_lesson_page.dart'; 12 import 'package:wow_english/shop/exchane/exchange_lesson_page.dart';
12 import 'package:wow_english/shop/exchangelist/exchange_lesson_list_page.dart'; 13 import 'package:wow_english/shop/exchangelist/exchange_lesson_list_page.dart';
13 import 'package:wow_english/shop/home/shop_home_page.dart'; 14 import 'package:wow_english/shop/home/shop_home_page.dart';
@@ -26,6 +27,7 @@ class AppRouteName { @@ -26,6 +27,7 @@ class AppRouteName {
26 static const String shop = 'shop'; 27 static const String shop = 'shop';
27 static const String exLesson = 'exLesson'; 28 static const String exLesson = 'exLesson';
28 static const String exList = 'exList'; 29 static const String exList = 'exList';
  30 + static const String reAfter = 'reAfter';
29 static const String tab = '/'; 31 static const String tab = '/';
30 } 32 }
31 33
@@ -58,6 +60,8 @@ class AppRouter { @@ -58,6 +60,8 @@ class AppRouter {
58 return CupertinoPageRoute(builder: (_) => const ExchangeLessonPage()); 60 return CupertinoPageRoute(builder: (_) => const ExchangeLessonPage());
59 case AppRouteName.exList: 61 case AppRouteName.exList:
60 return CupertinoPageRoute(builder: (_) => const ExchangeLessonListPage()); 62 return CupertinoPageRoute(builder: (_) => const ExchangeLessonListPage());
  63 + case AppRouteName.reAfter:
  64 + return CupertinoPageRoute(builder: (_) => const RepeatAfterPage());
61 case AppRouteName.setPwd: 65 case AppRouteName.setPwd:
62 final phoneNum = (settings.arguments as Map)['phoneNumber'] as String; 66 final phoneNum = (settings.arguments as Map)['phoneNumber'] as String;
63 return CupertinoPageRoute(builder: (_) => SetPassWordPage(phoneNum: phoneNum)); 67 return CupertinoPageRoute(builder: (_) => SetPassWordPage(phoneNum: phoneNum));