Home > Software design >  How to scroll to next tab using TabBarView into TabBarView
How to scroll to next tab using TabBarView into TabBarView

Time:02-22

I have TabBarView into TabBarView like following

//stful
late final TabController _controller1 = TabController( length: 3, vsync: this,initialIndex: 0);
 bottom:  TabBar(
  controller: _controller1,

 tabs: const [
 Tab(text: "Stful1",),
Tab(text: "Stfu2",),
Tab(text: "Stfu3",),

 ],
),

    TabBarView(
    controller: _controller1
    children: [
    Stful1()
    Stful2()
    Stful3()
   ]
   )

Now I have 3 Stfl Class and every Stful has also TabBarView with some tabs, I am going to use here Stful3 Tab to make it simple

Stful3() =>
    late final TabController _controller2 = TabController( length: 3, vsync: this,initialIndex: 0);
     bottom:  TabBar(
      controller: _controller2,
    
     tabs: const [
     Tab(text: "page1",),
    Tab(text: "page2",),
    Tab(text: "page3",),
    
     ],
    ),
    
        TabBarView(
        controller: _controller2
        children: [
        page1()
        page2()
        page3()
       ]
       )

Now lets say i am in page 1 and scrolling free with page1 and page3 but when i access to extent swip right or left where there is no tabs in current TabBarView it does not moving me to other tabs which they are in the main TabBarView .

does it possible in flutter frame work ? How can achieve this ?

EDIT

here is the full code

import 'package:flutter/material.dart';

class MyMainTabVarView extends StatefulWidget {
  const MyMainTabVarView({Key? key}) : super(key: key);

  @override
  _MyMainTabVarViewState createState() => _MyMainTabVarViewState();
}

class _MyMainTabVarViewState extends State<MyMainTabVarView> with SingleTickerProviderStateMixin{

  late final TabController controllerForMainTabVarView = TabController( length: 3, vsync: this,initialIndex: 0 );

  @override
  Widget build(BuildContext context) {
    return Scaffold(

      backgroundColor: Colors.blue,
      body: Column(
        children:  [
          Expanded(
            child: TabBarView(
              controller: controllerForMainTabVarView,
              children: const [
                MyStful1(),
                MyStful2(),
                MyStful3(),
              ],
            ),
          ),
          TabBar( // here i am use TabBar at the bottom of the screen instead of bottom Navigation Bar
            controller:controllerForMainTabVarView,
            tabs: const [
              Tab(text: "My Stful 1",),
              Tab(text: "My Stful 2",),
              Tab(text: "My Stful 3",),
            ],
          )
        ],
      ),
    );
  }
}



class MyStful1 extends StatefulWidget {
  const MyStful1({Key? key}) : super(key: key);

  @override
  _MyStful1State createState() => _MyStful1State();
}

class _MyStful1State extends State<MyStful1> with SingleTickerProviderStateMixin{

  late final TabController controllerForMyStful1 = TabController( length: 2, vsync: this,initialIndex: 0 );

  @override
  Widget build(BuildContext context) {
    return  Scaffold(
      appBar: AppBar(
        bottom: TabBar(
          controller:controllerForMyStful1,
          tabs: const [
            Tab(text: "Page1",),
            Tab(text: "Page2",),
          ],
        ),
      ),
      body: TabBarView(
        controller: controllerForMyStful1,
        children: const [
          Center(child: Text('Page1')),
          Center(child: Text('Page2')),
        ],
      ),
    );
  }
}



class MyStful2 extends StatefulWidget {
  const MyStful2({Key? key}) : super(key: key);

  @override
  _MyStful2State createState() => _MyStful2State();
}

class _MyStful2State extends State<MyStful2> with SingleTickerProviderStateMixin{

  late final TabController controllerForMyStful2 = TabController( length: 2, vsync: this,initialIndex: 0 );

  @override
  Widget build(BuildContext context) {
    return  Scaffold(
      appBar: AppBar(
        bottom: TabBar(
          controller:controllerForMyStful2,
          tabs: const [
            Tab(text: "Page1",),
            Tab(text: "Page2",),
          ],
        ),
      ),
      body: TabBarView(
        controller: controllerForMyStful2,
        children: const [
          Center(child: Text('Page1')),
          Center(child: Text('Page2')),
        ],
      ),
    );
  }
}


