1

I want to use DefaultTabController in the middle of the screen along with other widgets. There will be a widget before the TabBar. I managed to find an answer for this in SO. But the problem is I want to scroll the entire page. Provided answer only scroll the tab section. I added SingleChildScrollView by wrapping the entire thing. But that didn't work as that conflict with the Expanded widget.

Then I found another answer which uses CustomScrollView with slivers but again that only scroll the tab section not the entire screen.

Erroneous code with SingleChildScrollView: https://dartpad.dev/d380be0134d0c4e84b5dca87a58b3022

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
      debugShowCheckedModeBanner: false,
      home: SingleChildScrollView(
        child: Column(
          children: [
            SizedBox(height: 150, child: Text('Hey')),
            Expanded(child: ProfileTabBarNavigation()),
          ],
        ),
      ),
    );
  }
}

const String kArtwork = "Left";
const String kPastJobs = "Right";
const EdgeInsets kPaddingTabBar = EdgeInsets.all(5.0);
const Color kLightGrey = Colors.grey;

class ProfileTabBarNavigation extends StatelessWidget {
  final List<Tab> myTabs = <Tab>[
    const Tab(text: kArtwork),
    const Tab(text: kPastJobs)
  ];
  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: 2,
      initialIndex: 0,
      child: Scaffold(
        appBar: TabBar(
          tabs: myTabs,
          unselectedLabelColor: Colors.black54,
          labelColor: Colors.black,
          indicatorSize: TabBarIndicatorSize.tab,
          indicator: BoxDecoration(
            shape: BoxShape.rectangle,
            borderRadius: BorderRadius.circular(50),
            color: Colors.white,
          ),
        ),
        body: TabBarView(
          children: myTabs.map((Tab tab) {
            final String label = tab.text.toLowerCase();
            return ListView.builder(
              physics: NeverScrollableScrollPhysics(),
              itemCount: 100,
              itemBuilder: (context, index) {
                return ListTile(
                  title: Text(label),
                );
              },
            );
          }).toList(),
        ),
      ),
    );
  }
}

CustomScrollView: https://dartpad.dev/335f9e0d134a72232200bc8bfd493670

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
      debugShowCheckedModeBanner: false,
      home: CustomScrollView(
        slivers: [
          SliverFillRemaining(
            hasScrollBody: true,
            child: Column(
              children: [
                SizedBox(height: 150, child: Text('Hey')),
                Expanded(child: ProfileTabBarNavigation()),
              ],
            ),
          )
        ],
      ),
    );
  }
}

const String kArtwork = "Left";
const String kPastJobs = "Right";
const EdgeInsets kPaddingTabBar = EdgeInsets.all(5.0);
const Color kLightGrey = Colors.grey;

class ProfileTabBarNavigation extends StatelessWidget {
  final List<Tab> myTabs = <Tab>[
    const Tab(text: kArtwork),
    const Tab(text: kPastJobs)
  ];
  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: 2,
      initialIndex: 0,
      child: Scaffold(
        appBar: TabBar(
          tabs: myTabs,
          unselectedLabelColor: Colors.black54,
          labelColor: Colors.black,
          indicatorSize: TabBarIndicatorSize.tab,
        ),
        body: TabBarView(
          physics: NeverScrollableScrollPhysics(),
          children: myTabs.map((Tab tab) {
            final String label = tab.text.toLowerCase();
            return ListView.builder(
//               physics: NeverScrollableScrollPhysics(),
              itemCount: 50,
              itemBuilder: (context, index) {
                return ListTile(
                  title: Text(label),
                );
              },
            );
          }).toList(),
        ),
      ),
    );
  }
}

Got the CustomScrollView solution from here: How to use Expanded in SingleChildScrollView?

Gihan Anuruddha
  • 339
  • 4
  • 11

1 Answers1

2

Short answer: you need to use NestedScrollView. You also need to adjust a few things in your current code, so longer answer:

const String kArtwork = "Left";
const String kPastJobs = "Right";
const EdgeInsets kPaddingTabBar = EdgeInsets.all(5.0);
const Color kLightGrey = Colors.grey;

class MyApp extends StatelessWidget {
  Widget build(BuildContext context) {
    final String title = 'Multi Sliver Scrollable';
    return MaterialApp(
      title: title,
      theme: ThemeData.dark(),
      debugShowCheckedModeBanner: false,
      home: Home(title),
    );
  }
}

class Home extends StatelessWidget {
  Home(this.title);

  final String title;

  final List<Tab> myTabs = <Tab>[
    const Tab(text: kArtwork),
    const Tab(text: kPastJobs)
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text(title)),
      body: DefaultTabController(
        length: myTabs.length,
        child: NestedScrollView(
          headerSliverBuilder: (context, innerBoxIsScrolled) {
            return <Widget>[
              SliverToBoxAdapter(
                  child: SizedBox(height: 150, child: Text('Hey'))),
              SliverAppBar(
                toolbarHeight: 0,
                bottom: TabBar(
                  tabs: myTabs,
                  indicatorSize: TabBarIndicatorSize.tab,
                ),
              ),
            ];
          },
          body: TabBarView(
            children: myTabs.map((Tab tab) {
              final String label = tab.text.toLowerCase();
              return CustomScrollView(
                key: PageStorageKey<String>(label),
                slivers: [
                  SliverList(
                    delegate: SliverChildListDelegate.fixed(
                      List.filled(50, Text(label)),
                    ),
                  ),
                ],
              );
            }).toList(),
          ),
        ),
      ),
    );
  }
}
Lee3
  • 2,882
  • 1
  • 11
  • 19