From 6d61919a27d0d1918de3bf7658e66cb66139d83b Mon Sep 17 00:00:00 2001 From: wuqifeng <540416539@qq.com> Date: Mon, 22 Apr 2024 19:45:16 +0800 Subject: [PATCH] feat:增加过渡页&集成串联游戏 --- android/app/build.gradle | 3 ++- android/app/src/main/kotlin/com/kouyuxingqiu/wow_english/MainActivity.kt | 6 +++++- android/app/src/main/kotlin/com/kouyuxingqiu/wow_english/methodChannels/GameMethodChannel.kt | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ android/build.gradle | 1 + assets/images/bg_frame_module_pic.png | Bin 0 -> 55363 bytes assets/images/bg_header_sliver.png | Bin 0 -> 122621 bytes assets/images/ic_countdown.png | Bin 0 -> 2152 bytes assets/images/label_module_game.png | Bin 0 -> 16075 bytes assets/images/label_module_study.png | Bin 0 -> 16235 bytes assets/images/pic_module_game.png | Bin 0 -> 222046 bytes assets/images/pic_module_study.png | Bin 0 -> 253461 bytes lib/app/splash_page.dart | 2 +- lib/pages/moduleSelect/bloc.dart | 16 ++++++++++++++++ lib/pages/moduleSelect/event.dart | 3 +++ lib/pages/moduleSelect/state.dart | 9 +++++++++ lib/pages/moduleSelect/view.dart | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/pages/moduleSelect/widgets/BaseHomeHeaderWidget.dart | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/pages/shop/home/widgets/product_item.dart | 133 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/route/route.dart | 8 ++++++++ 19 files changed, 430 insertions(+), 3 deletions(-) create mode 100644 android/app/src/main/kotlin/com/kouyuxingqiu/wow_english/methodChannels/GameMethodChannel.kt create mode 100644 assets/images/bg_frame_module_pic.png create mode 100644 assets/images/bg_header_sliver.png create mode 100644 assets/images/ic_countdown.png create mode 100644 assets/images/label_module_game.png create mode 100644 assets/images/label_module_study.png create mode 100644 assets/images/pic_module_game.png create mode 100644 assets/images/pic_module_study.png create mode 100644 lib/pages/moduleSelect/bloc.dart create mode 100644 lib/pages/moduleSelect/event.dart create mode 100644 lib/pages/moduleSelect/state.dart create mode 100644 lib/pages/moduleSelect/view.dart create mode 100644 lib/pages/moduleSelect/widgets/BaseHomeHeaderWidget.dart create mode 100644 lib/pages/shop/home/widgets/product_item.dart diff --git a/android/app/build.gradle b/android/app/build.gradle index 4f7fa94..7664254 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -29,7 +29,7 @@ android { namespace "com.kouyuxingqiu.wow_english" // compileSdkVersion flutter.compileSdkVersion compileSdkVersion 33 - // 展示没有ndk需求 + // 暂时没有ndk需求 // ndkVersion flutter.ndkVersion compileOptions { @@ -87,4 +87,5 @@ dependencies { implementation 'com.geyifeng.immersionbar:immersionbar:3.2.2' // kotlin扩展(可选) implementation 'com.geyifeng.immersionbar:immersionbar-ktx:3.2.2' + implementation 'io.keyss.android.library:bjgame:1.0.2' } diff --git a/android/app/src/main/kotlin/com/kouyuxingqiu/wow_english/MainActivity.kt b/android/app/src/main/kotlin/com/kouyuxingqiu/wow_english/MainActivity.kt index 6e2bb0e..4d8363e 100644 --- a/android/app/src/main/kotlin/com/kouyuxingqiu/wow_english/MainActivity.kt +++ b/android/app/src/main/kotlin/com/kouyuxingqiu/wow_english/MainActivity.kt @@ -8,6 +8,7 @@ import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsControllerCompat import com.gyf.immersionbar.BarHide import com.gyf.immersionbar.ImmersionBar +import com.kouyuxingqiu.wow_english.methodChannels.GameMethodChannel import com.kouyuxingqiu.wow_english.methodChannels.SingSoungMethodChannel import io.flutter.embedding.android.FlutterActivity @@ -17,7 +18,10 @@ class MainActivity : FlutterActivity() { Log.i("WowEnglish", "MainActivity onCreate") //隐藏状态栏和导航栏 ImmersionBar.with(this).hideBar(BarHide.FLAG_HIDE_BAR).init() - flutterEngine?.let { SingSoungMethodChannel(this, it) } + flutterEngine?.let { + SingSoungMethodChannel(this, it) + GameMethodChannel(this, it) + } } override fun onResume() { diff --git a/android/app/src/main/kotlin/com/kouyuxingqiu/wow_english/methodChannels/GameMethodChannel.kt b/android/app/src/main/kotlin/com/kouyuxingqiu/wow_english/methodChannels/GameMethodChannel.kt new file mode 100644 index 0000000..7838dad --- /dev/null +++ b/android/app/src/main/kotlin/com/kouyuxingqiu/wow_english/methodChannels/GameMethodChannel.kt @@ -0,0 +1,59 @@ +package com.kouyuxingqiu.wow_english.methodChannels + +import android.content.Intent +import android.content.Intent.getIntent +import android.util.Log +import androidx.core.content.ContextCompat.startActivity +import com.kouyuxingqiu.wow_english.singsound.SingEngineHelper +import com.kouyuxingqiu.wow_english.util.GlobalHandler +import io.flutter.embedding.android.FlutterActivity +import io.flutter.embedding.engine.FlutterEngine +import io.flutter.plugin.common.MethodChannel +import org.cocos2dx.cpp.AppActivity +import java.lang.ref.WeakReference + + +/** + * @author: stay + * @date: 2024/4/22 18:36 + * @description: 游戏方法通道 + */ +class GameMethodChannel(activity: FlutterActivity, flutterEngine: FlutterEngine) { + private var methodChannel: MethodChannel? = null + private val TAG = "GameMethodChannel" + + companion object { + var channel: WeakReference? = null + + fun invokeMethod(method: String, arguments: Any?) { + channel?.get()?.methodChannel?.invokeMethod(method, arguments) + } + } + + init { + // name需与flutter端一致 + methodChannel = + MethodChannel( + flutterEngine.dartExecutor.binaryMessenger, + "wow_english/game_method_channel" + ) + methodChannel?.setMethodCallHandler { call, result -> + Log.d(TAG, "call=${call.method} ${call.arguments} result=$result") + when (call.method) { + "openGamePage" -> { + if (call.hasArgument("gameId")) { + val gameId = call.argument("gameId") + activity.startActivity( + Intent(activity, AppActivity::class.java).apply { + putExtra("game", gameId) + }) + result.success(true) + } else { + result.success(false) + } + } + } + } + channel = WeakReference(this) + } +} \ No newline at end of file diff --git a/android/build.gradle b/android/build.gradle index 9151f20..482dae9 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -17,6 +17,7 @@ allprojects { google() mavenCentral() maven { url 'https://repo.singsound.com/repository/singsound_ginger_android_sdk/' } + maven { url 'https://maven.zjzxsl.com/repository/android-public/' } } } diff --git a/assets/images/bg_frame_module_pic.png b/assets/images/bg_frame_module_pic.png new file mode 100644 index 0000000..777b5a5 Binary files /dev/null and b/assets/images/bg_frame_module_pic.png differ diff --git a/assets/images/bg_header_sliver.png b/assets/images/bg_header_sliver.png new file mode 100644 index 0000000..452987d Binary files /dev/null and b/assets/images/bg_header_sliver.png differ diff --git a/assets/images/ic_countdown.png b/assets/images/ic_countdown.png new file mode 100644 index 0000000..77aac71 Binary files /dev/null and b/assets/images/ic_countdown.png differ diff --git a/assets/images/label_module_game.png b/assets/images/label_module_game.png new file mode 100644 index 0000000..3bd4b39 Binary files /dev/null and b/assets/images/label_module_game.png differ diff --git a/assets/images/label_module_study.png b/assets/images/label_module_study.png new file mode 100644 index 0000000..506c924 Binary files /dev/null and b/assets/images/label_module_study.png differ diff --git a/assets/images/pic_module_game.png b/assets/images/pic_module_game.png new file mode 100644 index 0000000..a7468d6 Binary files /dev/null and b/assets/images/pic_module_game.png differ diff --git a/assets/images/pic_module_study.png b/assets/images/pic_module_study.png new file mode 100644 index 0000000..f7f3388 Binary files /dev/null and b/assets/images/pic_module_study.png differ diff --git a/lib/app/splash_page.dart b/lib/app/splash_page.dart index 96d7725..3cf91be 100644 --- a/lib/app/splash_page.dart +++ b/lib/app/splash_page.dart @@ -69,7 +69,7 @@ class _TransitionViewState extends State { } else { pushNamedAndRemoveUntil(AppRouteName.login, (route) => false); }*/ - pushNamedAndRemoveUntil(AppRouteName.home, (route) => false); + pushNamedAndRemoveUntil(AppRouteName.moduleSelect, (route) => false); }); } diff --git a/lib/pages/moduleSelect/bloc.dart b/lib/pages/moduleSelect/bloc.dart new file mode 100644 index 0000000..e4bd5f8 --- /dev/null +++ b/lib/pages/moduleSelect/bloc.dart @@ -0,0 +1,16 @@ +import 'package:bloc/bloc.dart'; + +import 'event.dart'; +import 'state.dart'; + + +class ModuleSelectBloc extends Bloc { + + ModuleSelectBloc() : super(ModuleSelectState().init()) { + on(_init); + } + + void _init(InitEvent event, Emitter emit) async { + emit(state.clone()); + } +} diff --git a/lib/pages/moduleSelect/event.dart b/lib/pages/moduleSelect/event.dart new file mode 100644 index 0000000..5695068 --- /dev/null +++ b/lib/pages/moduleSelect/event.dart @@ -0,0 +1,3 @@ +abstract class ModuleSelectEvent {} + +class InitEvent extends ModuleSelectEvent {} \ No newline at end of file diff --git a/lib/pages/moduleSelect/state.dart b/lib/pages/moduleSelect/state.dart new file mode 100644 index 0000000..8a51120 --- /dev/null +++ b/lib/pages/moduleSelect/state.dart @@ -0,0 +1,9 @@ +class ModuleSelectState { + ModuleSelectState init() { + return ModuleSelectState(); + } + + ModuleSelectState clone() { + return ModuleSelectState(); + } +} diff --git a/lib/pages/moduleSelect/view.dart b/lib/pages/moduleSelect/view.dart new file mode 100644 index 0000000..076a6d7 --- /dev/null +++ b/lib/pages/moduleSelect/view.dart @@ -0,0 +1,89 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:wow_english/common/extension/string_extension.dart'; +import 'package:wow_english/pages/moduleSelect/state.dart'; +import 'package:wow_english/pages/moduleSelect/widgets/BaseHomeHeaderWidget.dart'; + +import 'bloc.dart'; +import 'event.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:wow_english/route/route.dart'; + +class ModuleSelectPage extends StatelessWidget { + const ModuleSelectPage({super.key}); + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (BuildContext context) => ModuleSelectBloc()..add(InitEvent()), + child: Builder(builder: (context) => _HomePageView()), + ); + } +} + +class _HomePageView extends StatelessWidget { + @override + Widget build(BuildContext context) { + final bloc = BlocProvider.of(context); + return BlocListener( + listener: (context, state) {}, + child: _homeView(), + ); + } + + Widget _homeView() => BlocBuilder( + builder: (context, state) { + final bloc = BlocProvider.of(context); + return Scaffold( + body: Container( + color: Colors.white, + child: Column( + children: [ + const BaseHomeHeaderWidget(), + Expanded( + child: Center( + child: Row( + children: [ + Expanded( + child: GestureDetector( + onTap: () { + pushNamed(AppRouteName.home); + }, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image.asset('pic_module_study'.assetPng, + width: 162.5.w, height: 203.5.h), + 10.verticalSpace, + Image.asset('label_module_study'.assetPng, + width: 124.w, height: 34.h), + ], + ), + ), + ), + Expanded( + child: GestureDetector( + onTap: () { + pushNamed(AppRouteName.games); + }, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image.asset('pic_module_game'.assetPng, + width: 162.5.w, height: 203.5.h), + 10.verticalSpace, + Image.asset('label_module_game'.assetPng, + width: 124.w, height: 34.h), + ], + )), + ), + ], + ), + ), + ) + ], + ), + ), + ); + }); +} diff --git a/lib/pages/moduleSelect/widgets/BaseHomeHeaderWidget.dart b/lib/pages/moduleSelect/widgets/BaseHomeHeaderWidget.dart new file mode 100644 index 0000000..5560345 --- /dev/null +++ b/lib/pages/moduleSelect/widgets/BaseHomeHeaderWidget.dart @@ -0,0 +1,104 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:wow_english/common/extension/string_extension.dart'; + +import '../../../common/core/user_util.dart'; +import '../../../models/course_entity.dart'; +import '../../../route/route.dart'; +import '../../../utils/image_util.dart'; +import '../../user/bloc/user_bloc.dart'; + +class BaseHomeHeaderWidget extends StatelessWidget { + const BaseHomeHeaderWidget({super.key, this.entity}); + + final CourseEntity? entity; + + @override + Widget build(BuildContext context) { + return BlocBuilder( + builder: (context, state) { + return Container( + height: 45, + width: double.infinity, + decoration: BoxDecoration( + image: DecorationImage( + image: AssetImage('bg_header_sliver'.assetPng), + fit: BoxFit.cover, + ), + ), + padding: EdgeInsets.symmetric(horizontal: 9.5.w), + child: Row( + children: [ + ScreenUtil().bottomBarHeight.horizontalSpace, + GestureDetector( + onTap: () => {onUserClick()}, + child: Container( + decoration: BoxDecoration( + border: Border.all( + width: 1.0, + color: const Color(0xFF140C10), + ), + borderRadius: BorderRadius.circular(21), + ), + child: CircleAvatar( + radius: 21, + backgroundImage: ImageUtil.getImageProviderOnDefault( + UserUtil.getUser()?.avatarUrl), + ), + ), + ), + GestureDetector( + onTap: () { + onUserClick(); + }, + 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: Text( + UserUtil.getUser()?.name ?? '未登录', + style: TextStyle( + color: const Color(0xFF333333), fontSize: 16.sp), + ), + ), + ), + 20.horizontalSpace, + const Expanded( + child: Text( + "WOW ENGLISH", + textAlign: TextAlign.left, + style: TextStyle(color: Colors.white, fontSize: 30.0), + )), + Row(children: [ + Image( + width: 20.0.w, + height: 20.0.h, + image: AssetImage('ic_countdown'.assetPng)), + // 替换为你的图片资源路径 + const SizedBox(width: 10.0), + // 图片和文本之间的间隔 + const Text('还剩29天'), + ]), + ScreenUtil().bottomBarHeight.horizontalSpace, + ], + )); + }, + ); + } +} + +void onUserClick() { + if (UserUtil.token.isEmpty) { + pushNamed(AppRouteName.login); + } else { + pushNamed(AppRouteName.user); + } +} diff --git a/lib/pages/shop/home/widgets/product_item.dart b/lib/pages/shop/home/widgets/product_item.dart new file mode 100644 index 0000000..8fd000f --- /dev/null +++ b/lib/pages/shop/home/widgets/product_item.dart @@ -0,0 +1,133 @@ +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:wow_english/models/product_entity.dart'; + +class ProductItem extends StatelessWidget { + const ProductItem({super.key, + required this.onTap, this.entity}); + + final ProductEntity? entity; + + final Function() onTap; + + @override + Widget build(BuildContext context) { + return Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10.r), + border: Border.all( + width: 1.0, + color: Colors.black + ) + // image: DecorationImage( + // image: AssetImage( + // ''.assetPng, + // ), + // fit: BoxFit.fill + // ) + ), + padding: EdgeInsets.symmetric(horizontal: 16.w,vertical: 16.h), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + // Container( + // width: 124.w, + // decoration: BoxDecoration( + // border: Border.all( + // width: 1.0, + // color: const Color(0xFF333333), + // ), + // image: const DecorationImage( + // + // image: NetworkImage(entity?.coverUrl??''), + // ) + // ), + // ), + CachedNetworkImage( + imageUrl: entity?.picUrl ?? '', + fit: BoxFit.fill, + imageBuilder: (context, imageProvider) => + Container( + decoration: BoxDecoration( + border: Border.all( + width: 1.0, + color: const Color(0xFF333333), + ), + borderRadius: BorderRadius.circular(5.0), + ), + ), + placeholder: (context, url) => CircularProgressIndicator(), + // errorWidget: (context, url, error) => const Icon(Icons.error), + height: 124.h, + width: 124.w, + ), + 21.5.horizontalSpace, + Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text( + entity?.name ?? '', + softWrap: true, + textAlign: TextAlign.left, + style: TextStyle( + fontSize: 12.sp, + color: const Color(0xFF333333) + ), + ), + RichText( + text: TextSpan( + children:[ + TextSpan( + text: '¥', + style: TextStyle( + fontSize: 21.sp, + color: const Color(0xFFF51A1A), + ) + ), + TextSpan( + text: entity?.price?.toString() ?? '', + style: TextStyle( + fontSize: 40.sp, + color: const Color(0xFFF51A1A), + ), + ) + ] + ), + ), + GestureDetector( + onTap: () { + onTap(); + }, + child: Container( + decoration: BoxDecoration( + color: const Color(0xFFF5C51F), + borderRadius: BorderRadius.circular(5.r), + border: Border.all( + color: const Color(0xFF333333), + width: 1.0, + ) + ), + padding: EdgeInsets.symmetric( + vertical: 1.h, + horizontal: 26.5.w, + ), + child: Text( + '立即购买', + style: TextStyle( + fontSize: 10.sp, + color: const Color(0xFF333333) + ), + ), + ), + ) + ], + ), + ) + ], + ), + ); + } +} \ No newline at end of file diff --git a/lib/route/route.dart b/lib/route/route.dart index 2865611..e6b5a20 100644 --- a/lib/route/route.dart +++ b/lib/route/route.dart @@ -3,12 +3,14 @@ import 'package:flutter/material.dart'; import 'package:wow_english/app/splash_page.dart'; import 'package:wow_english/common/pages/wow_web_page.dart'; import 'package:wow_english/models/product_entity.dart'; +import 'package:wow_english/pages/games/view.dart'; import 'package:wow_english/pages/home/home_page.dart'; import 'package:wow_english/pages/lessons/lesson_page.dart'; import 'package:wow_english/pages/listen/listen_page.dart'; import 'package:wow_english/pages/login/forgetpwd/forget_password_home_page.dart'; import 'package:wow_english/pages/login/loginpage/login_page.dart'; import 'package:wow_english/pages/login/setpwd/set_pwd_page.dart'; +import 'package:wow_english/pages/moduleSelect/view.dart'; import 'package:wow_english/pages/practice/topic_picture_page.dart'; import 'package:wow_english/pages/repeatafter/repeat_after_page.dart'; import 'package:wow_english/pages/repeataftercontent/repeat_after_content_page.dart'; @@ -32,6 +34,8 @@ import '../utils/log_util.dart'; class AppRouteName { static const String splash = 'splash'; static const String login = 'login'; + static const String moduleSelect = 'moduleSelect'; + static const String games = 'games'; static const String home = 'home'; static const String fogPwd = 'fogPwd'; @@ -88,6 +92,10 @@ class AppRouter { transitionsBuilder: (_, __, ___, child) => child); case AppRouteName.login: return CupertinoPageRoute(builder: (_) => const LoginPage()); + case AppRouteName.moduleSelect: + return CupertinoPageRoute(builder: (_) => const ModuleSelectPage()); + case AppRouteName.games: + return CupertinoPageRoute(builder: (_) => const GamesPage()); case AppRouteName.home: var moduleId = ''; if (settings.arguments != null) { -- libgit2 0.22.2