3
@override
  Widget build(BuildContext context) {
    super.build(context);

    SystemChrome.setEnabledSystemUIOverlays(SystemUiOverlay.values);
    return AnnotatedRegion<SystemUiOverlayStyle>(
      value: SystemUiOverlayStyle(
        statusBarColor: Colors.transparent,
      ),
      child: Scaffold(
     key: _scaffoldKeyProfilePage,

      body: DefaultTabController(
        length: 2,
 child:RefreshIndicator(
          onRefresh: _onRefresh,
        child: NestedScrollView(
          
            headerSliverBuilder: (context, _) {
              return [
                SliverList(
                delegate: SliverChildListDelegate(
                 [                 BuildMainProfile(
              ....//
                 ),
                 Padding(
                ...//another design 
                 ), 
                
              ];
            },
            // You tab view goes here
            body: Column(
              children: <Widget>[
                TabBar(
              tabs: [
                Tab(text: 'A'),
                Tab(text: 'B'),
              ],
                ),
                Expanded(
              child: TabBarView(
                children: [
                  BuildPost(,

                  ),
                 BuildWings()
                ],
              ),
                ),
              ],
            ),
          ),),
      ),

}enter image description here


Above is the example of error which I am getting
error:A RenderFlex overflowed by 48 pixels on the bottom.
How to solve this issue? Tried using expanded on TabBar and giving flex of 1 to tab bar and flex of 10 to tabView , but with that tab bar shrinks on scrolling down.


Here below is the code for tabBar view A and B is even similar

class BuildPost extends StatefulWidget {
  final String uid;

  const BuildPost({
    Key key,
    @required this.uid,
  }) : super(key: key);
  @override
  _BuildPostState createState() => _BuildPostState();
}

class _BuildPostState extends State<BuildPost> {
  List<Post> _post = [];

  getUsersPost() async {
    final database = FirestoreDatabase();
    List<Post> _postModel = await database.getUsersPost(widget.uid);
    setState(() {
      _post = _postModel.toList();
    });
  }

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

  @override
  Widget build(BuildContext context) {
    return _post.isEmpty
        ? Container(
            height: 500,
            width: double.infinity,
          )
        : GestureDetector(
            child: Directionality(
                textDirection: TextDirection.ltr,
                child: AnimationLimiter(
                  child: StaggeredGridView.countBuilder(
                    padding: EdgeInsets.all(10),
                    shrinkWrap: true,
                    physics: NeverScrollableScrollPhysics(),
                    crossAxisCount: 3,
                    itemCount: _post.length,
                    itemBuilder: (context, index) {
                      return AnimationConfiguration.staggeredGrid(
                        position: index,
                        duration: const Duration(milliseconds: 500),
                        columnCount: 3,
                        child: SlideAnimation(
                          verticalOffset: 50.0,
                          child: FadeInAnimation(
                              duration: Duration(milliseconds: 1000),
                              child: BuildData(
                                totalPost: _post.length,
                                postList: _post,
                                index: index,
                                post: _post[index],
                              )),
                        ),
                      );
                    },
                    staggeredTileBuilder: (index) => StaggeredTile.count(
                        index % 7 == 0 ? 2 : 1,
                        index % 7 == 0 ? (2.1) : (1.05)),
                    mainAxisSpacing: 4.0,
                    crossAxisSpacing: 4.0,
                  ),
                )),
          );
  }
}

kanwar manraj
  • 492
  • 8
  • 26
  • I have managed to re-create the same UI without issue, could you please give more code for the Tabs so I can test more. – Jackson Lee Dec 26 '20 at 03:52
  • @JacksonLee I have added the code for the Tabs – kanwar manraj Dec 26 '20 at 06:09
  • I think your headerSliverBuilder is too tall, leaving to enough space for the TabBar in the body. – spkersten Dec 26 '20 at 12:36
  • @spkersten that space is deliberately tall, which is dynamic. Where the user can put their bio. – kanwar manraj Dec 26 '20 at 12:52
  • I think the body is supposed to be some scrollable widget (ListView, CustomScrollView). Can you put the TabBar at the bottom of headerSliverBuilder? – spkersten Dec 26 '20 at 13:33
  • I can't add the tab bar at the bottom of headerSliverBuilder, because when we scroll tab bar would be hidden and wouldn't stick to the top. Any other way out? My layout is almost similar to https://stackoverflow.com/a/59981330/13406343 – kanwar manraj Dec 26 '20 at 14:28
  • Thanks, I just need the model for Post and BuildData widget - If its easier, drop the files into my onedrive - https://1drv.ms/u/s!AoUkF50a_XNzgX0ocwbBGiaqELFQ?e=n1j4Bk – Jackson Lee Dec 26 '20 at 19:33
  • BuildData just contain the code for the grid ,which is nothing more than a rounded container with further gesture detector property. And Post is just a model class for the usersPost from Firestore. – kanwar manraj Dec 26 '20 at 19:50
  • why is the Expanded is needed as the parent of the TabBarView? what does removing does? – Yadu Dec 29 '20 at 04:23
  • Removing Expanded gives an error – kanwar manraj Dec 29 '20 at 07:28

3 Answers3

1

It is because the body height of NestedScrollView is from 0 to MediaQuery.of(context).size.height, while your TabBar inside the column make it layout a minimal height of TabBar.

Move TabBar inside builder

Form the example of NestedScrollView, you can see the TabBar is inside headerSliverBuilder. You can simply move the TabBar inside it (wrap a SliverToBoxAdapteror SliverAppBar to make it sliver).

Then you can remove the Column and Expand Widget above the TabBarView

child: NestedScrollView(
  headerSliverBuilder: (context, _) {
    return [
      SliverList( 
       ...
      ),
      SliverAppBar(
        pinned: true,
        primary: false,  // no reserve space for status bar
        toolbarHeight: 0,  // title height = 0
        bottom: TabBar(
          tabs: [
            Tab(text: 'A'),
            Tab(text: 'B'),
          ],
        ),
      )
    ];
  }
  body: TabBarView(
    children: [
     ...
  

enter image description here

yellowgray
  • 4,006
  • 6
  • 28
  • Hey the issue with the first solution is I want the tab bar to be pinned +the issue with your first code is similar to this https://drive.google.com/file/d/1qTJa37BRax4rQv7egdptynRk0lHRMz8q/view the issue is , if you clearly see when we scroll up after reaching the bottom of tabView, the grid of tab view remains inside the headerSliverBuilder. headerSliver starts showing its component before we reach the top of the grid of tab View. And the issue with 2nd solution is ,TabBar gets shrink and deshrink on scrolling – kanwar manraj Dec 29 '20 at 14:31
  • I update with a `ListView` with `ConstrainedBox` solution. Check it out if it fit your situation. – yellowgray Dec 30 '20 at 05:53
  • Nope, it doesn't fit in, Now the issue is due to list view, the Grid scroll in its own position, and seems like there's no use of using NestedScrollView. Demo is here https://drive.google.com/file/d/1OrwxdvXiLo49eUP8ulC_tjVT1gmXoSyC/view?usp=sharing – kanwar manraj Dec 30 '20 at 06:32
  • No, I haven't set any scroller inside my NestedScrollView – kanwar manraj Dec 30 '20 at 08:52
  • I see. I change the first solution using `SliverAppBar` with pinned is true. Is the layout fit? – yellowgray Dec 30 '20 at 09:13
  • Due to this SliverAppBar, there's a lot of unwanted space due to leading and title and the issue of "When we scroll up after reaching the bottom of tabView, the grid of tab view remains inside the headerSliverBuilder. headerSliver starts showing its component before we reach the top of the grid of tab View" -remains still there – kanwar manraj Dec 30 '20 at 12:09
  • 2
    I remove the unwanted answer and update with SliverAppBar part. You can actually remove unwanted space (please see the update). I am quite a little bit lost what you really want in result. Your original question is the overflowing issue, but no much describing what your layout should be. – yellowgray Jan 02 '21 at 06:22
  • Could you please provide the code for the grid of yours, because I am still facing the same issue here https://drive.google.com/file/d/1164KZyVIVgoC0UMDj1jG2-nyZykqNO9E/view?usp=sharing . We could see we never get to see the 0th grid again on scrolling. – kanwar manraj Jan 02 '21 at 11:37
  • ok, I got where the issue was, I was having My nestedScrollViews property floatHeaderSlivers: true, – kanwar manraj Jan 02 '21 at 11:46
  • Isn't this just the same answer as I gave? – spkersten Jan 02 '21 at 14:49
  • 1
    spkersten I think u are right. I haven't notice after trying so many options, the final one is like yours... Let me give you a upvote for your foresight. – yellowgray Jan 02 '21 at 15:08
0

The body property of NestedScrollView gets a tight height constraint equal to the space left over by headerSliverBuilder (considering the scroll position). In your code, you've as body a Column widget with a fixed height (the TabBar) widget in there. So when the height constraint of body gets smaller than the TabBar height, it will overflow the Column.

So in body, there must be a widget that can shrink to zero height, most likely a scrollable (ListView, CustomScrollView). In your case, you can move the TabBar to the bottom of headerSliverBuilder, wrapping it with:

SliverPersistentHeader(
  pinned: true,
  delegate: SimpleHeaderDelegate(
    child: TabBar(...),
  ),
)

using:

class SimpleHeaderDelegate extends SliverPersistentHeaderDelegate {
  SimpleHeaderDelegate({@required this.child});

  final PreferredSizeWidget child;

  @override
  Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) => child;

  @override
  double get maxExtent => child.preferredSize.height;

  @override
  double get minExtent => child.preferredSize.height;

  @override
  bool shouldRebuild(covariant SimpleHeaderDelegate oldDelegate) => oldDelegate.child != child;
}
spkersten
  • 2,849
  • 21
  • 20
  • I can't add the tab bar at the bottom of headerSliverBuilder, because when we scroll tab bar would be hidden and wouldn't stick to the top. – kanwar manraj Dec 26 '20 at 14:23
  • I tried this but it has affected the UI design and scrolling isn't proper now if you could please check it out https://drive.google.com/file/d/1qTJa37BRax4rQv7egdptynRk0lHRMz8q/view?usp=sharing – kanwar manraj Dec 26 '20 at 15:07
  • I don't see much wrong in that gif. Maybe you want to give child in `SimpleHeaderDelegate` a white background? – spkersten Dec 26 '20 at 15:14
  • the issue is , if you clearly see when we scroll up after reaching the bottom of tabView, the grid of tab view remains inside the headerSliverBuilder. headerSliver starts showing its component before we reach the top of the grid of tab View. – kanwar manraj Dec 26 '20 at 15:26
  • @kanwarmanraj Perhaps because you have set `physics: NeverScrollableScrollPhysics(),` for that grid? – spkersten Dec 27 '20 at 10:09
  • Actually no, I have set physics: ScrollPhysics() – kanwar manraj Dec 27 '20 at 10:52
0

See SingleChildScrollView class, Expanding content to fit the viewport:

https://api.flutter.dev/flutter/widgets/SingleChildScrollView-class.html

  • 1
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jun 03 '22 at 19:39