Unverified Commit a4ae59ba authored by Pedro Massango's avatar Pedro Massango Committed by GitHub

Fix "Support configurable hit test behavior on Draggable and DragTarget" (#74047)

parent 51078bcb
...@@ -72,3 +72,4 @@ nt4f04uNd <nt4f04und@gmail.com> ...@@ -72,3 +72,4 @@ nt4f04uNd <nt4f04und@gmail.com>
Anurag Roy <anuragr9847@gmail.com> Anurag Roy <anuragr9847@gmail.com>
Andrey Kabylin <andrey@kabylin.ru> Andrey Kabylin <andrey@kabylin.ru>
vimerzhao <vimerzhao@gmail.com> vimerzhao <vimerzhao@gmail.com>
Pedro Massango <pedromassango.developer@gmail.com>
...@@ -199,6 +199,7 @@ class Draggable<T extends Object> extends StatefulWidget { ...@@ -199,6 +199,7 @@ class Draggable<T extends Object> extends StatefulWidget {
this.onDragCompleted, this.onDragCompleted,
this.ignoringFeedbackSemantics = true, this.ignoringFeedbackSemantics = true,
this.rootOverlay = false, this.rootOverlay = false,
this.hitTestBehavior = HitTestBehavior.deferToChild,
}) : assert(child != null), }) : assert(child != null),
assert(feedback != null), assert(feedback != null),
assert(ignoringFeedbackSemantics != null), assert(ignoringFeedbackSemantics != null),
...@@ -350,6 +351,11 @@ class Draggable<T extends Object> extends StatefulWidget { ...@@ -350,6 +351,11 @@ class Draggable<T extends Object> extends StatefulWidget {
/// Defaults to false. /// Defaults to false.
final bool rootOverlay; final bool rootOverlay;
/// How to behave during hit test.
///
/// Defaults to [HitTestBehavior.deferToChild].
final HitTestBehavior hitTestBehavior;
/// Creates a gesture recognizer that recognizes the start of the drag. /// Creates a gesture recognizer that recognizes the start of the drag.
/// ///
/// Subclasses can override this function to customize when they start /// Subclasses can override this function to customize when they start
...@@ -539,6 +545,7 @@ class _DraggableState<T extends Object> extends State<Draggable<T>> { ...@@ -539,6 +545,7 @@ class _DraggableState<T extends Object> extends State<Draggable<T>> {
_activeCount < widget.maxSimultaneousDrags!; _activeCount < widget.maxSimultaneousDrags!;
final bool showChild = _activeCount == 0 || widget.childWhenDragging == null; final bool showChild = _activeCount == 0 || widget.childWhenDragging == null;
return Listener( return Listener(
behavior: widget.hitTestBehavior,
onPointerDown: canDrag ? _routePointer : null, onPointerDown: canDrag ? _routePointer : null,
child: showChild ? widget.child : widget.childWhenDragging, child: showChild ? widget.child : widget.childWhenDragging,
); );
...@@ -616,6 +623,7 @@ class DragTarget<T extends Object> extends StatefulWidget { ...@@ -616,6 +623,7 @@ class DragTarget<T extends Object> extends StatefulWidget {
this.onAcceptWithDetails, this.onAcceptWithDetails,
this.onLeave, this.onLeave,
this.onMove, this.onMove,
this.hitTestBehavior = HitTestBehavior.translucent,
}) : super(key: key); }) : super(key: key);
/// Called to build the contents of this widget. /// Called to build the contents of this widget.
...@@ -652,6 +660,11 @@ class DragTarget<T extends Object> extends StatefulWidget { ...@@ -652,6 +660,11 @@ class DragTarget<T extends Object> extends StatefulWidget {
/// Note that this includes entering and leaving the target. /// Note that this includes entering and leaving the target.
final DragTargetMove? onMove; final DragTargetMove? onMove;
/// How to behave during hit testing.
///
/// Defaults to [HitTestBehavior.translucent].
final HitTestBehavior hitTestBehavior;
@override @override
_DragTargetState<T> createState() => _DragTargetState<T>(); _DragTargetState<T> createState() => _DragTargetState<T>();
} }
...@@ -727,7 +740,7 @@ class _DragTargetState<T extends Object> extends State<DragTarget<T>> { ...@@ -727,7 +740,7 @@ class _DragTargetState<T extends Object> extends State<DragTarget<T>> {
assert(widget.builder != null); assert(widget.builder != null);
return MetaData( return MetaData(
metaData: this, metaData: this,
behavior: HitTestBehavior.translucent, behavior: widget.hitTestBehavior,
child: widget.builder(context, _mapAvatarsToData<T>(_candidateAvatars), _mapAvatarsToData<Object>(_rejectedAvatars)), child: widget.builder(context, _mapAvatarsToData<T>(_candidateAvatars), _mapAvatarsToData<Object>(_rejectedAvatars)),
); );
} }
......
...@@ -2874,6 +2874,48 @@ void main() { ...@@ -2874,6 +2874,48 @@ void main() {
), ignoreTransform: true, ignoreRect: true)); ), ignoreTransform: true, ignoreRect: true));
semantics.dispose(); semantics.dispose();
}); });
testWidgets('configurable Draggable hit test behavior', (WidgetTester tester) async {
const HitTestBehavior hitTestBehavior = HitTestBehavior.deferToChild;
await tester.pumpWidget(
MaterialApp(
home: Column(
children: <Widget>[
Draggable<int>(
hitTestBehavior: hitTestBehavior,
feedback: Container(height: 50.0, child: const Text('Draggable')),
child: Container(height: 50.0, child: const Text('Target')),
),
],
),
),
);
expect(tester.widget<Listener>(find.byType(Listener).first).behavior, hitTestBehavior);
});
testWidgets('configurable DragTarget hit test behavior', (WidgetTester tester) async {
const HitTestBehavior hitTestBehavior = HitTestBehavior.deferToChild;
await tester.pumpWidget(
MaterialApp(
home: Column(
children: <Widget>[
DragTarget<int>(
hitTestBehavior: hitTestBehavior,
builder: (BuildContext context, List<int?> data,
List<dynamic> rejects) {
return Container(height: 100.0, child: const Text('Target'));
},
),
],
),
),
);
expect(tester.widget<MetaData>(find.byType(MetaData)).behavior, hitTestBehavior);
});
} }
Future<void> _testLongPressDraggableHapticFeedback({ required WidgetTester tester, required bool hapticFeedbackOnStart, required int expectedHapticFeedbackCount }) async { Future<void> _testLongPressDraggableHapticFeedback({ required WidgetTester tester, required bool hapticFeedbackOnStart, required int expectedHapticFeedbackCount }) async {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment