193 lines
5.9 KiB
Dart
193 lines
5.9 KiB
Dart
import 'package:flutter/material.dart';
|
||
import 'package:flutter/services.dart';
|
||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||
import 'package:get/get.dart';
|
||
import 'package:kaer_with_panels/app/widgets/kr_local_image.dart';
|
||
import 'package:kaer_with_panels/app/routes/app_pages.dart';
|
||
|
||
/// 🔹 HIBaseScaffold
|
||
/// 用于统一页面结构:
|
||
/// ✅ 全屏背景图
|
||
/// ✅ 左上角返回按钮
|
||
/// ✅ 右上角套餐入口按钮(球形)
|
||
/// ✅ 自定义主体内容(body)
|
||
///
|
||
/// 使用:
|
||
/// ```dart
|
||
/// return HIBaseScaffold(
|
||
/// showBack: true,
|
||
/// showSubscriptionCorner: true,
|
||
/// body: YourWidget(),
|
||
/// );
|
||
/// ```
|
||
class HIBaseScaffold extends StatelessWidget {
|
||
/// 页面主体内容
|
||
final Widget child;
|
||
|
||
/// 是否显示左上角返回按钮
|
||
final bool showBack;
|
||
|
||
/// 【新增】是否显示左上角菜单按钮(用于首页)
|
||
final bool showMenuButton;
|
||
|
||
/// 返回按钮点击事件(默认 Get.back())
|
||
final VoidCallback? onBackTap;
|
||
|
||
/// 页面主标题
|
||
final String? title;
|
||
|
||
/// 页面副标题
|
||
final String? subtitle;
|
||
|
||
/// 是否显示背景图
|
||
final bool showBackgroundImage;
|
||
|
||
final Color? backgroundColor;
|
||
|
||
/// resizeToAvoidBottomInset
|
||
final bool? resizeToAvoidBottomInset;
|
||
|
||
/// 为顶部内容(如返回按钮、标题)预留的高度
|
||
final double topContentAreaHeight;
|
||
|
||
const HIBaseScaffold({
|
||
super.key,
|
||
required this.child,
|
||
this.showBack = true,
|
||
this.showMenuButton = false,
|
||
this.onBackTap,
|
||
this.title,
|
||
this.subtitle,
|
||
this.showBackgroundImage = true,
|
||
this.topContentAreaHeight = 120.0,
|
||
this.resizeToAvoidBottomInset = false,
|
||
this.backgroundColor,
|
||
});
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
// 顶部状态栏高度
|
||
final double topPadding = MediaQuery.of(context).padding.top + 8;
|
||
|
||
return Scaffold(
|
||
extendBodyBehindAppBar: true,
|
||
resizeToAvoidBottomInset: resizeToAvoidBottomInset,
|
||
backgroundColor: showBackgroundImage
|
||
? Colors.transparent
|
||
: (backgroundColor ?? Theme.of(context).scaffoldBackgroundColor),
|
||
appBar: AppBar(
|
||
backgroundColor: Colors.transparent,
|
||
toolbarHeight: 0.0,
|
||
elevation: 0,
|
||
systemOverlayStyle: const SystemUiOverlayStyle(
|
||
statusBarIconBrightness: Brightness.light,
|
||
),
|
||
),
|
||
body: Stack(
|
||
fit: StackFit.expand,
|
||
children: [
|
||
// 背景图全屏
|
||
// if (showBackgroundImage)
|
||
// const Positioned.fill(
|
||
// child: KrLocalImage(
|
||
// imageName: 'global-bg',
|
||
// imageType: ImageType.jpg,
|
||
// ),
|
||
// ),
|
||
|
||
// 页面主体内容(child)
|
||
SafeArea(
|
||
child: Padding(
|
||
padding: EdgeInsets.only(top: topContentAreaHeight),
|
||
child: child,
|
||
),
|
||
),
|
||
|
||
// 左上角按钮区域
|
||
Positioned(
|
||
top: topPadding,
|
||
left: 40.w,
|
||
child: Builder(
|
||
builder: (context) {
|
||
// 优先显示菜单按钮
|
||
if (showMenuButton) {
|
||
return GestureDetector(
|
||
onTap: () async {
|
||
Get.toNamed(Routes.HI_MENU);
|
||
},
|
||
child: Container(
|
||
width: 48,
|
||
height: 48,
|
||
alignment: Alignment.center,
|
||
child: KrLocalImage(
|
||
imageName: 'hi-home-stack',
|
||
width: 48,
|
||
height: 48,
|
||
imageType: ImageType.svg,
|
||
),
|
||
),
|
||
);
|
||
}
|
||
// 如果不显示菜单按钮,再根据 showBack 判断是否显示返回按钮
|
||
else if (showBack) {
|
||
return GestureDetector(
|
||
onTap: onBackTap ?? () => Get.back(),
|
||
child: Container(
|
||
width: 48,
|
||
height: 48,
|
||
alignment: Alignment.center,
|
||
child: KrLocalImage(
|
||
imageName: 'hi-back-icon',
|
||
width: 48,
|
||
height: 48,
|
||
imageType: ImageType.svg,
|
||
),
|
||
),
|
||
);
|
||
}
|
||
// 如果两者都不显示,则返回一个空容器
|
||
return const SizedBox.shrink();
|
||
},
|
||
),
|
||
),
|
||
|
||
// 标题和副标题
|
||
if (title != null || subtitle != null)
|
||
Positioned(
|
||
top: topPadding +
|
||
(showBack ? 8 : 20), // 顶部空出状态栏高度,并根据是否有返回按钮调整间距
|
||
left: 0,
|
||
right: 0,
|
||
child: Column(
|
||
// 使用 Column 来垂直排列标题
|
||
crossAxisAlignment: CrossAxisAlignment.center, // 水平居中
|
||
children: [
|
||
if (title != null)
|
||
Text(
|
||
title!,
|
||
style: TextStyle(
|
||
color: Colors.black, // 在深色背景下使用白色
|
||
fontSize: 24,
|
||
fontWeight: FontWeight.bold,
|
||
),
|
||
),
|
||
if (subtitle != null)
|
||
Padding(
|
||
padding: EdgeInsets.only(top: 0), // 副标题与主标题之间的小间距
|
||
child: Text(
|
||
subtitle!,
|
||
style: TextStyle(
|
||
color: Colors.black, // 副标题使用带透明度的白色
|
||
fontSize: 14,
|
||
),
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
],
|
||
),
|
||
);
|
||
}
|
||
}
|