繁体   English   中英

TabBarView 或 IndexedStack 用于 BottomNavigationBar - Flutter

[英]TabBarView or IndexedStack for BottomNavigationBar - Flutter

在 flutter 中做底部导航栏的最佳方法是什么?

根据Getting to the Bottom of Navigation in Flutter flutter 团队使用IndexedStackOffstage在用户更改选项卡时显示小部件,但我看到TabBarView有另一种方法可以通过简单的幻灯片 Z6F1C25ED1523962B1BBF9 和保持每个小部件的滚动 state

那么IndexedStack + OffstageTabBarView什么区别呢? 我应该使用类似flutter_bloc还是只使用setState()来更改当前选项卡的最佳方法是什么?

概述

嗯,在Flutter中实现BottomNavigationBar的方法有很多。 但是使用IndexedStack方法会在开始时创建BottomNavigationBar的所有屏幕。 这可以使用TabBarView

这是我使用CupertinoTabBarPageView在我的应用程序中实现BottomNavigationBar的方法,因为它在开始时只会显示一个屏幕。 并且还使用AutomaticKeepAliveMixin ,因为它不会让屏幕再次被重新创建。


关键点

  • 带有PageControllerPageView ,您可以通过它轻松地在屏幕之间切换。
  • AutomaticKeepAliveClientMixin不允许重新创建屏幕,因此不需要使用IndexedStack
  • 更改currentIndex时,使用ProviderConsumer仅重新创建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通过不重新创建 Widget 来保留 state)

   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;
   }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM