skip to Main Content

I have the following scroll view

      CustomScrollView(
        physics: const NeverScrollableScrollPhysics(),
        slivers: [
          const SliverToBoxAdapter(
            child: Placeholder(
              fallbackHeight: 120,
            ),
          ),
          const SliverToBoxAdapter(
            child: SizedBox(
              height: 180,
              child: Placeholder(),
            ),
          ),
          SliverFillRemaining(
            child: _NavigationList(
              items: routes.items,
            ),
          ),
        ],
      ),

Where I intend the parent list to not be scrollable but the nested list in the SliverFillRemaining should be scrollable.

But what ends up happening is that the CustomScrollView is still scrollable with the scroll bar and has quite a bit of overflow. The overflow seems to exactly match the height of the two placeholders combined. How can I make it so that the parent is not scrollable but the child is. Because now the scroll bar still shows up.

This is what it looks like. The app is full screen and there seems to be overflow and you can scroll using the scrollbar.

enter image description here

Btw I can’t solve this with a column because it will cause overflow errors also. And if you try to solve it with an column and expanded then you would need to wrap the column with a SingleChildScrollView to prevent those error, which you can’t do since there is an expanded in the Column.

THE QUESTION:

So very straightforward since I notice a misunderstanding of the issue in the answers. When you have a CustomScrollView and you add boxes with height and a SliverFillRemaining you would expect that there would not be any more overflow. This does seem to be the case and it matches the height of the boxes. And this is why the the parent CustomScrollView shows a scroll bar. My question is how do I prevent this.

6

Answers


  1. Chosen as BEST ANSWER

    So I approached it differently. Since the parent list is only scrollable with the scroll bar I decided to disable the scroll bar for the parent list. It solves the issue I had.

    But it still seems a bug to me that boxes with height added to a CustomScrollView with a SliverFillRemaining create overflow.

    For now I will accept this as the answer.

          ScrollConfiguration(
            behavior: ScrollConfiguration.of(context).copyWith(
              scrollbars: false,
            ),
            child: CustomScrollView(
              physics: const NeverScrollableScrollPhysics(),
              slivers: [
                SliverToBoxAdapter(
                  child: Column(
                    children: const [
                      Placeholder(
                        fallbackHeight: 120,
                      ),
                      SizedBox(
                        height: 180,
                        child: Placeholder(),
                      ),
                      SizedBox(
                        height: 25,
                      ),
                    ],
                  ),
                ),
                SliverFillRemaining(
                  child: ScrollConfiguration(
                    behavior: ScrollConfiguration.of(context).copyWith(
                      scrollbars: true,
                    ),
                    child: _NavigationList(
                      items: routes.items,
                    ),
                  ),
                ),
              ],
            ),
          ),
    

  2. I made an example app with your code and it seems to be working as intended.
    Please give it a try. I’m using flutter 3.3.9. If this does not help you, I would suggest posting the code of an example that fully reproduces your issue.

    import 'package:flutter/material.dart';
    
    void main() {
      runApp(const MyApp());
    }
    
    class MyApp extends StatelessWidget {
      const MyApp({super.key});
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Flutter Demo',
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: const MyHomePage(),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      const MyHomePage({super.key});
    
      @override
      State<MyHomePage> createState() => _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: const Text('CustomScrollView'),
          ),
          body: Center(
            child: ScrollConfiguration(
              behavior: ScrollConfiguration.of(context).copyWith(scrollbars: false),
              child: CustomScrollView(
                physics: const NeverScrollableScrollPhysics(),
                slivers: [
                  SliverToBoxAdapter(
                    child: Column(
                      children: const [
                        SizedBox(
                          height: 120,
                          // child: GameSelectedIcon(),
                          child: Icon(Icons.garage),
                        ),
                        Placeholder(
                          fallbackHeight: 180,
                        ),
                        SizedBox(
                          height: 25,
                        ),
                      ],
                    ),
                  ),
                  SliverFillRemaining(
                    child: ScrollConfiguration(
                      behavior: ScrollConfiguration.of(context).copyWith(scrollbars: true),
                      child: ListView(
                        physics: const AlwaysScrollableScrollPhysics(),
                        shrinkWrap: true,
                        children: [
                          ...List.generate(20, (int index) {
                            return TextButton(
                              onPressed: () {},
                              child: Text('Navigate $index'),
                            );
                          }),
                        ],
                      ),
                    ),
                  ),
                ],
              ),
            ),
          ),
        );
      }
    }
    
    Login or Signup to reply.
  3. If you don’t intend the parent to scroll, then replace CustomScrollView with a Column, and make changes as below:

    Column(
      children: [
        SizedBox(
          height: 120,
          child: GameSelectedIcon(),
        ),
        Placeholder(
          fallbackHeight: 180,
        ),
        SizedBox(
          height: 25,
        ),
        Expanded(
          child: ListView(
            physics: const AlwaysScrollableScrollPhysics(),
            shrinkWrap: true,
            children: [
              _NavigationList(
                items: _navigationListItems,
              ),
            ],
          ),
        ),
      ],
    )
    
    Login or Signup to reply.
  4. Have you tried adding hasScrollBody: false to SliverFillRemaining? It should remove overflows

    Login or Signup to reply.
  5. With just using SliverAppBar you can achieve your desired output:
    just make pinned: true and give toolbarHeight: *as per your need*,

    Scaffold(
            appBar: AppBar(
              title: const Text("CustomScrollView"),
              centerTitle: true,
            ),
            body: CustomScrollView(
              slivers: [
                SliverAppBar(
                  pinned: true,
                  backgroundColor: Colors.white,
                  //can change color as per your need or remove for default theme
                  toolbarHeight: 350,
                  // change height of appbar
                  title: Column(
                    children: const [
                      Placeholder(
                        fallbackHeight: 120,
                      ),
                      SizedBox(
                        height: 180,
                        child: Placeholder(),
                      ),
                      SizedBox(
                        height: 25,
                      ),
                    ],
                  ),
                ),
                SliverFillRemaining(
                  child: ListView.builder(
                    shrinkWrap: true,
                    primary: false,
                    itemCount: 20,
                    itemBuilder: (context, index) {
                      return TextButton(
                        onPressed: () {},
                        child: Text("navigation $index"),
                      );
                    },
                  ),
                ),
              ],
            ),
          ),
    

    enter image description here

    Login or Signup to reply.
  6. I’m trying to use a CustomScrollView and two sliver sections to freeze the header and scroll down other side. Help comments can be found in my solution:

    ScrollConfiguration(
            ///Note: below property help to scrolling without scrollbars and use code in web browsers.
            behavior: const MaterialScrollBehavior()
                .copyWith(scrollbars: false, dragDevices: {
              PointerDeviceKind.touch,
              PointerDeviceKind.mouse,
            }),
            child: CustomScrollView(
              ///Note:  freeze headers on top by set below property .
              ///if delete this property ,may be header can scrolling and miss those .
              physics: const NeverScrollableScrollPhysics(),
              slivers: [
                //Note: top section of CustomScrollView
                const SliverToBoxAdapter(
                  child: Placeholder(
                    fallbackHeight: 400,
                  ),
                ),
    
                ///Note: other section of CustomScrollView - scrollable area
                /// if need scrollbar for here , can use  ScrollConfiguration widget !
                SliverFillRemaining(
                  child: ListView(children: [
                    for (int i = 0; i < 10; i++) ...[
                      Container(height: 100, color: Colors.green),
                      Container(height: 100, color: Colors.red),
                    ]
                  ]),
                ),
              ],
            ),
          ),
    

    if using ScrollConfiguration.of(context).copyWith(scrollbars: false) as a behavior for ScrollConfiguration , The scrollbars are removed, but your scrolling in flutter web remains disabled.
    better use MaterialScrollBehavior widget like below:

    const MaterialScrollBehavior()
                .copyWith(scrollbars: false, dragDevices: {
              PointerDeviceKind.touch,
              PointerDeviceKind.mouse,
            })
    

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search