Изменить номер значка - PullRequest
       6

Изменить номер значка

1 голос
/ 11 января 2020

В 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"),
    ));
  }
}

Ошибка

════════ Исключение, обнаруженное библиотекой виджетов ═════════════════════════════ ═════ Следующее утверждение было сгенерировано при построении NotificationListener: setState () вызвано в конструкторе: _MainPageState # 6ed53 (состояние жизненного цикла: создано, виджет не установлен)

Это происходит при вызове setState () для объект State для виджета, который еще не был вставлен в дерево виджетов. Нет необходимости вызывать setState () в конструкторе, поскольку предполагается, что состояние уже грязное при его первоначальном создании.

1 Ответ

2 голосов
/ 11 января 2020

Вместо того, чтобы пытаться вызвать функцию из родительского виджета для изменения значка при загрузке этого дочернего виджета, вы должны добавить прослушиватель в _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"),
      )
    );
  }
}

В вашем виджете Main:

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