更改徽章编号

Change badge number

在MainPage 中,它有2 个底部导航栏。一个是带有文字的图标,另一个是带有文字和徽章编号的图标。当我的应用程序启动时,徽章在第二个选项卡中显示 3。这很好用。

  class MainPage extends StatefulWidget {

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

  method(int num) => _MainPageState().showBadge(num);
}

class _MainPageState extends State<MainPage>
    with SingleTickerProviderStateMixin {
  int _selectedIndex = 0;
  int count = 0;
  TabController _tabController;
  PageController _pageController;

  @override
  void initState() {
    super.initState();

    _tabController = TabController(length: 5, vsync: this);
    _pageController = PageController(initialPage: _selectedIndex);

    showBadge(3);
  }

  void showBadge(int number) {
    setState(() {
      count = number;
    });
  }

  void onPageChange(int index) {
    setState(() {
      _selectedIndex = index;
    });
  }

  void _onItemTapped(int index) {
    _pageController.animateToPage(index,
        duration: kTabScrollDuration, curve: Curves.ease);
  }

  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      child: Scaffold(
        body: FixTabBarView(
            pageController: _pageController,
            onPageChange: onPageChange,
            tabController: _tabController,
            children: <Widget>[
              TabA(),
              TabB(),
            ]),
        bottomNavigationBar: BottomNavigationBar(
          type: BottomNavigationBarType.fixed,
          items: <BottomNavigationBarItem>[
            BottomNavigationBarItem(
                icon: Icon(Icons.A), title: Text('TabA')),
            BottomNavigationBarItem(
              icon: Stack(children: <Widget>[
                Icon(
                  Icons.B,
                ),
                Positioned(
                  top: 1.0,
                  right: 0.0,
                  child: Stack(
                    children: <Widget>[
                      Icon(Icons.brightness_1, size: 18, color: Colors.red),
                      Positioned(
                        top: 1.0,
                        right: 4.0,
                        child: new Text(count.toString(),
                            style: new TextStyle(
                                color: Colors.white,
                                fontSize: 15.0,
                                fontWeight: FontWeight.w500)),
                      )
                    ],
                  ),
                )
              ]),
              title: Text('TabB'),
            ),
          ],
          currentIndex: _selectedIndex,
          fixedColor: Colors.blue,
          onTap: _onItemTapped,
        ),
      ),
      onWillPop: () {},
    );
  }
}

单击选项卡 2 时,我希望徽章更改为 1,但它会引发错误。

  class TabB extends StatefulWidget {

  @override
  State<StatefulWidget> createState() => _TabBState();
}

class _TabBState extends State<TabB> {

  @override
  void initState() {
    super.initState();
    _bloc.callApi().then((onValue){
      MainPage().method(onValue);    // onValue is the number return from server
  });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
      title: Text("Tab 2"),
    ));
  }
}

错误

════════ Exception caught by widgets library ═══════════════════════════════════ The following assertion was thrown building NotificationListener: setState() called in constructor: _MainPageState#6ed53(lifecycle state: created, no widget, not mounted)

This happens when you call setState() on a State object for a widget that hasn't been inserted into the widget tree yet. It is not necessary to call setState() in the constructor, since the state is already assumed to be dirty when it is initially created.

与其尝试在加载子小部件时从父小部件调用函数来修改徽章,不如将侦听器添加到 _tabController 并在选择选项卡时更改徽章,如下所示:

@override
void initState() {
  super.initState();

  _tabController = TabController(length: 5, vsync: this);
  _tabController.addListener((){
    if(_tabController.index == 1){
      setState(() {
        showBadge(1);
      });
    }
  });

  _pageController = PageController(initialPage: _selectedIndex);

  showBadge(3);
}

确保为要匹配的标签页索引调整 if


在您的 TabB 上,您可以声明它接受 Function 作为其构造函数的一部分,然后调用该函数:

class TabB extends StatefulWidget {
  final Function showBadge;

  TabB({this.showBadge});

  @override
  State<StatefulWidget> createState() => _TabBState();
}

class _TabBState extends State<TabB> {

  @override
  void initState() {
    super.initState();
    _bloc.callApi().then((onValue){
      widget.showBadge(onValue);    // onValue is the number return from server
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Tab 2"),
      )
    );
  }
}

在您的主要小部件上:

FixTabBarView(
  pageController: _pageController,
  onPageChange: onPageChange,
  tabController: _tabController,
  children: <Widget>[
    TabA(),
    TabB(showBadge: showBadge,),
  ]
)