Sliver with TabBarView & SliverFillRemaining gives Bottom Overflowed by xxx pixels

2.3k views Asked by At

Need help for the Overflowing pixels issue.

I am currently using a, DefaultTabController -- Scaffold -- Builder -- CustomScrollView (SliverList + SliverFillRemaining)

SliverFillRemaining widget does not scroll full, it takes height equal to Screen height only, even when i scroll to the extreme.

Before scroll

Even After Full Scroll

Code for the same goes here....

Main code to refer is in build & _columnWithTabsAndTicketDetails function

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: ViewEditComplaintDetails(),
    );
  }
}

class ViewEditComplaintDetails extends StatefulWidget {
  ViewEditComplaintDetails({Key key}) : super(key: key);

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

class _ViewEditComplaintDetailsState extends State<ViewEditComplaintDetails> {
  //UI variables goes below.....
  Card _complaintPreviewCard;

  //NON-UI variables goes below....

  final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
  BuildContext _scaffoldContext;
  List<Widget> _productRelatedTabs;

  @override
  void initState() {
    super.initState();

    _complaintPreviewCard = _getComplaintPreviewCard();

    TextStyle _textStyle = TextStyle(fontWeight: FontWeight.w600, fontSize: 12);

    var complaintDetailsTab = Text('COMPLAINT\nDETAILS',
        textAlign: TextAlign.center, style: _textStyle);

    var contactDetailsTab = Text('CONTACT\nDETAILS',
        textAlign: TextAlign.center, style: _textStyle);

    var typeOfComplaintsTab = Text('TYPES OF\nCOMPLAINT',
        textAlign: TextAlign.center, style: _textStyle);

    var sampleDetailsTab =
        Text('SAMPLE\nDETAILS', textAlign: TextAlign.center, style: _textStyle);

    var equipAndAppliDetailsTab = Text('EQUIPMENT\nAPPLICATION DETAILS',
        textAlign: TextAlign.center, style: _textStyle);

    var uploadDocsTab = Text('UPLOADED\nDOCUMENTS',
        textAlign: TextAlign.center, style: _textStyle);

    var commentsTab =
        Text('COMMENTS', textAlign: TextAlign.center, style: _textStyle);

    _productRelatedTabs = List();
    _productRelatedTabs.add(complaintDetailsTab);
    _productRelatedTabs.add(contactDetailsTab);
    _productRelatedTabs.add(typeOfComplaintsTab);
    _productRelatedTabs.add(sampleDetailsTab);
    _productRelatedTabs.add(equipAndAppliDetailsTab);
    _productRelatedTabs.add(uploadDocsTab);
    _productRelatedTabs.add(commentsTab);
  }

  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: _productRelatedTabs.length,
      child: Scaffold(
          // drawer: Drawer(child: NavigationDrawer()),
          // key: _scaffoldKey,
          // appBar: AppBarCustom(context, "View Detail", _navDrawerTap,
          //         addGulfLogoInAppBar: false)
          //     .getCustomAppBar(),
          // bottomNavigationBar: AppBottomNavigationBar(context),
          body: new Builder(builder: (BuildContext context) {
        _scaffoldContext = context;
        return _columnWithTabsAndTicketDetails();
      })),
    );
  } //build closes here....

  _columnWithTabsAndTicketDetails() {
    SliverList _sliverList = SliverList(
      delegate: SliverChildListDelegate(
        [
          //Expanded(child: _getComplaintPreviewCard(), flex: 2),
          _getComplaintPreviewCard(),
          _getTabBar(),

          // _getTabBarView()
          // Expanded(child: _getTabBarView(), flex: 5)
        ],
      ),
    );

    SliverFillRemaining tabBarBottomView =
        SliverFillRemaining(child: _getTabBarView());

    Container finalContainerWithScrollView = Container(
        child: CustomScrollView(
          slivers: [
            // Expanded(child: _sliverList, flex: 1),
            // Expanded(child: tabBarBottomView, flex: 1)
            _sliverList, tabBarBottomView
          ],
        ),
        margin: EdgeInsets.fromLTRB(0, 10, 0, 10));

    return finalContainerWithScrollView;
  } //_columnWithTabsAndTicketDetails closes here....

  _getComplaintPreviewCard() {
    ////////........1st row goes below.........\\\\\\\\\\
    // Color ticketColor = _ticketActiveColor; //Initialization...
    //TODO: Check the status of the ticket & change the color here...
    _complaintPreviewCard = Card(
      margin: EdgeInsets.fromLTRB(10, 0, 10, 0),
      // elevation: ELEVATION_APP,
      child: ClipPath(
          child: Container(
        child: _getComplaintDetails(context),
        decoration: BoxDecoration(
            border: Border(left: BorderSide(color: Colors.green, width: 5))),
      )),
    );

    return _complaintPreviewCard;
  } //_getComplaintPreviewCard closes here....

  _getComplaintDetails(BuildContext context) {
    var margin = EdgeInsets.fromLTRB(10, 0, 5, 0);
    return Container(
        // margin: EdgeInsets.fromLTRB(10, 0, 5, 0),
        padding: EdgeInsets.fromLTRB(0, 8, 0, 0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: [
            Container(child: _complaintDetailsTopRow(), margin: margin),
            Container(child: _complaintDetailsBottomRow(), margin: margin),
            _getImagesVideoAudioCountRow(),
          ],
        ));
  } //_getComplaintDetails closes here....

  _complaintDetailsTopRow() {
    return Container(
      child: Column(
        // mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: [
          //Complaint Title row goes below....
          _getComplaintTitleRow(),
          _getComplaintIDRow(),
        ],
      ),
    );
  } //_complaintDetailsTopRow closes here.....

  _complaintDetailsBottomRow() {
    return Container(
      margin: EdgeInsets.only(top: 15),
      child: Row(crossAxisAlignment: CrossAxisAlignment.start, children: [
        Expanded(child: _getLeftAssignmentColumn(), flex: 4),
        Container(width: 10),
        Expanded(child: _getRightAssignmentColumn(), flex: 4),
      ]),
    );
  } //_complaintDetailsBottomRow closes here....

  _getComplaintTitleRow() {
    return Container(
      child: Row(
        crossAxisAlignment: CrossAxisAlignment.start,
        mainAxisAlignment: MainAxisAlignment.start,
        children: [
          Expanded(child: Icon(Icons.ac_unit), flex: 1),
          Expanded(child: Text("Complaint Title"), flex: 15),
        ],
      ),
    );
  } //_getComplaintTitleRow closes here.....

  _getComplaintIDRow() {
    var complaintDate = "", complaintCode = "";

    return Row(
      mainAxisAlignment: MainAxisAlignment.start,
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        // SmallestText("ID : GT12345", isBlack: true, bottomMargin: 10),
        Expanded(child: Text("ID : $complaintCode"), flex: 3),
        Container(
            margin: EdgeInsets.fromLTRB(5, 0, 5, 10),
            height: 15,
            width: 1,
            color: Colors.green),
        Expanded(
          child: Text("Created on : ${complaintDate}"),
          flex: 3,
        ),

        // Expanded(child: ticketStatusText, flex: 2),
        Container(width: 5) //Adding right margin...
      ],
    );
  } //_getComplaintIDRow closes here....

  _getLeftAssignmentColumn() {
    var complaintDate = "", complaintAssignedTo = "";

    return Container(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text("Assign to : $complaintAssignedTo"),
          Text("Assign on : $complaintDate"),
        ],
      ),
    );
  } //_getLeftAssignmentColumn closes here....

  _getRightAssignmentColumn() {
    String regionName = "", status = "";

    return Container(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.spaceAround,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text("Zone $regionName"),
          Text("Status : $status"),
        ],
      ),
    );
  } //_getRightAssignmentColumn closes here....

  _getImagesVideoAudioCountRow() {
    return Container(
        padding: EdgeInsets.fromLTRB(0, 5, 0, 5),
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: [
            Expanded(
                child:
                    Container(color: Colors.green, child: Icon(Icons.ac_unit)),
                flex: 1),
            Container(width: 1, height: 45, color: Colors.red),
            Expanded(child: Container(child: Icon(Icons.ac_unit)), flex: 1),
            Container(width: 1, height: 45, color: Colors.red),
            Expanded(child: Container(child: Icon(Icons.ac_unit)), flex: 1),
          ],
        ));
  } //_getImagesVideoAudioCountRow closes here....

  _getTabBar() {
    var tabControllerAppBar = new SizedBox(
      height: 50,
      child: new Container(
        height: 50,
        color: Colors.green,
        child: new SafeArea(
          child: new TabBar(isScrollable: true, tabs: _productRelatedTabs),
        ),
      ),
    );

    return tabControllerAppBar;
  } //_getTabBar closes here.....

  _getTabBarView() {
    var tabControllerBody = TabBarView(children: [
      Container(
          margin: EdgeInsets.fromLTRB(10, 0, 10, 0),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text("1"),
              TextFormField(),
              // Container(height: 15),
              Text("2"),
              TextFormField(),
              Text("3"),
              TextFormField(),
              Text("4"),
              TextFormField(),
              Text("5"),
              TextFormField(),
              Text("6"),
              TextFormField(),
              Text("7"),
              TextFormField(),
              Text("8"),
              TextFormField(),
              Text("9"),
              TextFormField(),
              Text("10"),
              TextFormField(),
              Text("11"),
              TextFormField(),
              Text("12"),
              TextFormField(),
            ],
          )),

      // new Column(
      //   children: <Widget>[new Text("Cart Page")],
      // ),

      // Container(
      //     margin:
      //         EdgeInsets.fromLTRB(_standard10Margin, 0, _standard10Margin, 0),
      //     child: ContactDetailsContainer(this, _complaintType,
      //         prefilledPackageDetails: null, prefilledProductDetails: null)),
      new Column(
        children: <Widget>[new Text("Cart Page")],
      ),
      new Column(
        children: <Widget>[new Text("Cart Page")],
      ),
      new Column(
        children: <Widget>[new Text("Lunches Page")],
      ),
      new Column(
        children: <Widget>[new Text("Lunches Page")],
      ),
      new Column(
        children: <Widget>[new Text("Lunches Page")],
      ),
      new Column(
        children: <Widget>[new Text("Lunches Page")],
      ),
    ]);

    return tabControllerBody;
  } //_getTabBarView closes here.....

} //_ViewEditComplaintDetailsState closes here....

