| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138 |
- import 'package:flutter/material.dart' hide Banner;
- import 'package:flutter_screenutil/flutter_screenutil.dart';
- import 'package:get/get.dart';
- import '../../../../utils/misc.dart';
- import '../../../data/models/banner/banner_list.dart';
- import '../../../widgets/ix_image.dart';
- import '../controllers/home_controller.dart';
- import '../../../extensions/widget_extension.dart';
- import '../../../../config/theme/theme_extensions/theme_extension.dart';
- /// 菜单列表组件
- /// 支持放在 SliverFillRemaining 中
- /// 排列规则:
- /// - 9个:3排,每排3个
- /// - 6个:2排,每排3个
- /// - 5个:2排,第一排3个,第二排2个
- /// - 4个:2排,每排2个
- /// - 3个:1排,每排3个
- /// - 2个:1排,每排2个
- /// - 1个:1排,占满
- class MenuList extends StatelessWidget {
- const MenuList({super.key});
- /// 根据数量计算每排的布局
- /// 返回一个二维列表,每个子列表表示一排的 Banner
- List<List<Banner>> _calculateLayout(List<Banner> items) {
- final count = items.length.clamp(0, 9);
- if (count == 0) return [];
- switch (count) {
- case 1:
- return [items.sublist(0, 1)];
- case 2:
- return [items.sublist(0, 2)];
- case 3:
- return [items.sublist(0, 3)];
- case 4:
- return [items.sublist(0, 2), items.sublist(2, 4)];
- case 5:
- return [items.sublist(0, 3), items.sublist(3, 5)];
- case 6:
- return [items.sublist(0, 3), items.sublist(3, 6)];
- case 7:
- return [items.sublist(0, 3), items.sublist(3, 6), items.sublist(6, 7)];
- case 8:
- return [items.sublist(0, 3), items.sublist(3, 6), items.sublist(6, 8)];
- case 9:
- default:
- return [items.sublist(0, 3), items.sublist(3, 6), items.sublist(6, 9)];
- }
- }
- @override
- Widget build(BuildContext context) {
- final controller = Get.find<HomeController>();
- return Obx(() {
- if (controller.nineBannerList.isEmpty) {
- return const SizedBox.shrink();
- }
- final layout = _calculateLayout(controller.nineBannerList);
- return Column(
- mainAxisSize: MainAxisSize.min,
- children: layout.asMap().entries.map((entry) {
- final rowIndex = entry.key;
- final rowItems = entry.value;
- return Padding(
- padding: EdgeInsets.only(top: rowIndex > 0 ? 8.w : 0),
- child: _buildRow(rowItems, controller),
- );
- }).toList(),
- );
- });
- }
- /// 构建一排菜单项
- Widget _buildRow(List<Banner> items, HomeController controller) {
- return Row(
- children: items.asMap().entries.map((entry) {
- final index = entry.key;
- final banner = entry.value;
- return Expanded(
- child: Padding(
- padding: EdgeInsets.only(left: index > 0 ? 8.w : 0),
- child: _buildMenuItem(banner, controller),
- ),
- );
- }).toList(),
- );
- }
- /// 构建单个菜单项
- Widget _buildMenuItem(Banner banner, HomeController controller) {
- final isLight = ReactiveTheme.isLightTheme;
- return GestureDetector(
- onTap: () => controller.onBannerTap(banner),
- child: Container(
- height: 56.w,
- decoration: BoxDecoration(
- color: Get.reactiveTheme.cardColor,
- borderRadius: BorderRadius.circular(10.r),
- border: isLight
- ? Border.all(color: Get.reactiveTheme.dividerColor, width: 1.w)
- : null,
- ),
- child: Column(
- mainAxisAlignment: MainAxisAlignment.center,
- children: [
- // 图标(网络图片)
- IXImage(
- source: banner.img ?? '',
- width: 20.w,
- height: 20.w,
- sourceType: ImageSourceType.network,
- ),
- 4.verticalSpaceFromWidth,
- // 标题
- Text(
- banner.title ?? '',
- textAlign: TextAlign.center,
- maxLines: 1,
- overflow: TextOverflow.ellipsis,
- style: TextStyle(
- fontSize: 13.sp,
- height: 1.4,
- color: Get.theme.hintColor,
- fontWeight: FontWeight.w500,
- ),
- ),
- ],
- ),
- ).withClickCursor(isDesktop),
- );
- }
- }
|