Looking for a 2D scrolling widget

378 views
Skip to first unread message

Stefan Matthias Aust

unread,
Nov 10, 2018, 10:16:08 AM11/10/18
to Flutter Dev
I'm looking for a widget that allows 2D scrolling like a UIScrollView.

I think, Flutter right now only supports 1D scrolling which is – unfortunate.

I tried to build something like a UIScrollView using a Stack with a Positioned child and a GestureDetector for detecting pan gestures. However, the illusion fails once the user tries to "fling" the view. I noticed that there is a velocity but I need help to translate this into the correct animation. Has anybody implemented such a scrolling behaviour already?

I also eventually need bouncing behaviour. Making sure that the offset doesn't get negative is easy but how do I access the stack's size and the child's size to determine the maximum offset? Is this possible without using RenderBoxes? Those are still quite mysterious for me. Is there a way to use a BouncingScrollPhysics which should do the trick for one dimension at least?


Here's my code:

class ScrollablePane extends StatefulWidget {
  final Widget child;

  const ScrollablePane({Key key, this.child}) : super(key: key);

  @override
  _ScrollablePaneState createState() => _ScrollablePaneState();
}

class _ScrollablePaneState extends State<ScrollablePane> {
  Offset offset = Offset.zero;

  @override
  Widget build(BuildContext context) {
    return Stack(
      fit: StackFit.expand,
      children: [
        Positioned(
          left: offset.dx,
          top: offset.dy,
          child: widget.child,
        ),
        GestureDetector(
          onPanUpdate: _onPanUpdate,
          onPanEnd: _onPanEnd,
        ),
      ],
    );
  }

  void _onPanUpdate(DragUpdateDetails d) {
    setState(() {
      offset += d.delta;
    });
  }

  void _onPanEnd(DragEndDetails d) {
    print(d.velocity.pixelsPerSecond);
  }
}

Thanks in advance for any hint to complete the implementation.

Stefan

Harish Balasubramanian

unread,
Nov 10, 2018, 12:25:21 PM11/10/18
to Stefan Matthias Aust, Flutter Dev
try using a singlechildscrollview widget

--
You received this message because you are subscribed to the Google Groups "Flutter Dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to flutter-dev...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Stefan Matthias Aust

unread,
Nov 11, 2018, 6:04:20 AM11/11/18
to Flutter Dev
Harish, 

I'm pretty sure that all built-in widgets support only a single scroll direction. I need to scroll in both directions, though.

At least, I found a way to get the child's size using a GlobalKey, and therefore, I can clamp the scrolling like so:

  void _onPanUpdate(DragUpdateDetails d) {
    final Offset max = key.currentContext.size - context.size;
    setState(() {
      offset = Offset(
        (offset.dx - d.delta.dx).clamp(0.0, max.dx),
        (offset.dy - d.delta.dy).clamp(0.0, max.dy),
      );
    });
  }


Stefan

Eric Seidel

unread,
Nov 12, 2018, 11:52:07 AM11/12/18
to Stefan Matthias Aust, Flutter Dev
Thanks for filing a bug: https://github.com/flutter/flutter/issues/23457

This also came up before when someone was making a maps widget.  https://github.com/apptreesoftware/flutter_map may also be a place to look.
--

Hans Muller

unread,
Nov 12, 2018, 11:56:52 AM11/12/18
to Eric Seidel, eib...@gmail.com, flutt...@googlegroups.com
There's an example of 2D scrolling, with support for "pinch to zoom", in the Flutter gallery demo: https://github.com/flutter/flutter/blob/master/examples/flutter_gallery/lib/demo/material/grid_list_demo.dart

Stefan Matthias Aust

unread,
Nov 14, 2018, 4:32:00 AM11/14/18
to Flutter Dev
Hans, 

thank you. This is what I was looking for.

I wasn't aware of of `AnimationController.fling` which seems to do the "heady lifting" :-)


Stefan
Reply all
Reply to author
Forward
0 new messages