一尘不染

Flutter:BottomNavigationBar在选项卡更改时重建页面

flutter

我在Flutter中的BottomNavigationBar出现问题。如果要更改标签,我想让页面保持活动状态。

这是我的实现

底部导航

class Home extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _HomeState();
  }
}

class _HomeState extends State<Home> {
  int _currentIndex = 0;
  List<Widget> _children;
  final Key keyOne = PageStorageKey("IndexTabWidget");

  @override
  void initState() {
    _children = [
      IndexTabWidget(key: keyOne),
      PlaceholderWidget(Colors.green),
      NewsListWidget(),
      ShopsTabWidget(),
      PlaceholderWidget(Colors.blue),
    ];
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(MyApp.appName),
        textTheme: Theme.of(context).textTheme.apply(
              bodyColor: Colors.black,
              displayColor: Colors.blue,
            ),
      ),
      body: _children[_currentIndex],
      bottomNavigationBar: BottomNavigationBar(
        onTap: onTabTapped,
        key: IHGApp.globalKey,
        fixedColor: Colors.green,
        type: BottomNavigationBarType.fixed,
        currentIndex: _currentIndex,
        items: [
          BottomNavigationBarItem(
            icon: Icon(Icons.home),
            title: Container(height: 0.0),
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.message),
            title: Container(height: 0.0),
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.settings),
            title: Container(height: 0.0),
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.perm_contact_calendar),
            title: Container(height: 0.0),
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.business),
            title: Container(height: 0.0),
          ),
        ],
      ),
    );
  }

  void onTabTapped(int index) {
    setState(() {
      _currentIndex = index;
    });
  }

  Column buildButtonColumn(IconData icon) {
    Color color = Theme.of(context).primaryColor;

    return Column(
      mainAxisSize: MainAxisSize.min,
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        Icon(icon, color: color),
      ],
    );
  }
}

这是我的索引页面(第一个标签):

class IndexTabWidget extends StatefulWidget {
  IndexTabWidget({Key key}) : super(key: key);

  @override
  State<StatefulWidget> createState() {
    return new IndexTabState();
  }
}

class IndexTabState extends State<IndexTabWidget>
    with AutomaticKeepAliveClientMixin {
  List<News> news = List();
  FirestoreNewsRepo newsFirestore = FirestoreNewsRepo();

  @override
  Widget build(BuildContext context) {
    return Material(
      color: Colors.white,
      child: new Container(
        child: new SingleChildScrollView(
          child: new ConstrainedBox(
            constraints: new BoxConstraints(),
            child: new Column(
              children: <Widget>[
                HeaderWidget(
                  CachedNetworkImageProvider(
                    'https://static1.fashionbeans.com/wp-content/uploads/2018/04/50-barbershop-top-savill.jpg',
                  ),
                  "",
                ),
                AboutUsWidget(),
                Padding(
                  padding: const EdgeInsets.all(16.0),
                  child: SectionTitleWidget(title: StringStorage.salonsTitle),
                ),
                StreamBuilder(
                  stream: newsFirestore.observeNews(),
                  builder: (context, snapshot) {
                    if (!snapshot.hasData) {
                      return CircularProgressIndicator();
                    } else {
                      news = snapshot.data;
                      return Column(
                        children: <Widget>[
                          ShopItemWidget(
                            AssetImage('assets/images/picture.png'),
                            news[0].title,
                            news[0],
                          ),
                          ShopItemWidget(
                            AssetImage('assets/images/picture1.png'),
                            news[1].title,
                            news[1],
                          )
                        ],
                      );
                    }
                  },
                ),
                Padding(
                  padding: const EdgeInsets.only(
                      left: 16.0, right: 16.0, bottom: 16.0),
                  child: SectionTitleWidget(title: StringStorage.galleryTitle),
                ),
                GalleryCategoryCarouselWidget(),
              ],
            ),
          ),
        ),
      ),
    );
  }

  @override
  bool get wantKeepAlive => true;
}

因此,如果我从索引选项卡切换到其他任何选项卡,然后再回到索引选项卡,则索引选项卡将始终重建。我对其进行了调试,发现在选项卡开关上总是会调用build函数。

你们能帮我解决这个问题吗?

非常感谢Albo


阅读 669

收藏
2020-08-13

共1个答案

一尘不染

以前的答案都没有为我解决。

切换选项卡时使页面保持活动状态的解决方案是将页面包装在 IndexedStack中

class Tabbar extends StatefulWidget {
  Tabbar({this.screens});

  static const Tag = "Tabbar";
  final List<Widget> screens;
  @override
  State<StatefulWidget> createState() {
  return _TabbarState();
  }
}

class _TabbarState extends State<Tabbar> {
  int _currentIndex = 0;
  Widget currentScreen;

  @override
  Widget build(BuildContext context) {
    var _l10n = PackedLocalizations.of(context);

    return Scaffold(
  body: IndexedStack(
    index: _currentIndex,
    children: widget.screens,
  ),
  bottomNavigationBar: BottomNavigationBar(
    fixedColor: Colors.black,
    type: BottomNavigationBarType.fixed,
    onTap: onTabTapped,
    currentIndex: _currentIndex,
    items: [
      BottomNavigationBarItem(
        icon: new Icon(Icons.format_list_bulleted),
        title: new Text(_l10n.tripsTitle),
      ),
      BottomNavigationBarItem(
        icon: new Icon(Icons.settings),
        title: new Text(_l10n.settingsTitle),
      )
    ],
  ),
);
  }

  void onTabTapped(int index) {
    setState(() {
      _currentIndex = index;
    });
  }
}
2020-08-13