class MyStful3 extends StatefulWidget {
  const MyStful3({Key? key}) : super(key: key);

  @override
  _MyStful3State createState() => _MyStful3State();
}

class _MyStful3State extends State<MyStful3>with SingleTickerProviderStateMixin {

  late final TabController controllerForMyStful3 = TabController( length: 2, vsync: this,initialIndex: 0 );

  @override
  Widget build(BuildContext context) {
    return  Scaffold(
      appBar: AppBar(
        bottom: TabBar(
          controller:controllerForMyStful3,
          tabs: const [
            Tab(text: "Page1",),
            Tab(text: "Page2",),
          ],
        ),
      ),
      body: TabBarView(
        controller: controllerForMyStful3,
        children: const [
          Center(child: Text('Page1')),
          Center(child: Text('Page2')),
        ],
      ),
    );
  }
}

CodePudding user response:

This logic can be simplified using PageView, same approach can apply on other widgets like IndexedStack.

Full snippet on dartPad.

class MyMainTabVarView extends StatefulWidget {
  const MyMainTabVarView({Key? key}) : super(key: key);

  @override
  _MyMainTabVarViewState createState() => _MyMainTabVarViewState();
}

class _MyMainTabVarViewState extends State<MyMainTabVarView>
    with TickerProviderStateMixin {
  late final TabController controllerForMainTabVarView =
      TabController(length: 3, vsync: this, initialIndex: 0);
  late final TabController topTabBarController =
      TabController(length: 2, vsync: this, initialIndex: 0);

  late PageController pageController = PageController();

  onPageChange(int index) {
    debugPrint("page num $index");
    controllerForMainTabVarView.animateTo(
      index ~/ 2,
      duration: const Duration(milliseconds: 400),
      curve: Curves.ease,
    );
    topTabBarController.animateTo(
      index % 2,
      duration: const Duration(milliseconds: 400),
      curve: Curves.ease,
    );

    setState(() {});
  }

  void navigation(bool isTopController) {
    //skip 1st build
    WidgetsBinding.instance?.addPostFrameCallback((timeStamp) {
      int mainTabBarIndex = controllerForMainTabVarView.index;
      int topTabBarIndex = topTabBarController.index;

      /// switch to TopTabBar index=0
      if (!isTopController) {
        topTabBarIndex = 0;
        topTabBarController.index = 0;
      }
      debugPrint("main $mainTabBarIndex top $topTabBarIndex");

      pageController.animateToPage(
        topTabBarIndex   mainTabBarIndex * 2,
        duration: const Duration(milliseconds: 400),
        curve: Curves.ease,
      );
      setState(() {});
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.blue,
      body: Column(
        children: [
          TabBar(
              controller: topTabBarController,
              tabs: const [
                Tab(text: "Page1"),
                Tab(text: "Page2"),
              ],
              onTap: (_) {
                navigation(true);
              }),
          Expanded(
            child: Container(
              color: Theme.of(context).scaffoldBackgroundColor,
              child: PageView(
                controller: pageController,
                onPageChanged: onPageChange,
                children: const [
                  Center(child: Text(' MyStful1 Page1')),
                  Center(child: Text(' MyStful1 Page2')),
                  Center(child: Text(' MyStful2 Page1')),
                  Center(child: Text(' MyStful2 Page2')),
                  Center(child: Text(' MyStful3 Page1')),
                  Center(child: Text(' MyStful3 Page2')),
                ],
              ),
            ),
          ),
          TabBar(
            // here i am use TabBar at the bottom of the screen instead of bottom Navigation Bar
            controller: controllerForMainTabVarView,
            onTap: (_) {
              navigation(false);
            },
            tabs: const [
              Tab(
                text: "My Stful 1",
              ),
              Tab(
                text: "My Stful 2",
              ),
              Tab(
                text: "My Stful 3",
              ),
            ],
          )
        ],
      ),
    );
  }
}
  • Related