Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flutter - stop ListView scrolling when interacting with child widget

I'm in a bit of a pickle. I'm developing a Flutter app (currently using release 0.8.2 on Windows in Android Studio) and I can't seem to work out this one implementation detail. It's quite possible that it's just so simple I've missed it but I would appreciate it if someone could point me in the right direction!

My problem is: I have a custom color picker widget that I've created that is within a scrolling ListView. In order for the user to interact with the color picker widget properly, I need to stop the ListView from scrolling whenever the user is dragging the color pointer around within the picker but I need to then allow the ListView to be scrolled once the interaction is finished (so I can't just set the physics to a NeverScrollableScrollPhysics).

Here is a link to a screencap of the Interface

I'm currently using a Listener to handle interaction within the color picker and whenever the user drags the pointer around, the ListView scrolls as well. I have tried using a GestureDetector but the pan DestureDetector does not prevent the ListView from scrolling. I tried adding a vertical drag handler to the GestureDetector as well which did prevent the ListView from scrolling but doing this adds a minimum drag distance before the pointer moves since the GestureDetector tries to differentiate between a pan and a vertical drag.

I would love any suggestions or a pointer in the right direction. Thanks!

like image 670
Chris Markus Avatar asked Sep 27 '18 19:09

Chris Markus


People also ask

How do I stop list view scroll in flutter?

How do I stop list view scrolling in flutter? Flutter ListView – Never Scrollable You can make the ListView widget never scrollable by setting physics property to NeverScrollableScrollPhysics().

How do I stop my widgets from scrolling?

Use physics: const NeverScrollableScrollPhysics() in Listview Then you can prevent your widget from beeing scrolled.

What is the difference between SingleChildScrollView ListView and ListView builder?

By using ListView, only the items that are visible are mounted and painted. On the other hand, by using SingleChildScrollView+Column, the entire item list is mounted+painted, even if only a few items are visible. The tradeoff is that ListView is less flexible.

What is ClampingScrollPhysics flutter?

ClampingScrollPhysics class Null safety. Scroll physics for environments that prevent the scroll offset from reaching beyond the bounds of the content. This is the behavior typically seen on Android. See also: ScrollConfiguration, which uses this to provide the default scroll behavior on Android.


2 Answers

It's an old question, but as I struggled with the same issue myself, here is a hack:

 bool _dragOverMap = false;
  GlobalKey _pointerKey = new GlobalKey();

  _checkDrag(Offset position, bool up) {
    if (!up) {
      // find your widget
      RenderBox box = _pointerKey.currentContext.findRenderObject();

      //get offset
      Offset boxOffset = box.localToGlobal(Offset.zero);

      // check if your pointerdown event is inside the widget (you could do the same for the width, in this case I just used the height)
      if (position.dy > boxOffset.dy &&
          position.dy < boxOffset.dy + box.size.height) {
        setState(() {
          _dragOverMap = true;
        });
      }
    } else {
      setState(() {
        _dragOverMap = false;
      });
    }
  }

  @override
  Widget build(BuildContext context) {

    return Scaffold(
      appBar: AppBar(

        title: Text("Scroll Test"),
      ),
      body: new Listener(
        onPointerUp: (ev) {
          _checkDrag(ev.position, true);
        },
        onPointerDown: (ev) {
          _checkDrag(ev.position, false);
        },
        child: ListView(
          // if dragging over your widget, disable scroll, otherwise allow scrolling
          physics:
              _dragOverMap ? NeverScrollableScrollPhysics() : ScrollPhysics(),
          children: [

            ListTile(title: Text("Tile to scroll")),
            Divider(),
              ListTile(title: Text("Tile to scroll")),
            Divider(),
              ListTile(title: Text("Tile to scroll")),
            Divider(),

            // Your widget that you want to prevent to scroll the Listview 
            Container(
              key: _pointerKey, // key for finding the widget
              height: 300,
              width: double.infinity,
              child: FlutterMap(
               // ... just as example, could be anything, in your case use the color picker widget
              ),
            ),
          ],
        ),
      ),
    );
  }
}

Works fine for me, maybe one could simplify a few things, but you get the point.

like image 141
Chris Avatar answered Nov 15 '22 07:11

Chris


It may help you.

  bool _scroll = false;

  _toggleScroll() {
    _scroll = !_scroll;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: ListView(
          // switch scrolling
          physics: _scroll ? NeverScrollableScrollPhysics() : ScrollPhysics(),
          children: [],
      ),
    );
  }
like image 26
Røhäñ Dås Avatar answered Nov 15 '22 08:11

Røhäñ Dås