底部导航
使用 LazyLoadIndexedStack 配合 BottomNavigationBar实现程序的导航页
flutter pub add lazy_load_indexed_stack
|
创建root_page.dart
维护导航页
root_page.dartimport 'package:e_book_clone/pges/home/home.dart'; import 'package:flutter/material.dart'; import 'package:lazy_load_indexed_stack/lazy_load_indexed_stack.dart';
class RootPage extends StatefulWidget { const RootPage({super.key});
@override State<RootPage> createState() => _RootPageState(); }
class _RootPageState extends State<RootPage> { int _currentIndex = 0;
@override Widget build(BuildContext context) { var bg = Theme.of(context).colorScheme.surface; return Scaffold( appBar: AppBar( elevation: 0, toolbarHeight: 0, backgroundColor: bg, surfaceTintColor: bg, ), backgroundColor: bg, bottomNavigationBar: _getBottomNavigator(context), body: LazyLoadIndexedStack( index: _currentIndex, children: const [ HomePage(), Center(child: Text('1')), Center(child: Text('2')), Center(child: Text('3')), ], ), ); }
Widget _getBottomNavigator(BuildContext context) { return BottomNavigationBar( currentIndex: _currentIndex, onTap: (index) { setState(() { _currentIndex = index; }); }, items: List.generate( 4, (index) { return BottomNavigationBarItem( label: '$index', icon: const Icon(Icons.abc), ); }, ), ); } }
|
导航页刷新方案
使用全局状态来管理切换的下标,如果在当前页面点击跳转到当前页面的底部导航按钮,代表刷新页面。
状态管理
使用Provider维护底部导航栏页下标,创建bottom_nav_provider.dart
文件
bottom_nav_provider.dartclass BottomNavProvider with ChangeNotifier { int _currentIndex = 0; Map<int, Function()?> refreshFuncs = {}; int get currentIndex => _currentIndex;
set currentIndex(int currentIndex) { _currentIndex = currentIndex; notifyListeners(); }
void refresh(int index) { refreshFuncs[index]?.call(); }
void setIndex(int index) { currentIndex = index; } }
|
修改导航页面,监听下标,同时判断是否是二次点击页面,即已经在当前页面时,再次点击导航到当前页面。
代码中用到的底部导航组件
flutter pub add salomon_bottom_bar
|
import 'package:e_book_clone/json/root_app_json.dart'; import 'package:e_book_clone/pages/douban_read/douban_read_page.dart'; import 'package:e_book_clone/pages/home/home_page.dart'; import 'package:e_book_clone/pages/my_book/my_book_page.dart'; import 'package:e_book_clone/pages/ebook_store/store_page.dart'; import 'package:e_book_clone/pages/bottom_nav_provider.dart'; import 'package:flutter/material.dart'; import 'package:lazy_load_indexed_stack/lazy_load_indexed_stack.dart'; import 'package:provider/provider.dart'; import 'package:salomon_bottom_bar/salomon_bottom_bar.dart';
class RootPage extends StatelessWidget { const RootPage({super.key});
@override Widget build(BuildContext context) { var bg = Theme.of(context).colorScheme.surface; return Scaffold( appBar: AppBar( elevation: 0, toolbarHeight: 0, backgroundColor: bg, surfaceTintColor: bg, ), backgroundColor: bg, bottomNavigationBar: _getBottomNavigator(context), body: LazyLoadIndexedStack( index: Provider.of<BottomNavProvider>(context).currentIndex, children: const [ HomePage(pageIndex: 0), DoubanReadPage(pageIndex: 1), StorePage(pageIndex: 2), MyBookPage(pageIndex: 3), ], ), ); }
Widget _getBottomNavigator(BuildContext context) { var bottomNavProvider = Provider.of<BottomNavProvider>(context, listen: false); return SalomonBottomBar( currentIndex: Provider.of<BottomNavProvider>(context).currentIndex, onTap: (index) { if (bottomNavProvider.currentIndex == index) { bottomNavProvider.refresh(index); } else { bottomNavProvider.currentIndex = index; } }, items: List.generate( rootAppJson.length, (index) { return SalomonBottomBarItem( selectedColor: Theme.of(context).colorScheme.onSurface, unselectedColor: Theme.of(context).colorScheme.inversePrimary, icon: Icon(rootAppJson[index]['icon']), title: Text(rootAppJson[index]['text']), ); }, ), ); } }
|
初始化刷新方法
当再次点击时,调用了刷新方法,该方法接受一个下标,即页面下标。执行对应页面的刷新方法,所以我们需要在页面初始化时将刷新方法添加到refreshFuncs
中。
Map<int, Function()?> refreshFuncs = {};
void refresh(int index) { refreshFuncs[index]?.call(); }
|
以HomePage
为案例,代码如下
home/home_page.dartimport 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:e_book_clone/pages/home/home_vm.dart';
class HomePage extends StatefulWidget { final int pageIndex; const HomePage({super.key, required this.pageIndex});
@override State<HomePage> createState() => _HomePageState(); }
class _HomePageState extends State<HomePage> { final HomeViewModel _viewmodel = HomeViewModel();
@override void initState() { super.initState(); refreshPage(); Future.microtask(() { Provider.of<BottomNavProvider>(context, listen: false) .refreshFuncs[widget.pageIndex] = refreshPage; }); }
void refreshPage() { _viewmodel.getPageData(); }
@override Widget build(BuildContext context) { return ChangeNotifierProvider<HomeViewModel>.value( value: _viewmodel, child: Scaffold( backgroundColor: Theme.of(context).colorScheme.surface, body: _getBody(), ), ); } Widget _getBody() { return const Center(child: Text('HomePage')); } }
|