Repository: flutter
Issue: Add more docs on EdgeDraggingAutoScroller
Labels: framework,f: scrolling,d: api docs,d: examples,d: stackoverflow,P3,team-framework,triaged-framework

## Steps to Reproduce

1. Execute `flutter run` on the code sample <!-- (see "Code sample" section below) -->
2. Drag an item from a listView within that listView to bottom. The Scrolling responds.  Now try dragging an item from one list to another. <!-- describe steps to demonstrate bug -->
3. The items separate out correctly but when the drag reaches the bottom the listview doesn't scroll <!-- for example "Tap on X and see a crash" -->
4. Couple of observations here:- 
  1. The listener probably needs an onTapDown before it can detect anything so that might be one reason things are not working.
  2.  In the print statements only the original listview details are printed not the target listview which somehow seems like the source listview is the only active one but not the rest. 
  3.  Using GlobalKeys in the listviews hasn't made any difference as far as I could tell. 
  4. I am probably missing something here but can't figure out what.

**Expected results:** <!-- what did you want to see? -->
When an item is dragged out to another listview's top or bottom the target Listview should scroll.

**Actual results:** <!-- what did you see? -->
The scrolling only works if the drag is within the same listview and not another one.

<details>
<summary>Code sample</summary>

```dart
import 'dart:ui';

import 'package:flutter/material.dart';

import 'drag_drop_item.dart';
import 'drag_scrollable_list.dart';
import 'draggable_list.dart';

void main() {
  runApp(const MyApp());
}

class MyCustomScrollBehavior extends MaterialScrollBehavior {
  @override
  Set<PointerDeviceKind> get dragDevices => {
        PointerDeviceKind.touch,
        PointerDeviceKind.mouse,
        // etc.
      };
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      scrollBehavior: MyCustomScrollBehavior(),
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: ListView.builder(
        itemCount: 5,
        scrollDirection: Axis.horizontal,
        itemBuilder: (BuildContext context, int index) {
          return DragDropItem(
            value: List.generate(30, (index) => 'Item $index'),
            vertical: false,
            child: SizedBox(
              width: 300.0,
              child: DragScrollableList(),
            ),
            // child: const DraggableList(
            //   maxHeight: 2500.0,
            //   maxWidth: 350.0,
            // ),
          );
        },
      ),
    );
  }
}
```

```dart
// ignore_for_file: must_be_immutable

import 'package:draggable_listview/drag_drop_item.dart';
import 'package:flutter/material.dart';
import 'package:gesture_x_detector/gesture_x_detector.dart';

class DragScrollableList extends StatelessWidget {
  final ScrollController _controller = ScrollController();
  bool _isDragging = false;

  DragScrollableList({super.key});

  @override
  Widget build(BuildContext context) {
    return Listener(
      onPointerMove: (event) {
        if (!_isDragging) {
          print('Is not Dragging');
          return;
        }
        print('Is Dragging');
        var renderObject = context.findRenderObject() as RenderBox;

        var size = renderObject.size;
        var renderOffset = renderObject.localToGlobal(Offset.zero);
        var dragOffset = event.position;

        if (dragOffset.dx > renderOffset.dx &&
            dragOffset.dx < renderOffset.dx + size.width &&
            dragOffset.dy > renderOffset.dy &&
            dragOffset.dy < renderOffset.dy + size.height) {
          _controller.animateTo(dragOffset.dy + 100,
              duration: const Duration(milliseconds: 200), curve: Curves.ease);
        }

        print('ListView Size: $size');
        print('ListView Offset: $renderOffset');
        print('Drag Offset: $dragOffset');
      },
      child: ListView.builder(
        controller: _controller,
        itemCount: 30,
        itemBuilder: (context, index) => DragDropItem(
          onDragEnded: () => _isDragging = false,
          onDragStarted: () => _isDragging = true,
          value: 'Item $index',
          child: ListTile(
            title: Text('Item $index'),
          ),
        ),
      ),
    );
  }
}
```

```dart
import 'package:flutter/material.dart';

class DragDropItem<T extends Object> extends StatelessWidget {
  final Widget _child;
  final T _value;
  final bool _vertical;

  final VoidCallback? _onDragStarted;
  final VoidCallback? _onDragEnded;

  const DragDropItem({
    super.key,
    required Widget child,
    required T value,
    bool vertical = true,
    VoidCallback? onDragStarted,
    VoidCallback? onDragEnded,
  })  : _onDragEnded = onDragEnded,
        _onDragStarted = onDragStarted,
        _vertical = vertical,
        _child = child,
        _value = value;

  @override
  Widget build(BuildContext context) {
    Widget draggable = LayoutBuilder(
      builder: (context, constraints) {
        return LongPressDraggable<T>(
          data: _value,
          maxSimultaneousDrags: 1,
          childWhenDragging: Opacity(
            opacity: 0.5,
            child: _child,
          ),
          feedback: Material(
            elevation: 4.0,
            child: ConstrainedBox(
              constraints: constraints,
              child: _child,
            ),
          ),
          onDragCompleted: () => _dragEnded(),
          onDragEnd: (details) => _dragEnded(),
          onDragStarted: () => _dragStarted(),
          // onDragUpdate: _onDragUpdate,
          onDraggableCanceled: (velocity, offset) => _dragEnded(),
          child: _child,
        );
      },
    );
    return DragTarget<T>(
      builder: (
        BuildContext context,
        List<T?> candidateData,
        List<dynamic> rejectedData,
      ) {
        if (_vertical) {
          return Column(
            children: _buildChildren(
              context,
              candidateData,
              rejectedData,
              draggable,
            ),
          );
        } else {
          return Row(
            children: _buildChildren(
              context,
              candidateData,
              rejectedData,
              draggable,
            ),
          );
        }
      },
      onAccept: (data) => _dragEnded(),
      // onAcceptWithDetails: _onAcceptWithDetails,
      // onLeave: (data) => _dragEnded(),
      // onMove: _onMove,
      onWillAccept: (data) {
        if (data != null && _value != data) {
          return true;
        }
        return false;
      },
    );
  }

  void _dragEnded() {
    if (_onDragEnded == null) {
      return;
    }
    _onDragEnded!();
  }

  void _dragStarted() {
    if (_onDragStarted == null) {
      return;
    }
    _onDragStarted!();
  }

  List<Widget> _buildChildren(
    BuildContext context,
    List<T?> candidateData,
    List<dynamic> rejectedData,
    Widget draggable,
  ) {
    return <Widget>[
      AnimatedSize(
        duration: const Duration(milliseconds: 100),
        child: candidateData.isEmpty
            ? Container()
            : Opacity(
                opacity: 0.0,
                child: _child,
              ),
      ),
      candidateData.isEmpty ? draggable : _child
    ];
  }
}
```

</details>