简体   繁体   中英

Flutter - How to correctly delete a tab in a TabBarView

I'm using TabBarView to create a browser-like multi-tab application with dynamic tab creation. I've been following this answer . However I run into a quite bizzare problem when trying to delete a tab. Since I'm a beginner, I'm not sure if I did the wrong way or it is a Flutter bug.

Overview of this problem: If there remains two tabs in TabBarView, and you deleted the second tab while you are viewing it , TabBarView throws a exception, complaining that it can not perform scroll animation when item number < 2. However, this exception keeps coming up even if I switched tab in advance in the function. And this exception screws tab management from that point on.

I'd really appreciate if someone can show me the correct way of implementing a dynamic tab system.

The demo code is as follows. The code is complete and ready to run. Create a few tabs, then delete them from back to front . An exception will occur when you delete the second last tab. After that the tab system will behave like a mess.

import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
  @override MyAppState createState() => MyAppState();
}
class MyAppState extends State<MyApp> with TickerProviderStateMixin {
  List<Tab> tabs = [];TabController tabController;var count = 1;
  void newTab() {
    setState(() {
      tabs.add(Tab(text: '$count',));count++;
      tabController = TabController(length: tabs.length, vsync: this);
    });
  }
  void closeCurrentTab() {
    setState(() {
      //  A bunch of if-statement..........
      //  Even if you switch the tab before deletion, the error still occur.
      //tabController.animateTo(tabController.index-1);
      tabs.removeAt(tabController.index);
      tabController = TabController(length: tabs.length, vsync: this);
    });
  }
  @override void initState() {
    super.initState();
    tabs.add(Tab(text: '0',));
    tabController = TabController(length: tabs.length, vsync: this);
  }
  @override void dispose() {
    tabController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          actions: <Widget>[
            IconButton(icon: Icon(Icons.add), onPressed: newTab),
            IconButton(icon: Icon(Icons.close), onPressed: closeCurrentTab,)
          ],
          bottom: TabBar(controller: tabController, tabs: tabs.map((tab) => tab).toList()),// A trick to trigger TabBar rebuild.
        ),
        body: TabBarView(controller: tabController, children: tabs.map((tab) => Text(tab.text)).toList()),
      ),
    );
  }
}

It appears to me that the scroll animation after deletion is performed regardless of TabController.animateTo().

Well it turns out to be a flutter widget bug. It should not throw this exception when deleting tabs.

As reported in this Github issue . It should be fixed sometime in the future.

Right now I'm using PageView as an alternative. PageView works just fine.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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