|
|
@@ -0,0 +1,219 @@
|
|
|
+import 'package:flutter/material.dart';
|
|
|
+import 'package:flutter_screenutil/flutter_screenutil.dart';
|
|
|
+import 'package:get/get.dart';
|
|
|
+import 'package:keyboard/base/base_page.dart';
|
|
|
+import 'package:keyboard/resource/assets.gen.dart';
|
|
|
+import 'package:keyboard/resource/colors.gen.dart';
|
|
|
+import 'package:video_player/video_player.dart';
|
|
|
+
|
|
|
+import '../../../di/get_it.dart';
|
|
|
+import '../../../router/app_pages.dart';
|
|
|
+import '../../../utils/status_bar_util.dart';
|
|
|
+import 'keyboard_tutorial_video_controller.dart';
|
|
|
+
|
|
|
+/// 键盘使用教程-视频引导页
|
|
|
+class KeyboardTutorialVideoPage
|
|
|
+ extends BasePage<KeyboardTutorialVideoController> {
|
|
|
+ KeyboardTutorialVideoPage({super.key}) {
|
|
|
+ Get.lazyPut(() => getIt.get<KeyboardTutorialVideoController>());
|
|
|
+ }
|
|
|
+
|
|
|
+ static void start() {
|
|
|
+ Get.toNamed(RoutePath.keyboardTutorialVideo);
|
|
|
+ }
|
|
|
+
|
|
|
+ @override
|
|
|
+ bool immersive() {
|
|
|
+ // 开启沉浸式
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ @override
|
|
|
+ backgroundColor() {
|
|
|
+ return Color(0xFFF2EFFF);
|
|
|
+ }
|
|
|
+
|
|
|
+ @override
|
|
|
+ Widget buildBody(BuildContext context) {
|
|
|
+ return Scaffold(
|
|
|
+ backgroundColor: backgroundColor(),
|
|
|
+ body: Stack(
|
|
|
+ children: [
|
|
|
+ // 头部
|
|
|
+ Positioned(left: 0, top: 0, right: 0, child: _buildHeader(context)),
|
|
|
+ // 状态栏和标题栏
|
|
|
+ Positioned(
|
|
|
+ left: 0,
|
|
|
+ top: 0,
|
|
|
+ right: 0,
|
|
|
+ child: Column(
|
|
|
+ mainAxisSize: MainAxisSize.min,
|
|
|
+ children: [_buildStatusBar(), _buildTopBar()],
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ // 内容,填充剩余部分
|
|
|
+ Positioned.fill(
|
|
|
+ top: 180.h + StatusBarUtil.getStatusBarHeight(Get.context!),
|
|
|
+ left: 0,
|
|
|
+ right: 0,
|
|
|
+ bottom: 0,
|
|
|
+ child: SingleChildScrollView(child: _buildContent()),
|
|
|
+ ),
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ /// 导航栏占位
|
|
|
+ Widget _buildStatusBar() {
|
|
|
+ // 导航栏高度
|
|
|
+ double statusBarHeight = StatusBarUtil.getStatusBarHeight(Get.context!);
|
|
|
+ return Container(height: statusBarHeight);
|
|
|
+ }
|
|
|
+
|
|
|
+ /// 顶部栏
|
|
|
+ Widget _buildTopBar() {
|
|
|
+ return Container(
|
|
|
+ // 宽度撑满父组件
|
|
|
+ width: double.infinity,
|
|
|
+ height: kToolbarHeight,
|
|
|
+ // 背景颜色
|
|
|
+ color: Colors.transparent,
|
|
|
+ // padding: EdgeInsets.symmetric(horizontal: 16.0),
|
|
|
+ child: ConstrainedBox(
|
|
|
+ // 设置宽度为无限大,撑满父组件,否则Stack获取不到高度,会报错
|
|
|
+ constraints: BoxConstraints(minWidth: double.infinity),
|
|
|
+ child: Stack(
|
|
|
+ alignment: Alignment.center,
|
|
|
+ children: [
|
|
|
+ // 返回按钮
|
|
|
+ Positioned(
|
|
|
+ left: 16.w,
|
|
|
+ child: GestureDetector(
|
|
|
+ onTap: controller.clickBack,
|
|
|
+ child: Assets.images.iconBlackBackArrow.image(
|
|
|
+ width: 24.w,
|
|
|
+ height: 24.h,
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ /// 头部布局
|
|
|
+ Widget _buildHeader(BuildContext context) {
|
|
|
+ return SizedBox(
|
|
|
+ width: double.infinity,
|
|
|
+ height: 260.h,
|
|
|
+ child: Stack(
|
|
|
+ alignment: Alignment.center,
|
|
|
+ children: [
|
|
|
+ // 蒙版
|
|
|
+ Assets.images.bgKeyboardVideoTutorialHeaderMask.image(
|
|
|
+ width: double.infinity,
|
|
|
+ height: double.infinity,
|
|
|
+ ),
|
|
|
+ // 提示语
|
|
|
+ Positioned(
|
|
|
+ top: 20.h + StatusBarUtil.getStatusBarHeight(context),
|
|
|
+ child: Assets.images.iconKeyboardTutorialVideoHeaderSlogan.image(
|
|
|
+ width: 352.w,
|
|
|
+ height: 178.h,
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ ],
|
|
|
+ ),
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ /// 内容
|
|
|
+ Widget _buildContent() {
|
|
|
+ return Container(
|
|
|
+ // 渐变背景
|
|
|
+ decoration: BoxDecoration(
|
|
|
+ gradient: LinearGradient(
|
|
|
+ colors: [Color(0x00FFFFFF), Color(0xFFF2EFFF)],
|
|
|
+ begin: Alignment.topCenter,
|
|
|
+ end: Alignment.bottomRight,
|
|
|
+ ),
|
|
|
+ shape: BoxShape.rectangle,
|
|
|
+ ),
|
|
|
+ child: Column(children: [_buildTutorialVideo()]),
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ /// 教程视频
|
|
|
+ Widget _buildTutorialVideo() {
|
|
|
+ return Container(
|
|
|
+ margin: EdgeInsets.only(left: 16, right: 16, top: 12, bottom: 23),
|
|
|
+ padding: EdgeInsets.all(12.w),
|
|
|
+ decoration: BoxDecoration(
|
|
|
+ color: ColorName.white,
|
|
|
+ borderRadius: BorderRadius.all(Radius.circular(24.w)),
|
|
|
+ ),
|
|
|
+ child: LayoutBuilder(
|
|
|
+ builder: (context, constraints) {
|
|
|
+ double maxWidth = constraints.maxWidth - 24.w;
|
|
|
+ double videoRatio = controller.videoController.value.aspectRatio;
|
|
|
+ return Stack(
|
|
|
+ alignment: Alignment.center,
|
|
|
+ children: [
|
|
|
+ // 视频容器(动态宽高 + 裁剪)
|
|
|
+ SizedBox(
|
|
|
+ width: maxWidth,
|
|
|
+ height: maxWidth / videoRatio,
|
|
|
+ child: ClipRRect(
|
|
|
+ borderRadius: BorderRadius.circular(12.w),
|
|
|
+ child: VideoPlayer(controller.videoController),
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ // 操作按钮
|
|
|
+ _buildActionBtn(),
|
|
|
+ ],
|
|
|
+ );
|
|
|
+ },
|
|
|
+ ),
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ /// 操作按钮
|
|
|
+ Widget _buildActionBtn() {
|
|
|
+ return Obx(() {
|
|
|
+ return Stack(
|
|
|
+ children: [
|
|
|
+ Visibility(
|
|
|
+ visible: !controller.isVideoPlaying.value,
|
|
|
+ child: _buildPlayBtn(),
|
|
|
+ ),
|
|
|
+ Visibility(
|
|
|
+ visible: controller.isVideoPlaying.value,
|
|
|
+ child: _buildPauseBtn(),
|
|
|
+ ),
|
|
|
+ ],
|
|
|
+ );
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ /// 播放按钮
|
|
|
+ Widget _buildPlayBtn() {
|
|
|
+ return GestureDetector(
|
|
|
+ onTap: () {
|
|
|
+ controller.clickPlay();
|
|
|
+ },
|
|
|
+ child: Assets.images.iconPlay.image(width: 52.w, height: 52.w),
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ /// 暂停按钮
|
|
|
+ Widget _buildPauseBtn() {
|
|
|
+ return GestureDetector(
|
|
|
+ onTap: () {
|
|
|
+ controller.clickPause();
|
|
|
+ },
|
|
|
+ child: Assets.images.iconPause.image(width: 52.w, height: 52.w),
|
|
|
+ );
|
|
|
+ }
|
|
|
+}
|