初始化提交

This commit is contained in:
2025-09-23 16:23:15 +08:00
commit 877b18a70f
590 changed files with 53617 additions and 0 deletions
+54
View File
@@ -0,0 +1,54 @@
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:kaer_with_panels/app/modules/kr_login/views/kr_login_view.dart';
import 'package:kaer_with_panels/app/modules/kr_main/views/kr_tabbar_view.dart';
import 'package:kaer_with_panels/app/widgets/kr_local_image.dart';
import '../controllers/kr_main_controller.dart';
class KRMainView extends GetView<KRMainController> {
const KRMainView({super.key});
@override
Widget build(BuildContext context) {
final theme = Theme.of(context); // 获取当前主题
return Scaffold(
// 根据下标显示哪个页面
body: GetBuilder<KRMainController>(builder: (mc) {
return PageView(
children: mc.widgets,
controller: controller.pageController,
physics: const NeverScrollableScrollPhysics(),
);
}),
bottomNavigationBar: Obx(
() => KRCustomBottomNavBar(
backgroundColor: theme.scaffoldBackgroundColor,
currentIndex: controller.kr_currentIndex.value,
onTap: (i) => controller.kr_setPage(i),
items: [
KRCustomBottomNavBarItem(
imageName: "tab_home_n",
activeImageName: "tab_home_s",
),
KRCustomBottomNavBarItem(
imageName: "tab_invite_n",
activeImageName: "tab_invite_s",
),
KRCustomBottomNavBarItem(
imageName: "tab_statistics_n",
activeImageName: "tab_statistics_s",
),
KRCustomBottomNavBarItem(
imageName: "tab_my_n",
activeImageName: "tab_my_s",
),
],
),
),
);
}
}
+109
View File
@@ -0,0 +1,109 @@
import 'package:flutter/material.dart';
import 'package:kaer_with_panels/app/widgets/kr_local_image.dart';
/// 用来描述底部导航栏的每一项
class KRCustomBottomNavBarItem {
/// 未选中时的图片名称
final String imageName;
/// 选中时的图片名称(可选,不传则用同一张 imageName)
final String? activeImageName;
/// 标签(可选)
final String? label;
KRCustomBottomNavBarItem({
required this.imageName,
this.activeImageName,
this.label,
});
}
class KRCustomBottomNavBar extends StatelessWidget {
/// 传入当前选中的索引
final int currentIndex;
/// 导航栏的各个条目信息
final List<KRCustomBottomNavBarItem> items;
/// 点击某项时的回调
final ValueChanged<int> onTap;
/// 背景色
final Color backgroundColor;
/// 选中时 图标/文字 颜色
final Color selectedColor;
/// 未选中时 图标/文字 颜色
final Color unselectedColor;
/// 导航栏高度(不含安全区额外高度)
final double height;
/// 是否在内部自动使用 SafeArea
final bool useSafeArea;
const KRCustomBottomNavBar({
Key? key,
required this.currentIndex,
required this.items,
required this.onTap,
this.backgroundColor = Colors.white,
this.selectedColor = Colors.blue,
this.unselectedColor = Colors.grey,
this.height = 56.0,
this.useSafeArea = true,
}) : super(key: key);
@override
Widget build(BuildContext context) {
assert(items.isNotEmpty, 'The items list cannot be empty.');
assert(currentIndex >= 0 && currentIndex < items.length,
'The currentIndex must be within the bounds of the items list.');
Widget child = Container(
color: backgroundColor,
height: height,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: List.generate(items.length, (index) {
final item = items[index];
final bool isSelected = (index == currentIndex);
final iconName = isSelected
? (item.activeImageName ?? item.imageName)
: item.imageName;
final textColor = isSelected ? selectedColor : unselectedColor;
return Expanded(
child: InkWell(
onTap: () => onTap(index),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
KrLocalImage(
imageName: iconName,
height: 24,
width: 24,
),
if (item.label != null) ...[
const SizedBox(height: 4),
Text(
item.label!,
style: TextStyle(color: textColor, fontSize: 12),
),
],
],
),
),
);
}),
),
);
// 使用 SafeArea 包裹,避免底部被手势栏遮挡
return useSafeArea ? SafeArea(child: child) : child;
}
}