How do I enable scrollbar for vertical scroll and disable for horizontal?

3,562

Solution 1

class NoScrollbar extends StatelessWidget {
  final Widget child;
  const NoScrollbar({Key key, this.child}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return NotificationListener<ScrollNotification>(
      onNotification: (_) => true,
      child: child,
    );
  }
}

Just wrap the NoScrollbar Widget around the Scrolling Widget, you don't want to have the Scrollbar appear. This solved it for me!

Solution 2

Niklas answer did not work for me in Flutter 2.5. I don't know if it's because my layout is different or what. But if you have a PageView (as a carousel for example) inside a ListView the way I found to remove PageView's scrollbar is the following.

Add to Scrollbar widget a notificationPredicate:

notificationPredicate: (ScrollNotification notification) {
  return notification.depth == 0 && notification.metrics.axis == Axis.vertical;
}

This will only show scrollbar for vertical interactions.

Flutter documentation about notificationPredicate.

Share:
3,562
Tumist
Author by

Tumist

Updated on December 18, 2022

Comments

  • Tumist
    Tumist over 1 year

    I've been building layout with both horizontal and vertical scrolling. Vertical scrollable Column is for main content and is populated by different views, including horizontal ListView which shows promo banners. I wanted to show scrollbar for vertical scrolling, but not for horizontal. I've wrapped the SingleChildScrollView which makes Column scrollable in ScrollBar, but the bar appeared on both vertical on horizontal scrolls. Is there any fine-tuning for these kinds of things?

    Sample to demonstrate the issure

    import 'package:flutter/material.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Scrollables',
          home: MyHomePage(),
        );
      }
    }
    
    class MyHomePage extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Scrollbar(
            child: new SingleChildScrollView(
                child: new Container(
              padding: EdgeInsets.only(top: 40.0),
              child: Column(children: <Widget>[
                HorizontalListView(),
                VerticalListView(),
              ]),
            )),
          ),
        );
      }
    }
    
    class HorizontalListView extends StatelessWidget {
      var items = new List<String>();
    
      _addNewItem(int index) {
        items.add("Item $index");
      }
    
      @override
      Widget build(BuildContext context) => Container(
          height: 120,
          child: ListView.builder(
              scrollDirection: Axis.horizontal,
              itemCount: 15,
              itemBuilder: (context, index) {
                return Card(child: ListItem(index));
              }));
    }
    
    class VerticalListView extends StatelessWidget {
      var items = new List<String>();
    
      _addNewItem(int index) {
        items.add("Item $index");
      }
    
      @override
      Widget build(BuildContext context) => Container(
          child: ListView.builder(
              scrollDirection: Axis.vertical,
              itemCount: 50,
              shrinkWrap: true,
              physics: const NeverScrollableScrollPhysics(),
              itemBuilder: (context, index) {
                return ListItem(index);
              }));
    }
    
    class ListItem extends StatelessWidget {
      int _index;
      ListItem(this._index);
      @override
      Widget build(BuildContext context) {
        return Container(
          width: 280,
          child: Text("Item ${this._index}"),
        );
      }
    }
    
    

    Scrolling demonstration

    Pay attention to the bottom on horizontal scrolling

  • MobileMon
    MobileMon over 3 years
    I don't understand how this works but it does work
  • nt4f04und
    nt4f04und over 3 years
    @MobileMon flutter scrollbar is based on ScrollNotifications, and because returning true from the NotificationListener<ScrollNotification> onNotification will prevent notication bubbling, it won't reach the Scrollbar widget and it thus it won't appear