Search code examples
flutternavigationgesturetabbarflutter-pageview

Handle swipe of PageViewer Programmatically in TabBar - Flutter


I have Implemented TabBar with 3 Tabs. In 2nd Tab, the class contains PageViewer and its 3 Pages.

Now when I swipe from 1st tab to 3rd Tab, the order of page appearing is this:

1st Tab >> 
2nd Tab(PageViewer index 0th page) > (index 1st page) > (index 2nd page) >> 
3rd Tab.

But when I swipe from 3rd Tab to 1st Tab, the order of page appearing is this:

3rd Tab >>
2nd Tab(PageViewer index 0th page) >>
1st Tab.

What I want when I go from 3rd Tab to 1st Tab is:

3rd Tab >>
2nd Tab(PageViewer index 3rd page) > (index 2nd page) > (index 1st page) >>
1st Tab.

I am looking for solution that can have Code sample or Handling with gestures.


Solution

  • You can keep the track of the previous tab index. Use that to render the pageview's initial page. Refer following code sample.

    Tabbar included widget,

    class MyTabbedPage extends StatefulWidget {
      const MyTabbedPage({Key key}) : super(key: key);
      @override
      _MyTabbedPageState createState() => _MyTabbedPageState();
    }
    class _MyTabbedPageState extends State<MyTabbedPage> with SingleTickerProviderStateMixin {
      TabController _tabController;
      // keeps the track of tab index
      int _currentIndex = 0;
    
      @override
      void initState() {
        super.initState();
        _tabController = TabController(vsync: this, length: 3);
        _tabController.addListener(_handleTabSelection);
      }
    
      _handleTabSelection() {
        setState(() {
          if (_tabController.index != 1) _currentIndex = _tabController.index;
        });
      }
    
      @override
      void dispose() {
        _tabController?.dispose();
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: Scaffold(
            appBar: AppBar(
              bottom: TabBar(
                controller: _tabController,
                tabs: [
                  Tab(text: 'Tab 1'),
                  Tab(text: 'Tab 2'),
                  Tab(text: 'Tab 3'),
                ],
              ),
              title: const Text('Tabs Demo'),
            ),
            body: TabBarView(
              controller: _tabController,
              children: [
                Center(child: Text('Tab 1')),
                SecondTab(tabIndex: _currentIndex),
                Center(child: Text('Tab 3')),
              ],
            ),
          ),
        );
      }
    }
    

    Pageview included second tab widget,

    class SecondTab extends StatelessWidget {
      final int tabIndex; // tab index, which came from
      SecondTab({Key key, @required this.tabIndex}) : super(key: key);
    
      @override
      Widget build(BuildContext context) {
        // set initial page to first or last based on previous tab index
        final PageController controller = PageController(initialPage: tabIndex);
    
        return PageView(
          scrollDirection: Axis.horizontal,
          controller: controller,
          children: const <Widget>[
            Center(child: Text('First Page')),
            Center(child: Text('Second Page')),
            Center(child: Text('Third Page')),
          ],
        );
      }
    }
    

    I hope you can get an idea from this.