【问题标题】:TabBarView or IndexedStack for BottomNavigationBar - FlutterTabBarView 或 IndexedStack 用于 BottomNavigationBar - Flutter
【发布时间】:2020-08-08 09:42:56
【问题描述】:

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

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

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

【问题讨论】:

    标签: flutter flutter-navigation


    【解决方案1】:

    概览

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

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


    关键点

    • PageViewPageController 可以轻松地在屏幕之间切换。
    • 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 通过不重新创建小部件来保留状态)

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

    【讨论】:

      猜你喜欢
      • 2020-12-05
      • 1970-01-01
      • 2021-05-19
      • 2020-07-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-28
      相关资源
      最近更新 更多