TabBarView 或 IndexedStack 用于 BottomNavigationBar - Flutter
Posted
技术标签:
【中文标题】TabBarView 或 IndexedStack 用于 BottomNavigationBar - Flutter【英文标题】:TabBarView or IndexedStack for BottomNavigationBar - Flutter 【发布时间】:2020-08-08 09:42:56 【问题描述】:在颤动中做底部导航栏的最佳方法是什么?
根据Getting to the Bottom of Navigation in Flutter,flutter 团队使用IndexedStack
和Offstage
在用户更改选项卡时显示小部件,但我看到TabBarView
有另一种方法可以通过简单的幻灯片在小部件之间切换动画并保持每个小部件的滚动状态
那么IndexedStack
+ Offstage
和TabBarView
之间有什么区别?我应该使用flutter_bloc
还是只使用setState()
来更改当前选项卡的最佳方法是什么?
【问题讨论】:
【参考方案1】:概览
嗯,在 Flutter 中实现BottomNavigationBar
的方法有很多。
但是使用IndexedStack
方法会在开始时创建BottomNavigationBar
的所有屏幕。这可以使用TabBarView
修复。
以下是我使用CupertinoTabBar
和PageView
在我的应用程序中实现BottomNavigationBar
的方法,因为它在开始时只会显示一个屏幕。并且还使用AutomaticKeepAliveMixin
,因为它不会让屏幕再次重新创建。
关键点
PageView
和 PageController
可以轻松地在屏幕之间切换。
AutomaticKeepAliveClientMixin
不允许重新创建屏幕,因此无需使用 IndexedStack
。
在更改currentIndex
时,使用Provider
和Consumer
仅重新创建CupertinoTabBar
。而不是使用setState()
,因为它会重新创建整个屏幕,让所有小部件都得到重建。但这里使用Provider
仅重新创建TabBar
。
代码示例
主页 (
BottomNavigtionBar
)
class HomeScreen extends StatefulWidget
@override
_HomeScreenState createState() => _HomeScreenState();
class _HomeScreenState extends State<HomeScreen>
PageController _pageController;
@override
void initState()
_pageController = PageController();
super.initState();
@override
void dispose()
_pageController.dispose();
super.dispose();
@override
Widget build(BuildContext context)
return Scaffold(
// Wrapping the CupertinoTabBar in Consumer so that It only get
// recreated.
bottomNavigationBar: Consumer<HomeVM>(
builder: (context, model, child)
return CupertinoTabBar(
backgroundColor: Colors.white10,
currentIndex: model.currentPage,
onTap: (index)
index == model.currentPage
? print('same screen')
: _pageController.jumpToPage(
index,
);
model.changePage(index);
,
items: bottomNavItems);
,
),
body:ChangeNotifierProvider(
create: (_) => locator<HelpVM>(),
child: SafeArea(
top: false,
child: PageView(
controller: _pageController,
physics: NeverScrollableScrollPhysics(),
children: <Widget>[
FrontScreen(),
WorkRootScreen(),
HelpScreen(),
AccountScreen(),
],
),
),
),
);
const List<BottomNavigationBarItem> bottomNavItems =
<BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: const Icon(
FontAwesomeIcons.home,
),
),
//...... bottomNavigationBarItems
];
HomeVM(使用
Provider
更改索引并仅使用Consumer
重新创建TabBar
)
class HomeVM extends ChangeNotifier
int _currentPage = 0;
int get currentPage => _currentPage;
void changePage(int index)
this._currentPage = index;
notifyListeners();
FrontScreen(这里我们使用
AutomaticKeepAliveClientMixin
通过不重新创建小部件来保留状态)
class FrontScreen extends StatefulWidget
@override
_FrontScreenState createState() => _FrontScreenState();
class _FrontScreenState extends State<FrontScreen>
with AutomaticKeepAliveClientMixin
@override
Widget build(BuildContext context)
// VIMP to Add this Line.
super.build(context);
return SafeArea(
// Your Screen Code
);
@override
bool get wantKeepAlive => true;
【讨论】:
以上是关于TabBarView 或 IndexedStack 用于 BottomNavigationBar - Flutter的主要内容,如果未能解决你的问题,请参考以下文章
带有 IndexedStack 的 AnimatedSwitcher