mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
Draggable can be accepted when the data is null (#97355)
This commit is contained in:
parent
9e7cc970ea
commit
2ad0ac0ef2
@ -16,9 +16,9 @@ class ExampleDragTarget extends StatefulWidget {
|
||||
class ExampleDragTargetState extends State<ExampleDragTarget> {
|
||||
Color _color = Colors.grey;
|
||||
|
||||
void _handleAccept(Color data) {
|
||||
void _handleAccept(Color? data) {
|
||||
setState(() {
|
||||
_color = data;
|
||||
_color = data!;
|
||||
});
|
||||
}
|
||||
|
||||
@ -215,7 +215,7 @@ class MovableBall extends StatelessWidget {
|
||||
);
|
||||
} else {
|
||||
return DragTarget<bool>(
|
||||
onAccept: (bool data) { callback(position); },
|
||||
onAccept: (bool? data) { callback(position); },
|
||||
builder: (BuildContext context, List<bool?> accepted, List<dynamic> rejected) {
|
||||
return dashedBall;
|
||||
},
|
||||
|
@ -81,9 +81,9 @@ class _MyStatefulWidgetState extends State<MyStatefulWidget> {
|
||||
),
|
||||
);
|
||||
},
|
||||
onAccept: (int data) {
|
||||
onAccept: (int? data) {
|
||||
setState(() {
|
||||
acceptedData += data;
|
||||
acceptedData += data!;
|
||||
});
|
||||
},
|
||||
),
|
||||
|
@ -20,7 +20,7 @@ typedef DragTargetWillAccept<T> = bool Function(T? data);
|
||||
/// Signature for causing a [DragTarget] to accept the given data.
|
||||
///
|
||||
/// Used by [DragTarget.onAccept].
|
||||
typedef DragTargetAccept<T> = void Function(T data);
|
||||
typedef DragTargetAccept<T> = void Function(T? data);
|
||||
|
||||
/// Signature for determining information about the acceptance by a [DragTarget].
|
||||
///
|
||||
@ -638,7 +638,7 @@ class DragTargetDetails<T> {
|
||||
DragTargetDetails({required this.data, required this.offset}) : assert(offset != null);
|
||||
|
||||
/// The data that was dropped onto this [DragTarget].
|
||||
final T data;
|
||||
final T? data;
|
||||
|
||||
/// The global position when the specific pointer event occurred on
|
||||
/// the draggable.
|
||||
@ -767,14 +767,14 @@ class _DragTargetState<T extends Object> extends State<DragTarget<T>> {
|
||||
setState(() {
|
||||
_candidateAvatars.remove(avatar);
|
||||
});
|
||||
widget.onAccept?.call(avatar.data! as T);
|
||||
widget.onAcceptWithDetails?.call(DragTargetDetails<T>(data: avatar.data! as T, offset: avatar._lastOffset!));
|
||||
widget.onAccept?.call(avatar.data as T?);
|
||||
widget.onAcceptWithDetails?.call(DragTargetDetails<T>(data: avatar.data as T?, offset: avatar._lastOffset!));
|
||||
}
|
||||
|
||||
void didMove(_DragAvatar<Object> avatar) {
|
||||
if (!mounted)
|
||||
return;
|
||||
widget.onMove?.call(DragTargetDetails<T>(data: avatar.data! as T, offset: avatar._lastOffset!));
|
||||
widget.onMove?.call(DragTargetDetails<T>(data: avatar.data as T?, offset: avatar._lastOffset!));
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -39,7 +39,9 @@ void main() {
|
||||
return const SizedBox(height: 100.0, child: Text('Target'));
|
||||
},
|
||||
onMove: (_) => moveCount++,
|
||||
onAccept: accepted.add,
|
||||
onAccept: (int? data) {
|
||||
accepted.add(data!);
|
||||
},
|
||||
onAcceptWithDetails: acceptedDetails.add,
|
||||
),
|
||||
],
|
||||
@ -91,9 +93,60 @@ void main() {
|
||||
expect(moveCount, 1);
|
||||
});
|
||||
|
||||
testWidgets('Draggable can be accepted when the data is null', (WidgetTester tester) async {
|
||||
// Regression test for https://github.com/flutter/flutter/issues/84816
|
||||
final Map<String, int?> receivedData = <String, int?>{};
|
||||
|
||||
await tester.pumpWidget(MaterialApp(
|
||||
home: Column(
|
||||
children: <Widget>[
|
||||
const Draggable<int>(
|
||||
feedback: Text('Dragging'),
|
||||
child: Text('Source'),
|
||||
),
|
||||
DragTarget<int>(
|
||||
builder: (BuildContext context, List<int?> data, List<dynamic> rejects) {
|
||||
return const SizedBox(height: 100.0, child: Text('Target 1'));
|
||||
},
|
||||
onWillAccept: (int? data) {
|
||||
receivedData['onWillAccept'] = data;
|
||||
return true;
|
||||
},
|
||||
onAccept: (int? data) {
|
||||
receivedData['onAccept'] = data;
|
||||
},
|
||||
onAcceptWithDetails: (DragTargetDetails<int> details) {
|
||||
receivedData['onAcceptWithDetails'] = details.data;
|
||||
},
|
||||
onMove: (DragTargetDetails<int> details) {
|
||||
receivedData['onMove'] = details.data;
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
));
|
||||
|
||||
final Offset firstLocation = tester.getCenter(find.text('Source'));
|
||||
final TestGesture gesture = await tester.startGesture(firstLocation, pointer: 7);
|
||||
await tester.pump();
|
||||
|
||||
final Offset secondLocation = tester.getCenter(find.text('Target 1'));
|
||||
await gesture.moveTo(secondLocation);
|
||||
await tester.pump();
|
||||
|
||||
await gesture.up();
|
||||
await tester.pump();
|
||||
|
||||
expect(receivedData.length, 4);
|
||||
expect(receivedData['onWillAccept'], null);
|
||||
expect(receivedData['onMove'], null);
|
||||
expect(receivedData['onAccept'], null);
|
||||
expect(receivedData['onAcceptWithDetails'], null);
|
||||
});
|
||||
|
||||
// Regression test for https://github.com/flutter/flutter/issues/76825
|
||||
testWidgets('Drag and drop - onLeave callback fires correctly with generic parameter', (WidgetTester tester) async {
|
||||
final Map<String,int> leftBehind = <String,int>{
|
||||
final Map<String, int> leftBehind = <String, int>{
|
||||
'Target 1': 0,
|
||||
'Target 2': 0,
|
||||
};
|
||||
@ -168,7 +221,7 @@ void main() {
|
||||
});
|
||||
|
||||
testWidgets('Drag and drop - onLeave callback fires correctly', (WidgetTester tester) async {
|
||||
final Map<String,int> leftBehind = <String,int>{
|
||||
final Map<String, int> leftBehind = <String, int>{
|
||||
'Target 1': 0,
|
||||
'Target 2': 0,
|
||||
};
|
||||
@ -244,7 +297,7 @@ void main() {
|
||||
|
||||
// Regression test for https://github.com/flutter/flutter/issues/76825
|
||||
testWidgets('Drag and drop - onMove callback fires correctly with generic parameter', (WidgetTester tester) async {
|
||||
final Map<String,int> targetMoveCount = <String,int>{
|
||||
final Map<String, int> targetMoveCount = <String, int>{
|
||||
'Target 1': 0,
|
||||
'Target 2': 0,
|
||||
};
|
||||
@ -263,7 +316,7 @@ void main() {
|
||||
},
|
||||
onMove: (DragTargetDetails<int> details) {
|
||||
targetMoveCount['Target 1'] =
|
||||
targetMoveCount['Target 1']! + details.data;
|
||||
targetMoveCount['Target 1']! + details.data!;
|
||||
},
|
||||
),
|
||||
DragTarget<int>(
|
||||
@ -272,7 +325,7 @@ void main() {
|
||||
},
|
||||
onMove: (DragTargetDetails<int> details) {
|
||||
targetMoveCount['Target 2'] =
|
||||
targetMoveCount['Target 2']! + details.data;
|
||||
targetMoveCount['Target 2']! + details.data!;
|
||||
},
|
||||
),
|
||||
],
|
||||
@ -317,7 +370,7 @@ void main() {
|
||||
});
|
||||
|
||||
testWidgets('Drag and drop - onMove callback fires correctly', (WidgetTester tester) async {
|
||||
final Map<String,int> targetMoveCount = <String,int>{
|
||||
final Map<String, int> targetMoveCount = <String, int>{
|
||||
'Target 1': 0,
|
||||
'Target 2': 0,
|
||||
};
|
||||
@ -1167,7 +1220,9 @@ void main() {
|
||||
builder: (BuildContext context, List<int?> data, List<dynamic> rejects) {
|
||||
return const SizedBox(height: 100.0, child: Text('Target'));
|
||||
},
|
||||
onAccept: accepted.add,
|
||||
onAccept: (int? data) {
|
||||
accepted.add(data!);
|
||||
},
|
||||
onAcceptWithDetails: acceptedDetails.add,
|
||||
),
|
||||
],
|
||||
@ -1243,7 +1298,9 @@ void main() {
|
||||
);
|
||||
},
|
||||
onWillAccept: (int? data) => false,
|
||||
onAccept: accepted.add,
|
||||
onAccept: (int? data) {
|
||||
accepted.add(data!);
|
||||
},
|
||||
onAcceptWithDetails: acceptedDetails.add,
|
||||
),
|
||||
],
|
||||
@ -1316,7 +1373,9 @@ void main() {
|
||||
return const SizedBox(height: 100.0, child: Text('Target'));
|
||||
},
|
||||
onWillAccept: (int? data) => false,
|
||||
onAccept: accepted.add,
|
||||
onAccept: (int? data) {
|
||||
accepted.add(data!);
|
||||
},
|
||||
onAcceptWithDetails: acceptedDetails.add,
|
||||
),
|
||||
]),
|
||||
@ -1366,7 +1425,9 @@ void main() {
|
||||
return const SizedBox(height: 100.0, child: Text('Target'));
|
||||
},
|
||||
onWillAccept: (int? data) => false,
|
||||
onAccept: accepted.add,
|
||||
onAccept: (int? data) {
|
||||
accepted.add(data!);
|
||||
},
|
||||
onAcceptWithDetails: acceptedDetails.add,
|
||||
),
|
||||
],
|
||||
@ -1580,7 +1641,9 @@ void main() {
|
||||
);
|
||||
},
|
||||
onWillAccept: (int? data) => false,
|
||||
onAccept: accepted.add,
|
||||
onAccept: (int? data) {
|
||||
accepted.add(data!);
|
||||
},
|
||||
onAcceptWithDetails: acceptedDetails.add,
|
||||
),
|
||||
],
|
||||
@ -1648,7 +1711,9 @@ void main() {
|
||||
builder: (BuildContext context, List<int?> data, List<dynamic> rejects) {
|
||||
return const SizedBox(height: 100.0, child: Text('Target'));
|
||||
},
|
||||
onAccept: accepted.add,
|
||||
onAccept: (int? data) {
|
||||
accepted.add(data!);
|
||||
},
|
||||
onAcceptWithDetails: acceptedDetails.add,
|
||||
),
|
||||
],
|
||||
@ -1789,7 +1854,9 @@ void main() {
|
||||
builder: (BuildContext context, List<int?> data, List<dynamic> rejects) {
|
||||
return const SizedBox(height: 100.0, child: Text('Target'));
|
||||
},
|
||||
onAccept: accepted.add,
|
||||
onAccept: (int? data) {
|
||||
accepted.add(data!);
|
||||
},
|
||||
onAcceptWithDetails: acceptedDetails.add,
|
||||
),
|
||||
],
|
||||
@ -1867,7 +1934,9 @@ void main() {
|
||||
),
|
||||
);
|
||||
},
|
||||
onAccept: acceptedInts.add,
|
||||
onAccept: (int? data) {
|
||||
acceptedInts.add(data!);
|
||||
},
|
||||
onAcceptWithDetails: acceptedIntsDetails.add,
|
||||
),
|
||||
DragTarget<double>(
|
||||
@ -1879,7 +1948,9 @@ void main() {
|
||||
),
|
||||
);
|
||||
},
|
||||
onAccept: acceptedDoubles.add,
|
||||
onAccept: (double? data) {
|
||||
acceptedDoubles.add(data!);
|
||||
},
|
||||
onAcceptWithDetails: acceptedDoublesDetails.add,
|
||||
),
|
||||
],
|
||||
@ -1995,7 +2066,9 @@ void main() {
|
||||
child: Text('Target1'),
|
||||
),
|
||||
);
|
||||
}, onAccept: acceptedDragTargetDatas.add,
|
||||
}, onAccept: (DragTargetData? data) {
|
||||
acceptedDragTargetDatas.add(data!);
|
||||
},
|
||||
onAcceptWithDetails: acceptedDragTargetDataDetails.add,
|
||||
),
|
||||
DragTarget<ExtendedDragTargetData>(
|
||||
@ -2007,7 +2080,9 @@ void main() {
|
||||
),
|
||||
);
|
||||
},
|
||||
onAccept: acceptedExtendedDragTargetDatas.add,
|
||||
onAccept: (ExtendedDragTargetData? data) {
|
||||
acceptedExtendedDragTargetDatas.add(data!);
|
||||
},
|
||||
onAcceptWithDetails: acceptedExtendedDragTargetDataDetails.add,
|
||||
),
|
||||
],
|
||||
@ -2057,7 +2132,9 @@ void main() {
|
||||
builder: (BuildContext context, List<int?> data, List<dynamic> rejects) {
|
||||
return const SizedBox(height: 100.0, child: Text('Target'));
|
||||
},
|
||||
onAccept: accepted.add,
|
||||
onAccept: (int? data) {
|
||||
accepted.add(data!);
|
||||
},
|
||||
onAcceptWithDetails: acceptedDetails.add,
|
||||
),
|
||||
],
|
||||
@ -2316,7 +2393,9 @@ void main() {
|
||||
builder: (BuildContext context, List<int?> data, List<dynamic> rejects) {
|
||||
return const SizedBox(height: 100.0, child: Text('Target'));
|
||||
},
|
||||
onAccept: accepted.add,
|
||||
onAccept: (int? data) {
|
||||
accepted.add(data!);
|
||||
},
|
||||
onAcceptWithDetails: acceptedDetails.add,
|
||||
),
|
||||
],
|
||||
@ -2346,7 +2425,9 @@ void main() {
|
||||
builder: (BuildContext context, List<int?> data, List<dynamic> rejects) {
|
||||
return const SizedBox(height: 100.0, child: Text('Target'));
|
||||
},
|
||||
onAccept: accepted.add,
|
||||
onAccept: (int? data) {
|
||||
accepted.add(data!);
|
||||
},
|
||||
onAcceptWithDetails: acceptedDetails.add,
|
||||
),
|
||||
],
|
||||
@ -2426,7 +2507,9 @@ void main() {
|
||||
builder: (BuildContext context, List<int?> data, List<dynamic> rejects) {
|
||||
return const SizedBox(height: 100.0, child: Text('Target'));
|
||||
},
|
||||
onAccept: accepted.add,
|
||||
onAccept: (int? data) {
|
||||
accepted.add(data!);
|
||||
},
|
||||
onAcceptWithDetails: acceptedDetails.add,
|
||||
),
|
||||
],
|
||||
@ -2511,7 +2594,9 @@ void main() {
|
||||
builder: (BuildContext context, List<int?> data, List<dynamic> rejects) {
|
||||
return const SizedBox(height: 100.0, child: Text('Target'));
|
||||
},
|
||||
onAccept: accepted.add,
|
||||
onAccept: (int? data) {
|
||||
accepted.add(data!);
|
||||
},
|
||||
onAcceptWithDetails: acceptedDetails.add,
|
||||
),
|
||||
],
|
||||
@ -2765,7 +2850,9 @@ void main() {
|
||||
builder: (BuildContext context, List<Object?> data, List<dynamic> rejects) {
|
||||
return const SizedBox(height: 100.0, child: Text('Target'));
|
||||
},
|
||||
onAccept: accepted.add,
|
||||
onAccept: (Object? data) {
|
||||
accepted.add(data!);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
@ -2801,7 +2888,9 @@ void main() {
|
||||
builder: (BuildContext context, List<int?> data, List<dynamic> rejects) {
|
||||
return const SizedBox(height: 100.0, child: Text('Target'));
|
||||
},
|
||||
onAccept: accepted.add,
|
||||
onAccept: (int? data) {
|
||||
accepted.add(data!);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
@ -2837,7 +2926,9 @@ void main() {
|
||||
builder: (BuildContext context, List<int?> data, List<dynamic> rejects) {
|
||||
return const SizedBox(height: 100.0, child: Text('Target'));
|
||||
},
|
||||
onAccept: accepted.add,
|
||||
onAccept: (int? data) {
|
||||
accepted.add(data!);
|
||||
},
|
||||
onWillAccept: (int? data) {
|
||||
if (data == null)
|
||||
isReceiveNullDataForCheck = true;
|
||||
@ -3180,7 +3271,9 @@ Future<void> _testChildAnchorFeedbackPosition({ required WidgetTester tester, do
|
||||
builder: (BuildContext context, List<int?> data, List<dynamic> rejects) {
|
||||
return const SizedBox(height: 100.0, child: Text('Target'));
|
||||
},
|
||||
onAccept: accepted.add,
|
||||
onAccept: (int? data) {
|
||||
accepted.add(data!);
|
||||
},
|
||||
onAcceptWithDetails: acceptedDetails.add,
|
||||
),
|
||||
],
|
||||
|
Loading…
Reference in New Issue
Block a user