Commit d35a4e8794ec9bdbbbbbe6092105a53615731422

Authored by liangchengyou
1 parent 60e47f7c

feat:磨耳朵功能UI

assets/images/back_around.png 0 → 100644

17.2 KB

assets/images/blue-positive.png 0 → 100644

22.6 KB

assets/images/listen_lock.png 0 → 100644

3.79 KB

lib/app/splash_page.dart
... ... @@ -29,7 +29,7 @@ class _TransitionViewState extends State<TransitionView> {
29 29 Future startTime() async {
30 30 Timer(const Duration(seconds: 2),() {
31 31 if(BasicConfigurationManager().sessionId!.isNotEmpty) {
32   - Navigator.of(context).pushNamedAndRemoveUntil(AppRouteName.tab, (route) => false);
  32 + Navigator.of(context).pushNamedAndRemoveUntil(AppRouteName.home, (route) => false);
33 33 } else {
34 34 Navigator.of(context).pushNamedAndRemoveUntil(AppRouteName.login,(route) => false);
35 35 }
... ...
lib/common/widgets/we_app_bar.dart
... ... @@ -31,9 +31,9 @@ class WEAppBar extends StatelessWidget implements PreferredSizeWidget {
31 31 child: Container(
32 32 alignment: Alignment.center,
33 33 child: Image.asset(
34   - 'back'.assetPng,
35   - height: 43,
36   - width: 43,
  34 + 'back_around'.assetPng,
  35 + height: 40,
  36 + width: 40,
37 37 ),
38 38 ),
39 39 ),
... ...
lib/home/bloc/home_bloc.dart
1   -import 'dart:async';
2   -
3   -import 'package:bloc/bloc.dart';
4   -import 'package:meta/meta.dart';
  1 +import 'package:flutter/cupertino.dart';
  2 +import 'package:flutter_bloc/flutter_bloc.dart';
5 3  
6 4 part 'home_event.dart';
7 5 part 'home_state.dart';
8 6  
9 7 class HomeBloc extends Bloc<HomeEvent, HomeState> {
10   - HomeBloc() : super(HomeInitial()) {
  8 + final PageController pageController;
  9 + HomeBloc(this.pageController) : super(HomeInitial()) {
11 10 on<HomeEvent>((event, emit) {
12 11 // TODO: implement event handler
13 12 });
... ...
lib/home/home_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 +import 'package:flutter_screenutil/flutter_screenutil.dart';
  5 +import 'package:wow_english/common/extension/string_extension.dart';
3 6 import 'package:wow_english/home/bloc/home_bloc.dart';
  7 +import 'package:wow_english/home/widgets/home_lesson_item_widget.dart';
4 8 import 'package:wow_english/home/widgets/home_tab_header_widget.dart';
5 9 import 'package:wow_english/route/route.dart';
6 10  
... ... @@ -10,7 +14,9 @@ class HomePage extends StatelessWidget {
10 14 @override
11 15 Widget build(BuildContext context) {
12 16 return BlocProvider(
13   - create: (context) => HomeBloc(),
  17 + create: (context) => HomeBloc(PageController(
  18 + initialPage: 0,
  19 + )),
14 20 child: _HomePageView(),
15 21 );
16 22 }
... ... @@ -23,7 +29,9 @@ class _HomePageView extends StatelessWidget {
23 29 } else if (type == HeaderActionType.phase) {
24 30 Navigator.of(AppRouter.context).pushNamed(AppRouteName.lesson);
25 31 } else if (type == HeaderActionType.listen) {
26   -
  32 + Navigator.of(AppRouter.context).pushNamed(AppRouteName.listen);
  33 + } else if (type == HeaderActionType.shop) {
  34 +
27 35 } else {
28 36  
29 37 }
... ... @@ -33,22 +41,78 @@ class _HomePageView extends StatelessWidget {
33 41 Widget build(BuildContext context) {
34 42 return BlocListener<HomeBloc,HomeState>(
35 43 listener: (context, state){},
36   - child: Scaffold(
37   - body: Container(
38   - color: Colors.white,
39   - child: Center(
40   - child: Column(
41   - children: [
42   - HomeTabHeaderWidget(
43   - actionTap: (HeaderActionType type) {
44   - _headerActionEvent(type);
45   - },
46   - ),
47   - ],
48   - ),
49   - ),
50   - ),
51   - ),
  44 + child: _homeView(),
52 45 );
53 46 }
  47 +
  48 + Widget _homeView() => BlocBuilder<HomeBloc,HomeState>(
  49 + builder: (context, state){
  50 + final bloc = BlocProvider.of<HomeBloc>(context);
  51 + return Scaffold(
  52 + body: Container(
  53 + color: Colors.white,
  54 + child: Center(
  55 + child: Column(
  56 + mainAxisAlignment: MainAxisAlignment.spaceBetween,
  57 + children: [
  58 + HomeTabHeaderWidget(
  59 + actionTap: (HeaderActionType type) {
  60 + _headerActionEvent(type);
  61 + },
  62 + ),
  63 + Expanded(
  64 + child: PageView.builder(
  65 + itemCount: 10,
  66 + controller: bloc.pageController,
  67 + pageSnapping: false,
  68 + onPageChanged: (int index) {
  69 + EasyLoading.showToast(index.toString());
  70 + },
  71 + itemBuilder: (BuildContext context,int index){
  72 + return const HomeLessonItem();
  73 + // return Container(
  74 + // color:index%2==0?Colors.red:Colors.blue
  75 + // );
  76 + })
  77 + ,
  78 + ),
  79 + SafeArea(
  80 + child: Padding(
  81 + padding: EdgeInsets.symmetric(horizontal: 13.w),
  82 + child: Row(
  83 + mainAxisAlignment: MainAxisAlignment.spaceBetween,
  84 + children: [
  85 + SizedBox(
  86 + height: 47.h,
  87 + width: 80.w,
  88 + ),
  89 + Container(
  90 + decoration: BoxDecoration(
  91 + color: Colors.blue,
  92 + borderRadius: BorderRadius.circular(14.5.r),
  93 + ),
  94 + padding: EdgeInsets.symmetric(vertical: 8.h,horizontal: 24.w),
  95 + child: Text(
  96 + '3/67',
  97 + style: TextStyle(
  98 + color: Colors.white,
  99 + fontSize: 12.sp
  100 + ),
  101 + ),
  102 + ),
  103 + Image.asset(
  104 + 'blue-positive'.assetPng,
  105 + height: 47.h,
  106 + width: 80.w,
  107 + ),
  108 + ],
  109 + ),
  110 + ),
  111 + )
  112 + ],
  113 + ),
  114 + ),
  115 + ),
  116 + );
  117 + });
54 118 }
55 119 \ No newline at end of file
... ...
lib/home/widgets/home_lesson_item_widget.dart 0 → 100644
  1 +import 'package:flutter/material.dart';
  2 +import 'package:flutter_screenutil/flutter_screenutil.dart';
  3 +
  4 +class HomeLessonItem extends StatelessWidget {
  5 + const HomeLessonItem({super.key});
  6 +
  7 + @override
  8 + Widget build(BuildContext context) {
  9 + return SizedBox(
  10 + width: double.infinity,
  11 + child: ListView.builder(
  12 + itemCount: 5,
  13 + scrollDirection: Axis.horizontal,
  14 + physics: const NeverScrollableScrollPhysics(),
  15 + itemBuilder: (BuildContext context,int index){
  16 + return Padding(
  17 + padding: EdgeInsets.symmetric(horizontal: 4.w),
  18 + child: Image.network(
  19 + 'https://img.liblibai.com/web/648331d5a2cb5.png?image_process=format,webp&x-oss-process=image/resize,w_2980,m_lfit/format,webp',
  20 + ),
  21 + );
  22 + }),
  23 + );
  24 + }
  25 +}
0 26 \ No newline at end of file
... ...
lib/home/widgets/home_tab_header_widget.dart
... ... @@ -11,6 +11,8 @@ enum HeaderActionType {
11 11 listen,
12 12 //购买
13 13 shop,
  14 + //个人信息
  15 + userinfo
14 16 }
15 17  
16 18 class HomeTabHeaderWidget extends StatelessWidget {
... ... @@ -29,20 +31,54 @@ class HomeTabHeaderWidget extends StatelessWidget {
29 31 child: Row(
30 32 children: [
31 33 ScreenUtil().bottomBarHeight.horizontalSpace,
32   - ClipRRect(
33   - borderRadius:BorderRadius.circular(21),
34   - child: Image.network(
35   - 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fsafe-img.xhscdn.com%2Fbw1%2Faa1c2213-820a-4223-8757-5f8cee318a28%3FimageView2%2F2%2Fw%2F1080%2Fformat%2Fjpg&refer=http%3A%2F%2Fsafe-img.xhscdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1688713226&t=192b18a613683bcdc5bd76f65c9ff032',
36   - height: 42,
37   - width: 42,
38   - fit: BoxFit.fill,
  34 + GestureDetector(
  35 + onTap: () {
  36 + if(actionTap != null) {
  37 + actionTap!(HeaderActionType.userinfo);
  38 + }
  39 + },
  40 + child: Container(
  41 + decoration: BoxDecoration(
  42 + border: Border.all(
  43 + width: 1.0,
  44 + color: const Color(0xFF140C10),
  45 + ),
  46 + borderRadius: BorderRadius.circular(21),
  47 + ),
  48 + child: const CircleAvatar(
  49 + radius: 21,
  50 + backgroundImage: NetworkImage(
  51 + 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fsafe-img.xhscdn.com%2Fbw1%2Faa1c2213-820a-4223-8757-5f8cee318a28%3FimageView2%2F2%2Fw%2F1080%2Fformat%2Fjpg&refer=http%3A%2F%2Fsafe-img.xhscdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1688713226&t=192b18a613683bcdc5bd76f65c9ff032'
  52 + ),
  53 + ),
39 54 ),
40 55 ),
41   - Container(
42   - color: Colors.white,
43   - margin: const EdgeInsets.only(left: 7),
44   - padding: const EdgeInsets.all(7.0),
45   - child: const Text('franky'),
  56 + GestureDetector(
  57 + onTap: () {
  58 + if(actionTap != null) {
  59 + actionTap!(HeaderActionType.userinfo);
  60 + }
  61 + },
  62 + child: Container(
  63 + margin: const EdgeInsets.only(left: 7),
  64 + padding: const EdgeInsets.all(4.0),
  65 + decoration: BoxDecoration(
  66 + color: Colors.white,
  67 + borderRadius: BorderRadius.circular(2),
  68 + border: Border.all(
  69 + width: 1.0,
  70 + color: const Color(0xFF140C10),
  71 + style: BorderStyle.solid
  72 + ),
  73 + ),
  74 + child: const Text(
  75 + 'franky',
  76 + style: TextStyle(
  77 + color: Color(0xFF333333),
  78 + fontSize: 16
  79 + ),
  80 + ),
  81 + ),
46 82 ),
47 83 20.horizontalSpace,
48 84 const Expanded(
... ...
lib/lessons/lesson_page.dart
... ... @@ -41,6 +41,16 @@ class _LessonPageView extends StatelessWidget {
41 41 listener: (context, state){},
42 42 child: Scaffold(
43 43 appBar: WEAppBar(
  44 + leading: IconButton(
  45 + onPressed: (){
  46 + Navigator.pop(context);
  47 + },
  48 + icon: Image.asset(
  49 + 'back'.assetPng,
  50 + height: 43,
  51 + width: 43,
  52 + )
  53 + ),
44 54 actions: <Widget>[
45 55 IconButton(
46 56 icon: Image.asset('shop'.assetPng),
... ...
lib/listen/bloc/listen_bloc.dart 0 → 100644
  1 +import 'dart:async';
  2 +
  3 +import 'package:bloc/bloc.dart';
  4 +import 'package:meta/meta.dart';
  5 +
  6 +part 'listen_event.dart';
  7 +part 'listen_state.dart';
  8 +
  9 +class ListenBloc extends Bloc<ListenEvent, ListenState> {
  10 + ListenBloc() : super(ListenInitial()) {
  11 + on<ListenEvent>((event, emit) {
  12 + // TODO: implement event handler
  13 + });
  14 + }
  15 +}
... ...
lib/listen/bloc/listen_event.dart 0 → 100644
  1 +part of 'listen_bloc.dart';
  2 +
  3 +@immutable
  4 +abstract class ListenEvent {}
... ...
lib/listen/bloc/listen_state.dart 0 → 100644
  1 +part of 'listen_bloc.dart';
  2 +
  3 +@immutable
  4 +abstract class ListenState {}
  5 +
  6 +class ListenInitial extends ListenState {}
... ...
lib/listen/listen_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/widgets/we_app_bar.dart';
  5 +import 'package:wow_english/listen/bloc/listen_bloc.dart';
  6 +import 'package:wow_english/listen/widgets/listen_item_widget.dart';
  7 +
  8 +class ListenPage extends StatelessWidget {
  9 + const ListenPage({super.key});
  10 +
  11 + @override
  12 + Widget build(BuildContext context) {
  13 + return BlocProvider(
  14 + create: (context) => ListenBloc(),
  15 + child: _ListenPageView(),
  16 + );
  17 + }
  18 +}
  19 +
  20 +class _ListenPageView extends StatelessWidget {
  21 + @override
  22 + Widget build(BuildContext context) {
  23 + return BlocListener<ListenBloc, ListenState>(
  24 + listener: (context, state) {
  25 +
  26 + },
  27 + child: Scaffold(
  28 + appBar: const WEAppBar(
  29 + titleText: '磨耳朵',
  30 + centerTitle: false,
  31 + ),
  32 + body: _listenView(),
  33 + ),
  34 + );
  35 + }
  36 +
  37 + Widget _listenView() => BlocBuilder<ListenBloc, ListenState>(
  38 + builder: (context, state) {
  39 + return ListView.builder(
  40 + itemCount: 10,
  41 + scrollDirection: Axis.horizontal,
  42 + padding: EdgeInsets.symmetric(horizontal: 30.w,vertical: 36.h),
  43 + itemBuilder: (BuildContext context,int index){
  44 + return ListenItemWidget(
  45 + isLock: (index < 5),
  46 + clickEvent: (){
  47 +
  48 + });
  49 + });
  50 + });
  51 +}
0 52 \ No newline at end of file
... ...
lib/listen/widgets/listen_item_widget.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 ListenItemWidget extends StatelessWidget {
  6 + const ListenItemWidget({super.key, this.isLock = false, required this.clickEvent});
  7 +
  8 + final Function() clickEvent;
  9 +
  10 + final bool isLock;
  11 +
  12 + @override
  13 + Widget build(BuildContext context) {
  14 + return Padding(
  15 + padding: EdgeInsets.symmetric(horizontal: 8.5.w),
  16 + child: Column(
  17 + children: [
  18 + GestureDetector(
  19 + onTap: () {
  20 + if (!isLock) {
  21 + clickEvent();
  22 + }
  23 + },
  24 + child: ClipRRect(
  25 + borderRadius:BorderRadius.circular(90),
  26 + child: Stack(
  27 + alignment:Alignment.center,
  28 + children: [
  29 + Image.network(
  30 + 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fsafe-img.xhscdn.com%2Fbw1%2Faa1c2213-820a-4223-8757-5f8cee318a28%3FimageView2%2F2%2Fw%2F1080%2Fformat%2Fjpg&refer=http%3A%2F%2Fsafe-img.xhscdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1688713226&t=192b18a613683bcdc5bd76f65c9ff032',
  31 + height: 180,
  32 + width: 180,
  33 + fit: BoxFit.fill,
  34 + ),
  35 + Offstage(
  36 + offstage: isLock??false,
  37 + child: Container(
  38 + height: 180,
  39 + width: 180,
  40 + color: const Color.fromRGBO(1, 1, 0, 0.5),
  41 + ),
  42 + ),
  43 + Offstage(
  44 + offstage: isLock,
  45 + child: Image.asset(
  46 + 'listen_lock'.assetPng,
  47 + height: 36,
  48 + width: 41,
  49 + ),
  50 + )
  51 + ],
  52 + ),
  53 + ),
  54 + ),
  55 + 23.verticalSpace,
  56 + Container(
  57 + height: 40.h,
  58 + padding: const EdgeInsets.symmetric(horizontal: 22),
  59 + decoration: BoxDecoration(
  60 + color: const Color(0xFFFFCC00),
  61 + borderRadius: BorderRadius.circular(20.r),
  62 + border: Border.all(
  63 + width: 1.0,
  64 + color: const Color(0xFF333333),
  65 + ),
  66 + ),
  67 + alignment: Alignment.center,
  68 + child: Text(
  69 + 'listen title',
  70 + style: TextStyle(
  71 + fontSize: 15.sp
  72 + ),
  73 + ),
  74 + )
  75 + ],
  76 + ),
  77 + );
  78 + }
  79 +}
0 80 \ No newline at end of file
... ...
lib/pages/page1.dart deleted
1   -import 'package:flutter/material.dart';
2   -import 'package:wow_english/common/widgets/we_app_bar.dart';
3   -
4   -class Page1 extends StatelessWidget {
5   - const Page1({super.key});
6   -
7   - @override
8   - Widget build(BuildContext context) {
9   - return const Scaffold(
10   - appBar: WEAppBar(
11   - titleText: '页面1',
12   - ),
13   - body:Center(
14   - child: Text('页面1'),
15   - ),
16   - );
17   - }
18   -}
19 0 \ No newline at end of file
lib/pages/page2.dart deleted
1   -import 'package:flutter/material.dart';
2   -import 'package:wow_english/common/widgets/we_app_bar.dart';
3   -
4   -class Page2 extends StatelessWidget {
5   - const Page2({super.key});
6   -
7   - @override
8   - Widget build(BuildContext context) {
9   - return const Scaffold(
10   - appBar: WEAppBar(
11   - titleText: '页面2',
12   - ),
13   - body:Center(
14   - child: Text('页面2'),
15   - ),
16   - );
17   - }
18   -}
19 0 \ No newline at end of file
lib/route/route.dart
... ... @@ -4,6 +4,7 @@ import &#39;package:wow_english/app/splash_page.dart&#39;;
4 4 import 'package:wow_english/common/pages/wow_web_page.dart';
5 5 import 'package:wow_english/home/home_page.dart';
6 6 import 'package:wow_english/lessons/lesson_page.dart';
  7 +import 'package:wow_english/listen/listen_page.dart';
7 8 import 'package:wow_english/login/forgetpwd/forget_password_home_page.dart';
8 9 import 'package:wow_english/login/loginpage/login_page.dart';
9 10 import 'package:wow_english/login/setpwd/set_pwd_page.dart';
... ... @@ -18,6 +19,7 @@ class AppRouteName {
18 19 static const String setPwd = 'setPwd';
19 20 static const String webView = 'webView';
20 21 static const String lesson = 'lesson';
  22 + static const String listen = 'listen';
21 23 static const String tab = '/';
22 24 }
23 25  
... ... @@ -42,6 +44,8 @@ class AppRouter {
42 44 return CupertinoPageRoute(builder: (_) => const ForgetPasswordHomePage());
43 45 case AppRouteName.lesson:
44 46 return CupertinoPageRoute(builder: (_) => const LessonPage());
  47 + case AppRouteName.listen:
  48 + return CupertinoPageRoute(builder: (_) => const ListenPage());
45 49 case AppRouteName.setPwd:
46 50 final phoneNum = (settings.arguments as Map)['phoneNumber'] as String;
47 51 return CupertinoPageRoute(builder: (_) => SetPassWordPage(phoneNum: phoneNum));
... ...
lib/tab/tab_page.dart
1 1 import 'package:flutter/material.dart';
2 2 import 'package:flutter_bloc/flutter_bloc.dart';
3   -import 'package:wow_english/Pages/page1.dart';
4   -import 'package:wow_english/Pages/page2.dart';
  3 +import 'package:wow_english/home/home_page.dart';
  4 +import 'package:wow_english/lessons/lesson_page.dart';
5 5 import 'package:wow_english/tab/blocs/tab_bloc.dart';
6 6  
7 7 class TabPage extends StatelessWidget {
8 8 const TabPage({super.key});
9 9  
10 10 final _pages =const <Widget>[
11   - Page1(),
12   - Page2()
  11 + HomePage(),
  12 + LessonPage()
13 13 ];
14 14  
15 15 final _tabIcons = const <Icon>[
... ...