简体   繁体   English

如何在 BLOC 的 Flutter 中的 BottomNavigationBar 中设置 currentIndex?

[英]How to set currentIndex in BottomNavigationBar in Flutter from BLOC?

I would like to use a StatelessWidget with BottomNavigationBar which I would control from a BLOC.我想使用带有BottomNavigationBarStatelessWidget ,我将从 BLOC 控制它。 I can hook up the body of the Scaffold and onTap of the BottomNavigationBar to the BLOC (see the code).我可以将Scaffold主体BottomNavigationBar 的onTap连接到 BLOC(参见代码)。 But I do not understand how one can set the currentIndex of BottomNavigationBar from BLOC (from Observable).但我不明白如何从 BLOC(来自 Observable)设置BottomNavigationBarcurrentIndex

Is there any good solution or do I need to use StatefulWidget as in https://stackoverflow.com/a/53019841/936780 which is similar to my example.有什么好的解决方案,或者我是否需要像https://stackoverflow.com/a/53019841/936780一样使用StatefulWidget ,这与我的示例类似。

The BLOC code: BLOC 代码:

class Bloc { 
  final _currentTabSink = PublishSubject<int>();
  final _currentTabIndex = BehaviorSubject<int>();

  Observable<int> get currentTabIndex => _currentTabIndex.stream;
  Function(int) get setTabIndex => _currentTabSink.sink.add;

  Bloc() {
    _currentTabSink.stream.pipe(_currentTabIndex);
  }

  dispose() {
    _currentTabSink.close();
    _currentTabIndex.close();
  }
}

Widget code:小部件代码:

class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final bloc = Provider.of(context);

    final List<Widget> _children = [
      AaWidget(),
      BbWidget(),
      CcWidget(),
      DdWidget(),
      EeWidget()
    ];

    return Scaffold(
        appBar: AppBar(
          title: Text(Localizations.of(context).appName),
        ),
        body: setBody(_children, bloc), // hook to BLOC
        bottomNavigationBar: BottomNavigationBar(
          currentIndex: 1, // ?? how to hook up to BLOC ??
          onTap: (index) {
            bloc.setTabIndex(index); // hook to BLOC
            },
          items: [
            addAa(context),
            addBb(context),
            addCc(context),
            addDd(context),
            addEE(context),
          ],
        ));
  }

  Widget setBody(List<Widget> children, Bloc bloc) {
    return StreamBuilder(
      stream: bloc.currentTabIndex,
      builder: (context, AsyncSnapshot<int> snapshot) {
        if (snapshot.hasData) {
          return children[snapshot.data];
        }
      },
    );
  }

  ...
}

I think you would need to wrap your Scaffold in a StreamBuilder with an initial data set and then you can access the snapshot data.我认为您需要使用初始数据集将Scaffold包装在StreamBuilder ,然后才能访问快照数据。 Something like this (I had to make some changes to your code so it would build for me)像这样的东西(我必须对你的代码进行一些更改,以便为我构建)

class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final bloc = Bloc();

    final List<Widget> _children = [
      Container(color: Colors.blue, child: Center(child: Text("1"))),
      Container(color: Colors.red, child: Center(child: Text("2"))),
      Container(color: Colors.green, child: Center(child: Text("3"))),
      Container(color: Colors.yellow, child: Center(child: Text("4"))),
      Container(color: Colors.orange, child: Center(child: Text("5"))),
    ];

    return StreamBuilder<int>(
      stream: bloc.currentTabIndex,
      initialData: 0,
      builder: (BuildContext context, AsyncSnapshot<int> snapshot) {
        if (!snapshot.hasData) {
          return Container();
        }

        return Scaffold(
          appBar: AppBar(
            title: Text("Test"),
          ),
          body: _children[snapshot.data],
          bottomNavigationBar: BottomNavigationBar(
            currentIndex: snapshot.data,
            onTap: (index) {
              bloc.setTabIndex(index);
            },
            items: _children
                .map((child) => BottomNavigationBarItem(
                    icon: Icon(Icons.add),
                    title: Text("Test"),
                    backgroundColor: Colors.black))
                .toList(),
          ),
        );
      },
    );
  }
}

This works for me, the only downside here is that you will be rebuilding the AppBar unnecessarily every time the index changes.这对我有用,唯一的缺点是每次索引更改时您都会不必要地重建AppBar

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

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