Ems
Ems

Reputation: 155

Is there a way to add listeners in DefaultTabController?

I have been trying to add listeners when using DefaultTabController. However, every time I add a TabController in order to get the current index in either TabBar and TabBarView, I lose sync between them.

This is my code below:

  @override
  Widget build(BuildContext context) {
    return new DefaultTabController(
      length: subPages.length,
      child: new Scaffold(
        appBar: appBar('homepage'),
        body: new Center(
          child: new NestedScrollView(
            headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
              return <Widget>[
                new SliverAppBar(
                  backgroundColor: Colors.white,
                  title: new TabBar(
                    labelColor: Colors.black,
                    indicatorColor: Colors.black,
                    labelStyle: new TextStyle(fontWeight: FontWeight.bold),
                    tabs: subPages.map((String str) => new Tab(text: str)).toList(),
                  ),
                ),
              ];
            },
            body: new TabBarView(
              children: subPages.map((String str) {
                return new ListView(
                  padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 16.0),
                  children: subPages.map((String str) {
                    return new Padding(
                      padding: const EdgeInsets.symmetric(vertical: 8.0),
                      child: new Text(str),
                    );
                  }).toList(),
                );
              }).toList(),
            ),
          ),
        ),
        floatingActionButton: new FloatingActionButton(
          backgroundColor: Colors.black,
          onPressed: null,
          tooltip: 'Increment',
          child: new Icon(Icons.add),
        ),
      ),
    );
  }

Upvotes: 7

Views: 5272

Answers (2)

周左左
周左左

Reputation: 372

  1. Define a tabController and a listener (once changing tab, it will be triggered twice)
class _ScreenState extends State<Screen> with SingleTickerProviderStateMixin {
  late TabController tabController;

  @override
  void initState() {
    super.initState();
    this.tabController = TabController(length: 3, vsync: this);
    this.tabController.addListener(() {
      if (this.tabController.indexIsChanging) {
        print(this.tabController.index);
        print(this.tabController.previousIndex);
      }
    });
  }
}
  1. Pass it to the TabBar and TabBarView, like:
TabBar(
  controller: this.tabController,
  tabs: [
   Tab(text: "0"),
   Tab(text: "1"),
   Tab(text: "2"),
  ],
)

TabBarView(controller: this.tabController, children: [...])

Upvotes: 1

Spixy
Spixy

Reputation: 313

I use this:

new DefaultTabController(
  child: Builder(
    builder: (context) {
   
      final tabController = DefaultTabController.of(context)!;
      tabController.addListener(() {
        print("New tab index: ${tabController.index}");
      });
    
      return Scaffold(
        ...
      );
    }
  ),
);

Upvotes: 8

Related Questions