title: Flutter change offset of draggable widgets in a stack at the same time as scrolling a SingleChildScrollView
body: <p>I have a stack of widgets in Flutter. The lowest stack is a large image that is contained inside SingleChildScrollView. I've set up a ScrollController so I know when the image has been horizontally scrolled in the view.</p>
  <p>Next in the stack I have several Positioned widgets (these are draggable so that they can moved around independent of each other).</p>
  <p>What I'd like to do is when the SingleChildScrollView is scrolled, I'd like to update the position of each of the positioned widgets higher up the stack.</p>
  <p>I've considered Stream, rebuildAllChildren and ValueNotifier but all seem quite complex for what, on the face of it, should be quite a simple thing to achieve. I'm probably missing something very obvious somewhere!</p>
  <p>Here's my code so far:</p>
  <pre><code>import 'dart:io';
  import 'package:flutter/material.dart';
  import 'package:shared_preferences/shared_preferences.dart';
  
  class LayoutScreen extends StatefulWidget {
    LayoutScreen();
  
    @override
    _LayoutScreenState createState() =&gt; _LayoutScreenState();
  }
  
  class _LayoutScreenState extends State&lt;LayoutScreen&gt; {
    ScrollController _controller;
    Offset boxoneposition;
    BuildContext context;
  
    _scrollListener() {
      print(_controller.offset);
      boxoneposition=Offset(100.0, 100);
      setState(() {
        print(boxoneposition);
        // this was a test - the value of boxoneposition is updated, however the view isn't
      });
   }
  
    @override
    void initState() {
      _controller = ScrollController();
      _controller.addListener(_scrollListener);
  
      boxoneposition = Offset(0.0, 30);
  
      super.initState();
    }
  
    DragBox boxOne() {
      // Trying to set up outside of widget build
      return DragBox(boxoneposition, 'Box One Yep', Colors.blueAccent, 1);
    }
  
    @override
    Widget build(BuildContext context) {
      return Stack(
        children: &lt;Widget&gt;[
  
          SingleChildScrollView(
            scrollDirection: Axis.horizontal,
            controller: _controller,
            child: Container(
              width: 1000,
              height: 1000,
              decoration: BoxDecoration(
                image: DecorationImage(
                  image: AssetImage('assets/images/logo.png'),
                  fit: BoxFit.cover,
                  repeat: ImageRepeat.noRepeat,
                ),
              ),
            ),
          ),
          //DragBox(boxoneposition, 'Box One', Colors.blueAccent, 1),
          boxOne(),
          DragBox(Offset(200.0, 50.0), 'Box Two', Colors.orange, 2),
          DragBox(Offset(300.0, 80.0), 'Box Three', Colors.lightGreen, 3),
        ],
      );
    }
  }
  
  class DragBox extends StatefulWidget {
    final Offset initPos;
    final String label;
    final Color itemColor;
    final int boxnumber;
  
    DragBox(this.initPos, this.label, this.itemColor, this.boxnumber);
  
    @override
    DragBoxState createState() =&gt; DragBoxState();
  }
  
  class DragBoxState extends State&lt;DragBox&gt; {
    Offset position = Offset(0.0, 0.0);
    String imagePath=&quot;&quot;;
  
    @override
    void initState() {
      super.initState();
      position = widget.initPos;
    }
  
    getBoxPic() async {
      SharedPreferences prefs = await SharedPreferences.getInstance();
      setState(() {
        String key='picture'+widget.boxnumber.toString();
        imagePath=prefs.getString(key);
      });
      print(imagePath);
      return File(imagePath);
    }
  
    @override
    Widget build(BuildContext context) {
      return Positioned(
        left: position.dx,
        top: position.dy,
        child: Draggable(
          data: widget.itemColor,
          child: Container(
            width: 100.0,
            height: 100.0,
            color: widget.itemColor,
            child: Center(
              child: 
              Image.asset('assets/images/logo.png')
            ),
          ),
          onDragStarted: () {
            setState(() {
              print(&quot;Foobar&quot;);
            });
          },
          onDraggableCanceled: (velocity, offset) {
            setState(() {
              position = offset;
              if (widget.boxnumber==1) {
                print(&quot;Wibble&quot;);
              }
            });
          },
          feedback: Container(
            width: 120.0,
            height: 120.0,
            color: widget.itemColor.withOpacity(0.5),
            child: Center(
              child: Text(
                widget.label,
                style: TextStyle(
                  color: Colors.white,
                  decoration: TextDecoration.none,
                  fontSize: 18.0,
                ),
              ),
            ),
          ),
        )
      );
    }
  }
  </code></pre>
  <p>Any help greatly appreciated!</p>