fix(home): 修正首页分类与卡片布局

This commit is contained in:
Zhou Weidong committed 2026-10-22 18:14:33 +08:00
1 parent 10477562d4
commit aa4870cce6
14 files changed
+573 -459

No files matched your search

+78 -61
View File
@@ -7,14 +7,25 @@ import '../../../core/theme/app_colors.dart';
import '../../../core/theme/app_dimens.dart';
import '../../../l10n/app_localizations.dart';
enum HomePrimaryTab {
featured,
newReleases,
categories,
ranking,
costume,
community,
}
class HomeGridCategoryShortcut {
const HomeGridCategoryShortcut({
required this.label,
required this.categoryName,
required this.tab,
});
final String label;
final String categoryName;
final HomePrimaryTab tab;
}
class HomeGridTagOption {
@@ -29,18 +40,12 @@ class HomeGridCallbacks {
required this.onSearch,
required this.onOpenVip,
required this.onOpenWallet,
required this.onOpenNewReleases,
required this.onOpenCategories,
required this.onOpenRanking,
required this.onOpenFilter,
});
final VoidCallback onSearch;
final VoidCallback onOpenVip;
final VoidCallback onOpenWallet;
final VoidCallback onOpenNewReleases;
final VoidCallback onOpenCategories;
final VoidCallback onOpenRanking;
final VoidCallback onOpenFilter;
}
@@ -50,9 +55,9 @@ class HomeGridHeader extends StatelessWidget {
required this.callbacks,
required this.categories,
required this.tags,
required this.selectedCategory,
required this.selectedPrimary,
required this.selectedTag,
required this.onCategorySelected,
required this.onPrimarySelected,
required this.onTagSelected,
this.walletBadge,
});
@@ -60,9 +65,9 @@ class HomeGridHeader extends StatelessWidget {
final HomeGridCallbacks callbacks;
final List<HomeGridCategoryShortcut> categories;
final List<HomeGridTagOption> tags;
final String? selectedCategory;
final HomePrimaryTab selectedPrimary;
final String? selectedTag;
final ValueChanged<String?> onCategorySelected;
final ValueChanged<HomePrimaryTab> onPrimarySelected;
final ValueChanged<String?> onTagSelected;
final int? walletBadge;
@@ -71,6 +76,8 @@ class HomeGridHeader extends StatelessWidget {
final l10n = AppLocalizations.of(context)!;
return Column(
key: const Key('home-grid-header'),
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [_searchRow(l10n), _primaryRow(l10n), _tagRow(l10n)],
);
}
@@ -84,6 +91,8 @@ class HomeGridHeader extends StatelessWidget {
AppDimens.spaceSm,
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Expanded(
child: InkWell(
@@ -210,37 +219,38 @@ class HomeGridHeader extends StatelessWidget {
horizontal: AppDimens.feedPageHorizontal,
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
_primaryItem(
key: const Key('home-section-featured'),
label: l10n.homeSectionFeatured,
selected: selectedCategory == null,
onTap: () => onCategorySelected(null),
tab: HomePrimaryTab.featured,
),
_primaryItem(
key: const Key('home-section-new'),
label: l10n.homeSectionNew,
selected: false,
onTap: callbacks.onOpenNewReleases,
tab: HomePrimaryTab.newReleases,
),
_primaryItem(
key: const Key('home-section-categories'),
label: l10n.homeSectionCategories,
selected: false,
onTap: callbacks.onOpenCategories,
tab: HomePrimaryTab.categories,
),
_primaryItem(
key: const Key('home-section-ranking'),
label: l10n.homeSectionRanking,
selected: false,
onTap: callbacks.onOpenRanking,
tab: HomePrimaryTab.ranking,
),
for (final category in categories)
_primaryItem(
key: Key('home-section-category-${category.categoryName}'),
key: Key(
category.categoryName.isEmpty
? 'home-section-${category.tab.name}'
: 'home-section-category-${category.categoryName}',
),
label: category.label,
selected: selectedCategory == category.categoryName,
onTap: () => onCategorySelected(category.categoryName),
tab: category.tab,
),
],
),
@@ -250,38 +260,35 @@ class HomeGridHeader extends StatelessWidget {
Widget _primaryItem({
required Key key,
required String label,
required bool selected,
required VoidCallback onTap,
required HomePrimaryTab tab,
}) {
final selected = selectedPrimary == tab;
return InkWell(
key: key,
onTap: onTap,
onTap: () => onPrimarySelected(tab),
child: Padding(
padding: const EdgeInsets.only(right: AppDimens.spaceXl),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
label,
padding: const EdgeInsets.only(right: AppDimens.homePrimaryCategoryGap),
child: SizedBox(
height: AppDimens.homePrimaryRowHeight,
child: Align(
alignment: Alignment.bottomLeft,
child: AnimatedDefaultTextStyle(
key: Key('home-primary-label-${tab.name}'),
duration: AppDimens.homePrimaryTabAnimationDuration,
curve: Curves.easeOut,
style: TextStyle(
color: selected
? AppColors.navSelected
: AppColors.textTertiary,
fontSize: AppDimens.homePrimaryTabFont,
fontSize: selected
? AppDimens.homePrimaryTabSelectedFont
: AppDimens.homePrimaryTabFont,
fontWeight: selected ? FontWeight.w700 : FontWeight.w400,
letterSpacing: 0,
),
child: Text(label, textAlign: TextAlign.left),
),
const SizedBox(height: AppDimens.spaceXs),
Container(
height: AppDimens.homeSectionIndicator,
width: selected ? 20 : 0,
decoration: BoxDecoration(
color: AppColors.navSelected,
borderRadius: BorderRadius.circular(AppDimens.pillRadius),
),
),
],
),
),
),
);
@@ -296,16 +303,20 @@ class HomeGridHeader extends StatelessWidget {
AppDimens.spaceSm,
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Expanded(
child: SingleChildScrollView(
key: const Key('home-secondary-tags'),
scrollDirection: Axis.horizontal,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
for (final tag in tags) ...[
_tagChip(tag),
const SizedBox(width: AppDimens.spaceSm),
const SizedBox(width: AppDimens.homeSecondaryTagGap),
],
],
),
@@ -339,29 +350,35 @@ class HomeGridHeader extends StatelessWidget {
Widget _tagChip(HomeGridTagOption tag) {
final selected = selectedTag == tag.id;
final label = Text(
tag.label,
style: TextStyle(
color: selected ? AppColors.navSelected : AppColors.textTertiary,
fontSize: AppDimens.homeSecondaryTagFont,
fontWeight: selected ? FontWeight.w700 : FontWeight.w400,
letterSpacing: 0,
),
);
return InkWell(
key: Key('home-tag-${tag.id}'),
borderRadius: BorderRadius.circular(AppDimens.pillRadius),
onTap: () => onTagSelected(selected ? null : tag.id),
child: Container(
padding: const EdgeInsets.symmetric(
horizontal: AppDimens.spaceMd,
vertical: AppDimens.spaceSm,
),
decoration: BoxDecoration(
color: selected ? AppColors.contentSurface : AppColors.transparent,
borderRadius: BorderRadius.circular(AppDimens.pillRadius),
),
child: Text(
tag.label,
style: TextStyle(
color: selected ? AppColors.navSelected : AppColors.textTertiary,
fontSize: AppDimens.homeSecondaryTagFont,
fontWeight: selected ? FontWeight.w700 : FontWeight.w400,
letterSpacing: 0,
),
),
),
child: selected
? Container(
padding: const EdgeInsets.symmetric(
horizontal: AppDimens.spaceMd,
vertical: AppDimens.spaceSm,
),
decoration: BoxDecoration(
color: AppColors.contentSurface,
borderRadius: BorderRadius.circular(AppDimens.pillRadius),
),
child: label,
)
: Padding(
padding: const EdgeInsets.symmetric(vertical: AppDimens.spaceSm),
child: label,
),
);
}
}