diff --git a/assets/images/back_around.png b/assets/images/back_around.png new file mode 100644 index 0000000..d4d8e8c --- /dev/null +++ b/assets/images/back_around.png diff --git a/assets/images/blue-positive.png b/assets/images/blue-positive.png new file mode 100644 index 0000000..3b5fb8d --- /dev/null +++ b/assets/images/blue-positive.png diff --git a/assets/images/listen_lock.png b/assets/images/listen_lock.png new file mode 100644 index 0000000..618912d --- /dev/null +++ b/assets/images/listen_lock.png diff --git a/lib/app/splash_page.dart b/lib/app/splash_page.dart index 2c37d52..cdf870e 100644 --- a/lib/app/splash_page.dart +++ b/lib/app/splash_page.dart @@ -29,7 +29,7 @@ class _TransitionViewState extends State { Future startTime() async { Timer(const Duration(seconds: 2),() { if(BasicConfigurationManager().sessionId!.isNotEmpty) { - Navigator.of(context).pushNamedAndRemoveUntil(AppRouteName.tab, (route) => false); + Navigator.of(context).pushNamedAndRemoveUntil(AppRouteName.home, (route) => false); } else { Navigator.of(context).pushNamedAndRemoveUntil(AppRouteName.login,(route) => false); } diff --git a/lib/common/widgets/we_app_bar.dart b/lib/common/widgets/we_app_bar.dart index 9c4ac67..4b5f43b 100644 --- a/lib/common/widgets/we_app_bar.dart +++ b/lib/common/widgets/we_app_bar.dart @@ -31,9 +31,9 @@ class WEAppBar extends StatelessWidget implements PreferredSizeWidget { child: Container( alignment: Alignment.center, child: Image.asset( - 'back'.assetPng, - height: 43, - width: 43, + 'back_around'.assetPng, + height: 40, + width: 40, ), ), ), diff --git a/lib/home/bloc/home_bloc.dart b/lib/home/bloc/home_bloc.dart index ad57422..d70e546 100644 --- a/lib/home/bloc/home_bloc.dart +++ b/lib/home/bloc/home_bloc.dart @@ -1,13 +1,12 @@ -import 'dart:async'; - -import 'package:bloc/bloc.dart'; -import 'package:meta/meta.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; part 'home_event.dart'; part 'home_state.dart'; class HomeBloc extends Bloc { - HomeBloc() : super(HomeInitial()) { + final PageController pageController; + HomeBloc(this.pageController) : super(HomeInitial()) { on((event, emit) { // TODO: implement event handler }); diff --git a/lib/home/home_page.dart b/lib/home/home_page.dart index 25ed3bb..72d3e43 100644 --- a/lib/home/home_page.dart +++ b/lib/home/home_page.dart @@ -1,6 +1,10 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_easyloading/flutter_easyloading.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:wow_english/common/extension/string_extension.dart'; import 'package:wow_english/home/bloc/home_bloc.dart'; +import 'package:wow_english/home/widgets/home_lesson_item_widget.dart'; import 'package:wow_english/home/widgets/home_tab_header_widget.dart'; import 'package:wow_english/route/route.dart'; @@ -10,7 +14,9 @@ class HomePage extends StatelessWidget { @override Widget build(BuildContext context) { return BlocProvider( - create: (context) => HomeBloc(), + create: (context) => HomeBloc(PageController( + initialPage: 0, + )), child: _HomePageView(), ); } @@ -23,7 +29,9 @@ class _HomePageView extends StatelessWidget { } else if (type == HeaderActionType.phase) { Navigator.of(AppRouter.context).pushNamed(AppRouteName.lesson); } else if (type == HeaderActionType.listen) { - + Navigator.of(AppRouter.context).pushNamed(AppRouteName.listen); + } else if (type == HeaderActionType.shop) { + } else { } @@ -33,22 +41,78 @@ class _HomePageView extends StatelessWidget { Widget build(BuildContext context) { return BlocListener( listener: (context, state){}, - child: Scaffold( - body: Container( - color: Colors.white, - child: Center( - child: Column( - children: [ - HomeTabHeaderWidget( - actionTap: (HeaderActionType type) { - _headerActionEvent(type); - }, - ), - ], - ), - ), - ), - ), + child: _homeView(), ); } + + Widget _homeView() => BlocBuilder( + builder: (context, state){ + final bloc = BlocProvider.of(context); + return Scaffold( + body: Container( + color: Colors.white, + child: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + HomeTabHeaderWidget( + actionTap: (HeaderActionType type) { + _headerActionEvent(type); + }, + ), + Expanded( + child: PageView.builder( + itemCount: 10, + controller: bloc.pageController, + pageSnapping: false, + onPageChanged: (int index) { + EasyLoading.showToast(index.toString()); + }, + itemBuilder: (BuildContext context,int index){ + return const HomeLessonItem(); + // return Container( + // color:index%2==0?Colors.red:Colors.blue + // ); + }) + , + ), + SafeArea( + child: Padding( + padding: EdgeInsets.symmetric(horizontal: 13.w), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + SizedBox( + height: 47.h, + width: 80.w, + ), + Container( + decoration: BoxDecoration( + color: Colors.blue, + borderRadius: BorderRadius.circular(14.5.r), + ), + padding: EdgeInsets.symmetric(vertical: 8.h,horizontal: 24.w), + child: Text( + '3/67', + style: TextStyle( + color: Colors.white, + fontSize: 12.sp + ), + ), + ), + Image.asset( + 'blue-positive'.assetPng, + height: 47.h, + width: 80.w, + ), + ], + ), + ), + ) + ], + ), + ), + ), + ); + }); } \ No newline at end of file diff --git a/lib/home/widgets/home_lesson_item_widget.dart b/lib/home/widgets/home_lesson_item_widget.dart new file mode 100644 index 0000000..9bf3a85 --- /dev/null +++ b/lib/home/widgets/home_lesson_item_widget.dart @@ -0,0 +1,25 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; + +class HomeLessonItem extends StatelessWidget { + const HomeLessonItem({super.key}); + + @override + Widget build(BuildContext context) { + return SizedBox( + width: double.infinity, + child: ListView.builder( + itemCount: 5, + scrollDirection: Axis.horizontal, + physics: const NeverScrollableScrollPhysics(), + itemBuilder: (BuildContext context,int index){ + return Padding( + padding: EdgeInsets.symmetric(horizontal: 4.w), + child: Image.network( + 'https://img.liblibai.com/web/648331d5a2cb5.png?image_process=format,webp&x-oss-process=image/resize,w_2980,m_lfit/format,webp', + ), + ); + }), + ); + } +} \ No newline at end of file diff --git a/lib/home/widgets/home_tab_header_widget.dart b/lib/home/widgets/home_tab_header_widget.dart index cc43ebd..d071d32 100644 --- a/lib/home/widgets/home_tab_header_widget.dart +++ b/lib/home/widgets/home_tab_header_widget.dart @@ -11,6 +11,8 @@ enum HeaderActionType { listen, //购买 shop, + //个人信息 + userinfo } class HomeTabHeaderWidget extends StatelessWidget { @@ -29,20 +31,54 @@ class HomeTabHeaderWidget extends StatelessWidget { child: Row( children: [ ScreenUtil().bottomBarHeight.horizontalSpace, - ClipRRect( - borderRadius:BorderRadius.circular(21), - child: Image.network( - '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', - height: 42, - width: 42, - fit: BoxFit.fill, + GestureDetector( + onTap: () { + if(actionTap != null) { + actionTap!(HeaderActionType.userinfo); + } + }, + child: Container( + decoration: BoxDecoration( + border: Border.all( + width: 1.0, + color: const Color(0xFF140C10), + ), + borderRadius: BorderRadius.circular(21), + ), + child: const CircleAvatar( + radius: 21, + backgroundImage: NetworkImage( + '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' + ), + ), ), ), - Container( - color: Colors.white, - margin: const EdgeInsets.only(left: 7), - padding: const EdgeInsets.all(7.0), - child: const Text('franky'), + GestureDetector( + onTap: () { + if(actionTap != null) { + actionTap!(HeaderActionType.userinfo); + } + }, + child: Container( + margin: const EdgeInsets.only(left: 7), + padding: const EdgeInsets.all(4.0), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(2), + border: Border.all( + width: 1.0, + color: const Color(0xFF140C10), + style: BorderStyle.solid + ), + ), + child: const Text( + 'franky', + style: TextStyle( + color: Color(0xFF333333), + fontSize: 16 + ), + ), + ), ), 20.horizontalSpace, const Expanded( diff --git a/lib/lessons/lesson_page.dart b/lib/lessons/lesson_page.dart index 868e654..5523e20 100644 --- a/lib/lessons/lesson_page.dart +++ b/lib/lessons/lesson_page.dart @@ -41,6 +41,16 @@ class _LessonPageView extends StatelessWidget { listener: (context, state){}, child: Scaffold( appBar: WEAppBar( + leading: IconButton( + onPressed: (){ + Navigator.pop(context); + }, + icon: Image.asset( + 'back'.assetPng, + height: 43, + width: 43, + ) + ), actions: [ IconButton( icon: Image.asset('shop'.assetPng), diff --git a/lib/listen/bloc/listen_bloc.dart b/lib/listen/bloc/listen_bloc.dart new file mode 100644 index 0000000..73aa9fe --- /dev/null +++ b/lib/listen/bloc/listen_bloc.dart @@ -0,0 +1,15 @@ +import 'dart:async'; + +import 'package:bloc/bloc.dart'; +import 'package:meta/meta.dart'; + +part 'listen_event.dart'; +part 'listen_state.dart'; + +class ListenBloc extends Bloc { + ListenBloc() : super(ListenInitial()) { + on((event, emit) { + // TODO: implement event handler + }); + } +} diff --git a/lib/listen/bloc/listen_event.dart b/lib/listen/bloc/listen_event.dart new file mode 100644 index 0000000..84f8d1c --- /dev/null +++ b/lib/listen/bloc/listen_event.dart @@ -0,0 +1,4 @@ +part of 'listen_bloc.dart'; + +@immutable +abstract class ListenEvent {} diff --git a/lib/listen/bloc/listen_state.dart b/lib/listen/bloc/listen_state.dart new file mode 100644 index 0000000..dfb830f --- /dev/null +++ b/lib/listen/bloc/listen_state.dart @@ -0,0 +1,6 @@ +part of 'listen_bloc.dart'; + +@immutable +abstract class ListenState {} + +class ListenInitial extends ListenState {} diff --git a/lib/listen/listen_page.dart b/lib/listen/listen_page.dart new file mode 100644 index 0000000..c23bc55 --- /dev/null +++ b/lib/listen/listen_page.dart @@ -0,0 +1,51 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:wow_english/common/widgets/we_app_bar.dart'; +import 'package:wow_english/listen/bloc/listen_bloc.dart'; +import 'package:wow_english/listen/widgets/listen_item_widget.dart'; + +class ListenPage extends StatelessWidget { + const ListenPage({super.key}); + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (context) => ListenBloc(), + child: _ListenPageView(), + ); + } +} + +class _ListenPageView extends StatelessWidget { + @override + Widget build(BuildContext context) { + return BlocListener( + listener: (context, state) { + + }, + child: Scaffold( + appBar: const WEAppBar( + titleText: '磨耳朵', + centerTitle: false, + ), + body: _listenView(), + ), + ); + } + + Widget _listenView() => BlocBuilder( + builder: (context, state) { + return ListView.builder( + itemCount: 10, + scrollDirection: Axis.horizontal, + padding: EdgeInsets.symmetric(horizontal: 30.w,vertical: 36.h), + itemBuilder: (BuildContext context,int index){ + return ListenItemWidget( + isLock: (index < 5), + clickEvent: (){ + + }); + }); + }); +} \ No newline at end of file diff --git a/lib/listen/widgets/listen_item_widget.dart b/lib/listen/widgets/listen_item_widget.dart new file mode 100644 index 0000000..ce84f9e --- /dev/null +++ b/lib/listen/widgets/listen_item_widget.dart @@ -0,0 +1,79 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:wow_english/common/extension/string_extension.dart'; + +class ListenItemWidget extends StatelessWidget { + const ListenItemWidget({super.key, this.isLock = false, required this.clickEvent}); + + final Function() clickEvent; + + final bool isLock; + + @override + Widget build(BuildContext context) { + return Padding( + padding: EdgeInsets.symmetric(horizontal: 8.5.w), + child: Column( + children: [ + GestureDetector( + onTap: () { + if (!isLock) { + clickEvent(); + } + }, + child: ClipRRect( + borderRadius:BorderRadius.circular(90), + child: Stack( + alignment:Alignment.center, + children: [ + Image.network( + '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', + height: 180, + width: 180, + fit: BoxFit.fill, + ), + Offstage( + offstage: isLock??false, + child: Container( + height: 180, + width: 180, + color: const Color.fromRGBO(1, 1, 0, 0.5), + ), + ), + Offstage( + offstage: isLock, + child: Image.asset( + 'listen_lock'.assetPng, + height: 36, + width: 41, + ), + ) + ], + ), + ), + ), + 23.verticalSpace, + Container( + height: 40.h, + padding: const EdgeInsets.symmetric(horizontal: 22), + decoration: BoxDecoration( + color: const Color(0xFFFFCC00), + borderRadius: BorderRadius.circular(20.r), + border: Border.all( + width: 1.0, + color: const Color(0xFF333333), + ), + ), + alignment: Alignment.center, + child: Text( + 'listen title', + style: TextStyle( + fontSize: 15.sp + ), + ), + ) + ], + ), + ); + } +} \ No newline at end of file diff --git a/lib/pages/page1.dart b/lib/pages/page1.dart deleted file mode 100644 index 88ca5bc..0000000 --- a/lib/pages/page1.dart +++ /dev/null @@ -1,18 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:wow_english/common/widgets/we_app_bar.dart'; - -class Page1 extends StatelessWidget { - const Page1({super.key}); - - @override - Widget build(BuildContext context) { - return const Scaffold( - appBar: WEAppBar( - titleText: '页面1', - ), - body:Center( - child: Text('页面1'), - ), - ); - } -} \ No newline at end of file diff --git a/lib/pages/page2.dart b/lib/pages/page2.dart deleted file mode 100644 index 5cf8126..0000000 --- a/lib/pages/page2.dart +++ /dev/null @@ -1,18 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:wow_english/common/widgets/we_app_bar.dart'; - -class Page2 extends StatelessWidget { - const Page2({super.key}); - - @override - Widget build(BuildContext context) { - return const Scaffold( - appBar: WEAppBar( - titleText: '页面2', - ), - body:Center( - child: Text('页面2'), - ), - ); - } -} \ No newline at end of file diff --git a/lib/route/route.dart b/lib/route/route.dart index 7ef389f..8a93fd8 100644 --- a/lib/route/route.dart +++ b/lib/route/route.dart @@ -4,6 +4,7 @@ import 'package:wow_english/app/splash_page.dart'; import 'package:wow_english/common/pages/wow_web_page.dart'; import 'package:wow_english/home/home_page.dart'; import 'package:wow_english/lessons/lesson_page.dart'; +import 'package:wow_english/listen/listen_page.dart'; import 'package:wow_english/login/forgetpwd/forget_password_home_page.dart'; import 'package:wow_english/login/loginpage/login_page.dart'; import 'package:wow_english/login/setpwd/set_pwd_page.dart'; @@ -18,6 +19,7 @@ class AppRouteName { static const String setPwd = 'setPwd'; static const String webView = 'webView'; static const String lesson = 'lesson'; + static const String listen = 'listen'; static const String tab = '/'; } @@ -42,6 +44,8 @@ class AppRouter { return CupertinoPageRoute(builder: (_) => const ForgetPasswordHomePage()); case AppRouteName.lesson: return CupertinoPageRoute(builder: (_) => const LessonPage()); + case AppRouteName.listen: + return CupertinoPageRoute(builder: (_) => const ListenPage()); case AppRouteName.setPwd: final phoneNum = (settings.arguments as Map)['phoneNumber'] as String; return CupertinoPageRoute(builder: (_) => SetPassWordPage(phoneNum: phoneNum)); diff --git a/lib/tab/tab_page.dart b/lib/tab/tab_page.dart index 18a7a0f..ea9035c 100644 --- a/lib/tab/tab_page.dart +++ b/lib/tab/tab_page.dart @@ -1,15 +1,15 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:wow_english/Pages/page1.dart'; -import 'package:wow_english/Pages/page2.dart'; +import 'package:wow_english/home/home_page.dart'; +import 'package:wow_english/lessons/lesson_page.dart'; import 'package:wow_english/tab/blocs/tab_bloc.dart'; class TabPage extends StatelessWidget { const TabPage({super.key}); final _pages =const [ - Page1(), - Page2() + HomePage(), + LessonPage() ]; final _tabIcons = const [