Skip to content

_DragAvatar.updateDrag, listsMatch calculation may prevent new "lower" DragTarget from being recognized #187543

Description

@xiangh-2018

Steps to reproduce

  1. Run code sample;
  2. Drag "Draggable" to "top", and drop in "top"'s own area; "top" contents does not change because it "will not accept";
  3. Drag & drop "Draggable" to "bottom", without crossing "top"; "bottom" contents changes accordingly;
  4. Drag "Draggable" to "top", and drop in the overlapping area of "top" & "bottom"; "bottom" contents does not change;

Expected results

At step 4, "bottom" contents changes;

Actual results

At step 4, "bottom" contents does not change;

Code sample

Code sample
import 'package:flutter/material.dart';

/// Flutter code sample for [Draggable].

void main() => runApp(const DraggableExampleApp());

class DraggableExampleApp extends StatelessWidget {
  const DraggableExampleApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: const Text('Draggable Sample')),
        body: const DraggableExample(),
      ),
    );
  }
}

class DraggableExample extends StatefulWidget {
  const DraggableExample({super.key});

  @override
  State<DraggableExample> createState() => _DraggableExampleState();
}

class _DraggableExampleState extends State<DraggableExample> {
  final acceptedDataTop = ValueNotifier(0);
  final acceptedDataBottom = ValueNotifier(0);

  @override
  Widget build(BuildContext context) {
    final targetTop = DragTarget<int>(
      builder: (
        BuildContext context,
        List<dynamic> accepted,
        List<dynamic> rejected,
      ) {
        return Container(
          height: 100.0,
          width: 100.0,
          color: Colors.orange.withAlpha(0xc0),
          child: Align(
            alignment: Alignment.topCenter,
            child: ListenableBuilder(
              listenable: acceptedDataTop,
              builder: (ctx, _) {
                return Text('top: ${acceptedDataTop.value}');
              },
            ),
          ),
        );
      },
      onWillAcceptWithDetails: (DragTargetDetails<int> details) {
        return false;
      },
      onAcceptWithDetails: (DragTargetDetails<int> details) {
        acceptedDataTop.value += details.data;
      },
    );

    final targetBottom = DragTarget<int>(
      builder: (
        BuildContext context,
        List<dynamic> accepted,
        List<dynamic> rejected,
      ) {
        return Container(
          height: 100.0,
          width: 100.0,
          color: Colors.cyan.withAlpha(0xc0),
          child: Align(
            alignment: Alignment.bottomCenter,
            child: ListenableBuilder(
              listenable: acceptedDataBottom,
              builder: (ctx, _) {
                return Text('bottom: ${acceptedDataBottom.value}');
              },
            ),
          ),
        );
      },
      onWillAcceptWithDetails: (DragTargetDetails<int> details) {
        return true;
      },
      onAcceptWithDetails: (DragTargetDetails<int> details) {
        acceptedDataBottom.value += details.data;
      },
    );

    return Row(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: <Widget>[
        Draggable<int>(
          // Data is the value this Draggable stores.
          data: 10,
          feedback: Container(
            color: const Color(0x7fff0000),
            height: 100,
            width: 100,
            child: const Icon(Icons.directions_run),
          ),
          childWhenDragging: Container(
            height: 100.0,
            width: 100.0,
            color: Colors.pinkAccent,
            child: const Center(child: Text('Child When Dragging')),
          ),
          child: Container(
            height: 100.0,
            width: 100.0,
            color: Colors.lightGreenAccent,
            child: const Center(child: Text('Draggable')),
          ),
        ),
        Container(
          height: 200.0,
          width: 200.0,
          color: const Color(0xff0f0f0f),
          child: Stack(
            children: [
              Positioned(
                left: 50,
                bottom: 50,
                child: targetBottom,
              ),
              Positioned(
                left: 0,
                top: 0,
                child: targetTop,
              ),
            ],
          ),
        ),
      ],
    );
  }
}

Screenshots or Video

Screenshots / Video demonstration
Screencast.from.2026-06-04.15-23-16.webm

Logs

Logs

No relevant log.

Flutter Doctor output

Doctor output
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.38.5, on Debian GNU/Linux 12 (bookworm) 6.1.0-43-amd64, locale en_US.UTF-8)
[✗] Android toolchain - develop for Android devices
    ✗ Unable to locate Android SDK.
      Install Android Studio from: https://developer.android.com/studio/index.html
      On first launch it will assist you in installing the Android SDK components.
      (or visit https://flutter.dev/to/linux-android-setup for detailed instructions).
      If the Android SDK has been installed to a custom location, please use
      `flutter config --android-sdk` to update to that location.

[✓] Chrome - develop for the web
[✓] Linux toolchain - develop for Linux desktop
[✓] Connected device (2 available)
[✓] Network resources

! Doctor found issues in 1 category.

Metadata

Metadata

Assignees

Labels

P2Important issues not at the top of the work listframeworkflutter/packages/flutter repository. See also f: labels.has reproducible stepsThe issue has been confirmed reproducible and is ready to work onteam-frameworkOwned by Framework teamtriaged-frameworkTriaged by Framework team

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions