如何根据页面主题更改Flutter中图标与导航栏的颜色
PageView页面切换时同步主题与导航栏/图标颜色实现方案
我需要在PageView中实现图标与导航栏颜色随页面主题变化的效果,项目包含5个页面,其中第2个页面(索引1)固定为深色主题,切换到该页面时,ScreenWrapper内所有元素的主题需同步变更。
修改后完整代码
import 'package:at_app1/features/post/presentation/create_post.dart'; import 'package:at_app1/features/post/presentation/home_page.dart'; import 'package:feather_icons/feather_icons.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; class ScreenWrapper extends StatefulWidget { const ScreenWrapper({super.key}); @override State<ScreenWrapper> createState() => _ScreenWrapperState(); } class _ScreenWrapperState extends State<ScreenWrapper> { int _currentIndex = 0; late ThemeData _currentTheme; // 初始化主题 @override void initState() { super.initState(); _currentTheme = ThemeData.light(); _updateSystemUI(_currentTheme.brightness); } // 更新系统状态栏与导航栏样式 void _updateSystemUI(Brightness brightness) { SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle( statusBarColor: Colors.transparent, statusBarIconBrightness: brightness == Brightness.dark ? Brightness.light : Brightness.dark, systemNavigationBarColor: brightness == Brightness.dark ? Colors.black : Colors.white, systemNavigationBarIconBrightness: brightness == Brightness.dark ? Brightness.light : Brightness.dark, )); } // 切换主题 void _switchTheme(int pageIndex) { setState(() { if (pageIndex == 1) { _currentTheme = ThemeData.dark(); } else { _currentTheme = ThemeData.light(); } _updateSystemUI(_currentTheme.brightness); }); } final _bottomNavigationBarItems = [ const BottomNavigationBarItem( icon: Icon(FeatherIcons.home), activeIcon: Icon(FeatherIcons.home, color: Colors.pink), label: '', ), const BottomNavigationBarItem( icon: Icon(FeatherIcons.users), activeIcon: Icon(FeatherIcons.users, color: Colors.blue), label: '', ), const BottomNavigationBarItem( icon: Icon(FeatherIcons.plusCircle), activeIcon: Icon(FeatherIcons.plusCircle, color: Colors.orange), label: '', ), const BottomNavigationBarItem( icon: Icon(FeatherIcons.heart), activeIcon: Icon(FeatherIcons.heart, color: Colors.purple), label: '', ), const BottomNavigationBarItem( icon: Icon(FeatherIcons.bookmark), activeIcon: Icon(FeatherIcons.bookmark, color: Colors.yellow), label: '', ), ]; final PageController _pageController = PageController(initialPage: 0); @override Widget build(BuildContext context) { return Theme( data: _currentTheme, child: Scaffold( extendBodyBehindAppBar: true, extendBody: true, body: Stack( alignment: Alignment.topCenter, children: [ PageView( controller: _pageController, onPageChanged: (newIndex) { setState(() => _currentIndex = newIndex); _switchTheme(newIndex); }, children: const [ HomePage(), CreatePostPage(), // FollowingPostPage(), // CameraExampleHome(), // NotificationPage(), // SavedPage(), ], ), Positioned( top: 0, left: 0, right: 0, child: AppBar( backgroundColor: Colors.transparent, leadingWidth: 50, leading: Padding( padding: EdgeInsets.only(left: MediaQuery.of(context).size.width * 0.05), child: GestureDetector( onTap: () {}, child: CircleAvatar(backgroundColor: Colors.grey), ), ), elevation: 0, iconTheme: IconThemeData(color: _currentTheme.brightness == Brightness.dark ? Colors.white : Colors.black), actions: [ Stack( alignment: Alignment.center, children: [ Icon(Icons.circle, color: Colors.red.withOpacity(0.7), size: 40), IconButton( onPressed: () {}, icon: const Icon(Icons.flag_outlined, size: 20, color: Colors.white), ), ], ), Padding( padding: EdgeInsets.only(right: MediaQuery.of(context).size.width * 0.03), child: Stack( alignment: Alignment.center, children: [ Icon(Icons.circle, color: Colors.yellow.withOpacity(0.7), size: 40), IconButton( onPressed: () {}, icon: const Icon(Icons.search, size: 20, color: Colors.white), ), ], ), ), ], ), ), ], ), bottomNavigationBar: Container( height: MediaQuery.of(context).size.height * 0.08, color: _currentTheme.brightness == Brightness.dark ? Colors.black : Colors.white, child: BottomNavigationBar( unselectedFontSize: 0, selectedFontSize: 0, iconSize: 30, currentIndex: _currentIndex, items: _bottomNavigationBarItems, type: BottomNavigationBarType.fixed, unselectedItemColor: _currentTheme.brightness == Brightness.dark ? Colors.grey[400] : Colors.grey[600], backgroundColor: Colors.transparent, elevation: 0, onTap: (index) { _pageController.animateToPage( index, duration: const Duration(milliseconds: 300), curve: Curves.ease, ); }, ), ), ), ); } }
关键修改说明
- 新增主题状态变量:通过
_currentTheme控制全局主题,初始化时设为浅色主题 - 系统UI同步更新:封装
_updateSystemUI方法,根据主题亮度自动切换状态栏、导航栏图标颜色与背景色 - 主题切换逻辑:在
onPageChanged中判断页面索引,切换至对应主题并触发状态更新 - 全局主题包裹:用
Theme组件包裹Scaffold,让内部所有子组件自动继承当前主题样式 - 导航栏适配:调整BottomNavigationBar的未选中图标颜色、背景色,跟随主题变化
- AppBar优化:设置
iconTheme让AppBar图标颜色随主题切换,保持视觉一致性
内容的提问来源于stack exchange,提问作者Ddd279
相关产品推荐
相关产品推荐

