Flutter - stop ListView scrolling when interacting with child widget
Asked Answered
F

2

13

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!

Friarbird answered 27/9, 2018 at 19:37 Comment(0)
P
9

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.

Pvc answered 4/5, 2020 at 21:49 Comment(1)
Hi, can you check a similar question of mine as well please #76558274Brunet
M
1

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: [],
      ),
    );
  }
Millburn answered 7/6, 2021 at 9:50 Comment(1)
Simplified Version of @Pvc 's answerLaundes

© 2022 - 2024 — McMap. All rights reserved.