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

2

5

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

Steelhead answered 24/2, 2020 at 8:53 Comment(2)
Did you find any solution?Pocketknife
I didn't, sadly. Still trying to figure this one out.Steelhead
P
8
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!

Pocketknife answered 19/3, 2020 at 8:42 Comment(2)
I don't understand how this works but it does workNolasco
@Nolasco 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 appearSharell
C
1

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.

Chloras answered 29/9, 2021 at 8:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.