What have i tried till now ?

  1. I have reached so far after referring this : https://stackoverflow.com/a/63305024/2975475

  2. Tried adding TabBarView inside SingleChildScrollView - Container - TabBarView but did not work.

  3. Tried adding TabBarView inside ListView - TabBarView but did not work.

  4. Removed TabBarView & setState on every Tab click, but then the selected tab resets to 0, everytime.

1

There are 1 answers

0
timilehinjegede On BEST ANSWER

As mentioned in the comments above, you also need the Tabs to scroll when the TabBarView content is scrolled.

I'll consider using a NestedScrollView in this scenario. Check here to read more about the NestedScrollView.

I added a demo of how to use the NestedScrollView using your code as an example:

class ViewEditComplaintDetails extends StatefulWidget {
  ViewEditComplaintDetails({Key key}) : super(key: key);

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

class _ViewEditComplaintDetailsState extends State<ViewEditComplaintDetails> {
  //UI variables goes below.....
  Card _complaintPreviewCard;

  //NON-UI variables goes below....

  final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
  BuildContext _scaffoldContext;
  List<Widget> _productRelatedTabs;

  @override
  void initState() {
    super.initState();

    _complaintPreviewCard = _getComplaintPreviewCard();

    TextStyle _textStyle = TextStyle(fontWeight: FontWeight.w600, fontSize: 12);

    var complaintDetailsTab = Text('COMPLAINT\nDETAILS',
        textAlign: TextAlign.center, style: _textStyle);

    var contactDetailsTab = Text('CONTACT\nDETAILS',
        textAlign: TextAlign.center, style: _textStyle);

    var typeOfComplaintsTab = Text('TYPES OF\nCOMPLAINT',
        textAlign: TextAlign.center, style: _textStyle);

    var sampleDetailsTab =
        Text('SAMPLE\nDETAILS', textAlign: TextAlign.center, style: _textStyle);

    var equipAndAppliDetailsTab = Text('EQUIPMENT\nAPPLICATION DETAILS',
        textAlign: TextAlign.center, style: _textStyle);

    var uploadDocsTab = Text('UPLOADED\nDOCUMENTS',
        textAlign: TextAlign.center, style: _textStyle);

    var commentsTab =
        Text('COMMENTS', textAlign: TextAlign.center, style: _textStyle);

    _productRelatedTabs = List();
    _productRelatedTabs.add(complaintDetailsTab);
    _productRelatedTabs.add(contactDetailsTab);
    _productRelatedTabs.add(typeOfComplaintsTab);
    _productRelatedTabs.add(sampleDetailsTab);
    _productRelatedTabs.add(equipAndAppliDetailsTab);
    _productRelatedTabs.add(uploadDocsTab);
    _productRelatedTabs.add(commentsTab);
  }

  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: _productRelatedTabs.length,
      child: Scaffold(
          // drawer: Drawer(child: NavigationDrawer()),
          // key: _scaffoldKey,
          // appBar: AppBarCustom(context, "View Detail", _navDrawerTap,
          //         addGulfLogoInAppBar: false)
          //     .getCustomAppBar(),
          // bottomNavigationBar: AppBottomNavigationBar(context),
          body: new Builder(builder: (BuildContext context) {
        _scaffoldContext = context;
        return NestedScrollView(
          headerSliverBuilder: (context, value) {
            return [
              // header
              SliverList(
                delegate: SliverChildListDelegate(
                  [
                    //Expanded(child: _getComplaintPreviewCard(), flex: 2),
                    _getComplaintPreviewCard(),
                    _getTabBar(),

                    // _getTabBarView()
                    // Expanded(child: _getTabBarView(), flex: 5)
                  ],
                ),
              ),
            ];
          },
          // tab bar view
          body: _getTabBarView(),
        );
      })),
    );
  } //build closes here....

  _getComplaintPreviewCard() {
    ////////........1st row goes below.........\\\\\\\\\\
    // Color ticketColor = _ticketActiveColor; //Initialization...
    //TODO: Check the status of the ticket & change the color here...
    _complaintPreviewCard = Card(
      margin: EdgeInsets.fromLTRB(10, 0, 10, 0),
      // elevation: ELEVATION_APP,
      child: ClipPath(
          child: Container(
        child: _getComplaintDetails(context),
        decoration: BoxDecoration(
            border: Border(left: BorderSide(color: Colors.green, width: 5))),
      )),
    );

    return _complaintPreviewCard;
  } //_getComplaintPreviewCard closes here....

  _getComplaintDetails(BuildContext context) {
    var margin = EdgeInsets.fromLTRB(10, 0, 5, 0);
    return Container(
        // margin: EdgeInsets.fromLTRB(10, 0, 5, 0),
        padding: EdgeInsets.fromLTRB(0, 8, 0, 0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: [
            Container(child: _complaintDetailsTopRow(), margin: margin),
            Container(child: _complaintDetailsBottomRow(), margin: margin),
            _getImagesVideoAudioCountRow(),
          ],
        ));
  } //_getComplaintDetails closes here....

  _complaintDetailsTopRow() {
    return Container(
      child: Column(
        // mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        children: [
          //Complaint Title row goes below....
          _getComplaintTitleRow(),
          _getComplaintIDRow(),
        ],
      ),
    );
  } //_complaintDetailsTopRow closes here.....

  _complaintDetailsBottomRow() {
    return Container(
      margin: EdgeInsets.only(top: 15),
      child: Row(crossAxisAlignment: CrossAxisAlignment.start, children: [
        Expanded(child: _getLeftAssignmentColumn(), flex: 4),
        Container(width: 10),
        Expanded(child: _getRightAssignmentColumn(), flex: 4),
      ]),
    );
  } //_complaintDetailsBottomRow closes here....

  _getComplaintTitleRow() {
    return Container(
      child: Row(
        crossAxisAlignment: CrossAxisAlignment.start,
        mainAxisAlignment: MainAxisAlignment.start,
        children: [
          Expanded(child: Icon(Icons.ac_unit), flex: 1),
          Expanded(child: Text("Complaint Title"), flex: 15),
        ],
      ),
    );
  } //_getComplaintTitleRow closes here.....

  _getComplaintIDRow() {
    var complaintDate = "", complaintCode = "";

    return Row(
      mainAxisAlignment: MainAxisAlignment.start,
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        // SmallestText("ID : GT12345", isBlack: true, bottomMargin: 10),
        Expanded(child: Text("ID : $complaintCode"), flex: 3),
        Container(
            margin: EdgeInsets.fromLTRB(5, 0, 5, 10),
            height: 15,
            width: 1,
            color: Colors.green),
        Expanded(
          child: Text("Created on : ${complaintDate}"),
          flex: 3,
        ),

        // Expanded(child: ticketStatusText, flex: 2),
        Container(width: 5) //Adding right margin...
      ],
    );
  } //_getComplaintIDRow closes here....

  _getLeftAssignmentColumn() {
    var complaintDate = "", complaintAssignedTo = "";

    return Container(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text("Assign to : $complaintAssignedTo"),
          Text("Assign on : $complaintDate"),
        ],
      ),
    );
  } //_getLeftAssignmentColumn closes here....

  _getRightAssignmentColumn() {
    String regionName = "", status = "";

    return Container(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.spaceAround,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text("Zone $regionName"),
          Text("Status : $status"),
        ],
      ),
    );
  } //_getRightAssignmentColumn closes here....

  _getImagesVideoAudioCountRow() {
    return Container(
        padding: EdgeInsets.fromLTRB(0, 5, 0, 5),
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
          children: [
            Expanded(
                child:
                    Container(color: Colors.green, child: Icon(Icons.ac_unit)),
                flex: 1),
            Container(width: 1, height: 45, color: Colors.red),
            Expanded(child: Container(child: Icon(Icons.ac_unit)), flex: 1),
            Container(width: 1, height: 45, color: Colors.red),
            Expanded(child: Container(child: Icon(Icons.ac_unit)), flex: 1),
          ],
        ));
  } //_getImagesVideoAudioCountRow closes here....

  _getTabBar() {
    var tabControllerAppBar = new SizedBox(
      height: 50,
      child: new Container(
        height: 50,
        color: Colors.green,
        child: new SafeArea(
          child: new TabBar(isScrollable: true, tabs: _productRelatedTabs),
        ),
      ),
    );

    return tabControllerAppBar;
  } //_getTabBar closes here.....

  _getTabBarView() {
    var tabControllerBody = TabBarView(children: [
      Container(
          margin: EdgeInsets.fromLTRB(10, 0, 10, 0),
          child: SingleChildScrollView(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text("1"),
                TextFormField(),
                // Container(height: 15),
                Text("2"),
                TextFormField(),
                Text("3"),
                TextFormField(),
                Text("4"),
                TextFormField(),
                Text("5"),
                TextFormField(),
                Text("6"),
                TextFormField(),
                Text("7"),
                TextFormField(),
                Text("8"),
                TextFormField(),
                Text("9"),
                TextFormField(),
                Text("10"),
                TextFormField(),
                Text("11"),
                TextFormField(),
                Text("12"),
                TextFormField(),
              ],
            ),
          )),

      // new Column(
      //   children: <Widget>[new Text("Cart Page")],
      // ),

      // Container(
      //     margin:
      //         EdgeInsets.fromLTRB(_standard10Margin, 0, _standard10Margin, 0),
      //     child: ContactDetailsContainer(this, _complaintType,
      //         prefilledPackageDetails: null, prefilledProductDetails: null)),
      new Column(
        children: <Widget>[new Text("Cart Page")],
      ),
      new Column(
        children: <Widget>[new Text("Cart Page")],
      ),
      new Column(
        children: <Widget>[new Text("Lunches Page")],
      ),
      new Column(
        children: <Widget>[new Text("Lunches Page")],
      ),
      new Column(
        children: <Widget>[new Text("Lunches Page")],
      ),
      new Column(
        children: <Widget>[new Text("Lunches Page")],
      ),
    ]);

    return tabControllerBody;
  } //_getTabBarView closes here.....

} //_ViewEditComplaintDetai

RESULT:

result1 result2