merge: 首页图标区分实心选中态

This commit is contained in:
Zhou Weidong committed 2026-10-22 19:29:18 +08:00
commit 5860302ce7
6 files changed
+44 -12

No files matched your search

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

+6
View File
@@ -1156,3 +1156,9 @@ $ flutter test
- `AppRootTab` 新增可选 `assetPath`,首页使用 `assets/icon/film_reel.png`。
- 共享导航通过 `ColorFiltered + Image.asset` 按选中态着色,尺寸保持 26,缺图回退胶片 Material 图标。
- 推荐、追剧、我的图标不变;素材与测试断言同步,按当前流程未执行 analyze/test。
## 2026-10-22 首页选中态实心摄影机
- `AppRootTab` 新增 `selectedAssetPath`,首页选中使用 `film_reel_filled.png`,未选中使用描边版。
- 共享导航保持 `ColorFiltered(srcIn)` 与 26×26,缺图按选中态回退实心/描边胶片图标。
- 推荐、追剧、我的不变;测试断言同步,按当前流程未执行 analyze/test。
+8 -3
View File
@@ -15,12 +15,14 @@ class AppBottomNavItem {
required this.onTap,
this.selected = false,
this.assetPath,
this.selectedAssetPath,
});
final Key tabKey;
final IconData icon;
final IconData selectedIcon;
final String? assetPath;
final String? selectedAssetPath;
final String label;
final VoidCallback onTap;
final bool selected;
@@ -66,6 +68,9 @@ class _NavDestination extends StatelessWidget {
Widget build(BuildContext context) {
final color = item.selected ? AppColors.navSelected : unselectedColor;
final fallbackIcon = item.selected ? item.selectedIcon : item.icon;
final assetPath = item.selected
? item.selectedAssetPath ?? item.assetPath
: item.assetPath;
return Expanded(
child: Semantics(
button: true,
@@ -83,7 +88,7 @@ class _NavDestination extends StatelessWidget {
duration: const Duration(milliseconds: 160),
curve: Curves.easeOut,
scale: item.selected ? 1 : 0.96,
child: item.assetPath == null
child: assetPath == null
? Icon(
fallbackIcon,
size: AppDimens.navIcon,
@@ -92,12 +97,12 @@ class _NavDestination extends StatelessWidget {
: ColorFiltered(
colorFilter: ColorFilter.mode(color, BlendMode.srcIn),
child: Image.asset(
item.assetPath!,
assetPath,
width: AppDimens.navIcon,
height: AppDimens.navIcon,
fit: BoxFit.contain,
errorBuilder: (_, _, _) => Icon(
item.icon,
fallbackIcon,
size: AppDimens.navIcon,
color: color,
),
+7 -2
View File
@@ -7,14 +7,18 @@ import 'app_bottom_nav.dart';
/// 客户端根导航的固定顺序。
enum AppRootTab {
home(assetPath: 'assets/icon/film_reel.png'),
home(
assetPath: 'assets/icon/film_reel.png',
selectedAssetPath: 'assets/icon/film_reel_filled.png',
),
recommend(),
following(),
mine();
const AppRootTab({this.assetPath});
const AppRootTab({this.assetPath, this.selectedAssetPath});
final String? assetPath;
final String? selectedAssetPath;
}
extension AppRootTabUi on AppRootTab {
@@ -72,6 +76,7 @@ class AppRootBottomNav extends StatelessWidget {
icon: tab.icon,
selectedIcon: tab.selectedIcon,
assetPath: tab.assetPath,
selectedAssetPath: tab.selectedAssetPath,
label: tab.label(l10n),
selected: tab == selected,
onTap: () => onSelected(tab),
+12 -6
View File
@@ -181,8 +181,8 @@ void main() {
});
testWidgets('should_fallback_when_asset_icon_is_missing', (tester) async {
await tester.pumpWidget(
MaterialApp(
Widget navigation({required bool selected}) {
return MaterialApp(
home: Scaffold(
bottomNavigationBar: AppBottomNav(
items: [
@@ -191,17 +191,23 @@ void main() {
icon: Icons.theaters_outlined,
selectedIcon: Icons.theaters,
assetPath: 'assets/icon/missing_film_reel.png',
selectedAssetPath: 'assets/icon/missing_film_reel_filled.png',
label: 'Home',
selected: true,
selected: selected,
onTap: () {},
),
],
),
),
),
);
await tester.pumpAndSettle();
);
}
await tester.pumpWidget(navigation(selected: true));
await tester.pumpAndSettle();
expect(find.byIcon(Icons.theaters), findsOneWidget);
await tester.pumpWidget(navigation(selected: false));
await tester.pumpAndSettle();
expect(find.byIcon(Icons.theaters_outlined), findsOneWidget);
});
}
+11 -1
View File
@@ -235,7 +235,7 @@ void main() {
);
expect(
(selectedHomeImage.image as AssetImage).assetName,
'assets/icon/film_reel.png',
'assets/icon/film_reel_filled.png',
);
expect(
Size(selectedHomeImage.width!, selectedHomeImage.height!),
@@ -300,6 +300,16 @@ void main() {
.colorFilter,
const ColorFilter.mode(AppColors.navUnselected, BlendMode.srcIn),
);
final unselectedHomeImage = tester.widget<Image>(
find.descendant(
of: find.byKey(const Key('tab-home')),
matching: find.byType(Image),
),
);
expect(
(unselectedHomeImage.image as AssetImage).assetName,
'assets/icon/film_reel.png',
);
});
testWidgets('should_map_four_tabs_to_home_recommend_following_and_me', (