parent
705cebb239
commit
a178bba5d2
@ -206,6 +206,10 @@ class DataCell {
|
|||||||
this.placeholder = false,
|
this.placeholder = false,
|
||||||
this.showEditIcon = false,
|
this.showEditIcon = false,
|
||||||
this.onTap,
|
this.onTap,
|
||||||
|
this.onLongPress,
|
||||||
|
this.onTapDown,
|
||||||
|
this.onDoubleTap,
|
||||||
|
this.onTapCancel,
|
||||||
}) : assert(child != null);
|
}) : assert(child != null);
|
||||||
|
|
||||||
/// A cell that has no content and has zero width and height.
|
/// A cell that has no content and has zero width and height.
|
||||||
@ -241,14 +245,48 @@ class DataCell {
|
|||||||
/// Called if the cell is tapped.
|
/// Called if the cell is tapped.
|
||||||
///
|
///
|
||||||
/// If non-null, tapping the cell will call this callback. If
|
/// If non-null, tapping the cell will call this callback. If
|
||||||
/// null, tapping the cell will attempt to select the row (if
|
/// null (including [onDoubleTap], [onLongPress], [onTapCancel] and [onTapDown]),
|
||||||
|
/// tapping the cell will attempt to select the row (if
|
||||||
/// [DataRow.onSelectChanged] is provided).
|
/// [DataRow.onSelectChanged] is provided).
|
||||||
///
|
final GestureTapCallback? onTap;
|
||||||
/// To define a tap behavior for the entire row, see
|
|
||||||
/// [DataRow.onSelectChanged].
|
|
||||||
final VoidCallback? onTap;
|
|
||||||
|
|
||||||
bool get _debugInteractive => onTap != null;
|
/// Called when the cell is double tapped.
|
||||||
|
///
|
||||||
|
/// If non-null, tapping the cell will call this callback. If
|
||||||
|
/// null (including [onTap], [onLongPress], [onTapCancel] and [onTapDown]),
|
||||||
|
/// tapping the cell will attempt to select the row (if
|
||||||
|
/// [DataRow.onSelectChanged] is provided).
|
||||||
|
final GestureTapCallback? onDoubleTap;
|
||||||
|
|
||||||
|
/// Called if the cell is long-pressed.
|
||||||
|
///
|
||||||
|
/// If non-null, tapping the cell will invoke this callback. If
|
||||||
|
/// null (including [onDoubleTap], [onTap], [onTapCancel] and [onTapDown]),
|
||||||
|
/// tapping the cell will attempt to select the row (if
|
||||||
|
/// [DataRow.onSelectChanged] is provided).
|
||||||
|
final GestureLongPressCallback? onLongPress;
|
||||||
|
|
||||||
|
/// Called if the cell is tapped down.
|
||||||
|
///
|
||||||
|
/// If non-null, tapping the cell will call this callback. If
|
||||||
|
/// null (including [onTap] [onDoubleTap], [onLongPress] and [onTapCancel]),
|
||||||
|
/// tapping the cell will attempt to select the row (if
|
||||||
|
/// [DataRow.onSelectChanged] is provided).
|
||||||
|
final GestureTapDownCallback? onTapDown;
|
||||||
|
|
||||||
|
/// Called if the user cancels a tap was started on cell.
|
||||||
|
///
|
||||||
|
/// If non-null, cancelling the tap gesture will invoke this callback.
|
||||||
|
/// If null (including [onTap], [onDoubleTap] and [onLongPress]),
|
||||||
|
/// tapping the cell will attempt to select the
|
||||||
|
/// row (if [DataRow.onSelectChanged] is provided).
|
||||||
|
final GestureTapCancelCallback? onTapCancel;
|
||||||
|
|
||||||
|
bool get _debugInteractive => onTap != null ||
|
||||||
|
onDoubleTap != null ||
|
||||||
|
onLongPress != null ||
|
||||||
|
onTapDown != null ||
|
||||||
|
onTapCancel != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A material design data table.
|
/// A material design data table.
|
||||||
@ -809,8 +847,12 @@ class DataTable extends StatelessWidget {
|
|||||||
required bool numeric,
|
required bool numeric,
|
||||||
required bool placeholder,
|
required bool placeholder,
|
||||||
required bool showEditIcon,
|
required bool showEditIcon,
|
||||||
required VoidCallback? onTap,
|
required GestureTapCallback? onTap,
|
||||||
required VoidCallback? onSelectChanged,
|
required VoidCallback? onSelectChanged,
|
||||||
|
required GestureTapCallback? onDoubleTap,
|
||||||
|
required GestureLongPressCallback? onLongPress,
|
||||||
|
required GestureTapDownCallback? onTapDown,
|
||||||
|
required GestureTapCancelCallback? onTapCancel,
|
||||||
required MaterialStateProperty<Color?>? overlayColor,
|
required MaterialStateProperty<Color?>? overlayColor,
|
||||||
}) {
|
}) {
|
||||||
final ThemeData themeData = Theme.of(context);
|
final ThemeData themeData = Theme.of(context);
|
||||||
@ -840,9 +882,17 @@ class DataTable extends StatelessWidget {
|
|||||||
child: DropdownButtonHideUnderline(child: label),
|
child: DropdownButtonHideUnderline(child: label),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
if (onTap != null) {
|
if (onTap != null ||
|
||||||
|
onDoubleTap != null ||
|
||||||
|
onLongPress != null ||
|
||||||
|
onTapDown != null ||
|
||||||
|
onTapCancel != null) {
|
||||||
label = InkWell(
|
label = InkWell(
|
||||||
onTap: onTap,
|
onTap: onTap,
|
||||||
|
onDoubleTap: onDoubleTap,
|
||||||
|
onLongPress: onLongPress,
|
||||||
|
onTapCancel: onTapCancel,
|
||||||
|
onTapDown: onTapDown,
|
||||||
child: label,
|
child: label,
|
||||||
overlayColor: overlayColor,
|
overlayColor: overlayColor,
|
||||||
);
|
);
|
||||||
@ -1000,6 +1050,10 @@ class DataTable extends StatelessWidget {
|
|||||||
placeholder: cell.placeholder,
|
placeholder: cell.placeholder,
|
||||||
showEditIcon: cell.showEditIcon,
|
showEditIcon: cell.showEditIcon,
|
||||||
onTap: cell.onTap,
|
onTap: cell.onTap,
|
||||||
|
onDoubleTap: cell.onDoubleTap,
|
||||||
|
onLongPress: cell.onLongPress,
|
||||||
|
onTapCancel: cell.onTapCancel,
|
||||||
|
onTapDown: cell.onTapDown,
|
||||||
onSelectChanged: () => row.onSelectChanged != null ? row.onSelectChanged!(!row.selected) : null,
|
onSelectChanged: () => row.onSelectChanged != null ? row.onSelectChanged!(!row.selected) : null,
|
||||||
overlayColor: row.color ?? effectiveDataRowColor,
|
overlayColor: row.color ?? effectiveDataRowColor,
|
||||||
);
|
);
|
||||||
|
@ -54,6 +54,18 @@ void main() {
|
|||||||
onTap: () {
|
onTap: () {
|
||||||
log.add('cell-tap: ${dessert.calories}');
|
log.add('cell-tap: ${dessert.calories}');
|
||||||
},
|
},
|
||||||
|
onDoubleTap: () {
|
||||||
|
log.add('cell-doubleTap: ${dessert.calories}');
|
||||||
|
},
|
||||||
|
onLongPress: () {
|
||||||
|
log.add('cell-longPress: ${dessert.calories}');
|
||||||
|
},
|
||||||
|
onTapCancel: () {
|
||||||
|
log.add('cell-tapCancel: ${dessert.calories}');
|
||||||
|
},
|
||||||
|
onTapDown: (TapDownDetails details) {
|
||||||
|
log.add('cell-tapDown: ${dessert.calories}');
|
||||||
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@ -94,9 +106,41 @@ void main() {
|
|||||||
));
|
));
|
||||||
await tester.pumpAndSettle(const Duration(milliseconds: 200));
|
await tester.pumpAndSettle(const Duration(milliseconds: 200));
|
||||||
|
|
||||||
|
await tester.tap(find.text('375'));
|
||||||
|
await tester.pump(const Duration(milliseconds: 100));
|
||||||
await tester.tap(find.text('375'));
|
await tester.tap(find.text('375'));
|
||||||
|
|
||||||
expect(log, <String>['cell-tap: 375']);
|
expect(log, <String>['cell-doubleTap: 375']);
|
||||||
|
log.clear();
|
||||||
|
|
||||||
|
await tester.longPress(find.text('375'));
|
||||||
|
// The tap down is triggered on gesture down.
|
||||||
|
// Then, the cancel is triggered when the gesture arena
|
||||||
|
// recognizes that the long press overrides the tap event
|
||||||
|
// so it triggers a tap cancel, followed by the long press.
|
||||||
|
expect(log,<String>['cell-tapDown: 375' ,'cell-tapCancel: 375', 'cell-longPress: 375']);
|
||||||
|
log.clear();
|
||||||
|
|
||||||
|
TestGesture gesture = await tester.startGesture(
|
||||||
|
tester.getRect(find.text('375')).center,
|
||||||
|
);
|
||||||
|
await tester.pump(const Duration(milliseconds: 100));
|
||||||
|
// onTapDown callback is registered.
|
||||||
|
expect(log, equals(<String>['cell-tapDown: 375']));
|
||||||
|
await gesture.up();
|
||||||
|
|
||||||
|
await tester.pump(const Duration(seconds: 1));
|
||||||
|
// onTap callback is registered after the gesture is removed.
|
||||||
|
expect(log, equals(<String>['cell-tapDown: 375', 'cell-tap: 375']));
|
||||||
|
log.clear();
|
||||||
|
|
||||||
|
// dragging off the bounds of the cell calls the cancel callback
|
||||||
|
gesture = await tester.startGesture(tester.getRect(find.text('375')).center);
|
||||||
|
await tester.pump(const Duration(milliseconds: 100));
|
||||||
|
await gesture.moveBy(const Offset(0.0, 200.0));
|
||||||
|
await gesture.cancel();
|
||||||
|
expect(log, equals(<String>['cell-tapDown: 375', 'cell-tapCancel: 375']));
|
||||||
|
|
||||||
log.clear();
|
log.clear();
|
||||||
|
|
||||||
await tester.tap(find.byType(Checkbox).last);
|
await tester.tap(find.byType(Checkbox).last);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user