How To Move The TabBarView in the Center to The Top of the Page?

Viewed 702

I have a TabBarView in the middle of the page which changes tab. The content on tab 1 is created by StaggeredGridView.countBuilder while content on 2nd tab is created by listview.builder.

The content of each tab is scrollable, however, only the content below the TabBarView is scrollable.

Is it possible that as I scroll the page, the TabBarView also moves from the middle of the screen to the top of the page and locks itself there, so that the entire screen can be filled with content from each tab?

I've seen people suggesting using SingleChildScrollView for the body and physics: NeverScrollableScrollPhysics() for the listview.builder.

This has not worked. The screen returns just the background color when it is run.

Current TabBarView Position

Desired TabBarView Position when scrolled.

1 Answers

You need to use a custom scrollView which holds all the items.

  1. Your profile details widget
  2. tabBar
  3. tabview

lets implement this

con: appbar cannot be pinned

import 'package:flutter/material.dart';

class MyCustomScrollViewScreen extends StatefulWidget {
  @override
  _MyCustomScrollViewScreenState createState() =>
      _MyCustomScrollViewScreenState();
}

class _MyCustomScrollViewScreenState extends State<MyCustomScrollViewScreen>
    with TickerProviderStateMixin {
  TabController tabController;
  @override
  Widget build(BuildContext context) {
    tabController = TabController(length: 2, vsync: this);
    return Scaffold(
      body: SafeArea(
        child: CustomScrollView(
          slivers: [
            SliverAppBar(
              floating: true,
              title: Text("AppBar"),
            ),
            //profile widget

            SliverToBoxAdapter(
              key: UniqueKey(),
              child: Container(
                color: Colors.green,
                height: 100,
                child: Center(child: Text("Profile details")),
              ),
            ),

            //tabbar
            SliverPersistentHeader(
                pinned: true,
                floating: true,
                delegate: MyCustomHeader(
                    expandedHeight: kToolbarHeight,
                    tabs: TabBar(
                      controller: tabController,
                      tabs: [
                        Icon(
                          Icons.ac_unit,
                          size: 30,
                          color: Colors.black,
                        ),
                        Icon(
                          Icons.access_alarm,
                          size: 30,
                          color: Colors.black,
                        ),
                      ],
                    ))),
            //children
            SliverFillRemaining(
              child: TabBarView(
                controller: tabController,
                children: [
                  Center(child: Text("I'm 1")),
                  Center(child: Text("I'm 2"))
                ],
              ),
            )
          ],
        ),
      ),
    );
  }
}

/// persistent header
class MyCustomHeader extends SliverPersistentHeaderDelegate {
  MyCustomHeader({
    @required this.expandedHeight,
    this.tabs,
    this.context,
  });

  final Widget tabs;
  final double expandedHeight;
  final BuildContext context;

  @override
  double get maxExtent => expandedHeight;

  @override
  double get minExtent => kToolbarHeight;

  @override
  bool shouldRebuild(SliverPersistentHeaderDelegate oldDelegate) => true;

  @override
  Widget build(
      BuildContext context, double shrinkOffset, bool overlapsContent) {
    return Container(
      child: tabs,
    );
  }
}

here is the result

img url

Related