parent
705cebb239
commit
a178bba5d2
@ -206,6 +206,10 @@ class DataCell {
|
||||
this.placeholder = false,
|
||||
this.showEditIcon = false,
|
||||
this.onTap,
|
||||
this.onLongPress,
|
||||
this.onTapDown,
|
||||
this.onDoubleTap,
|
||||
this.onTapCancel,
|
||||
}) : assert(child != null);
|
||||
|
||||
/// A cell that has no content and has zero width and height.
|
||||
@ -241,14 +245,48 @@ class DataCell {
|
||||
/// Called if the cell is tapped.
|
||||
///
|
||||
/// 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).
|
||||
///
|
||||
/// To define a tap behavior for the entire row, see
|
||||
/// [DataRow.onSelectChanged].
|
||||
final VoidCallback? onTap;
|
||||
final GestureTapCallback? 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.
|
||||
@ -809,8 +847,12 @@ class DataTable extends StatelessWidget {
|
||||
required bool numeric,
|
||||
required bool placeholder,
|
||||
required bool showEditIcon,
|
||||
required VoidCallback? onTap,
|
||||
required GestureTapCallback? onTap,
|
||||
required VoidCallback? onSelectChanged,
|
||||
required GestureTapCallback? onDoubleTap,
|
||||
required GestureLongPressCallback? onLongPress,
|
||||
required GestureTapDownCallback? onTapDown,
|
||||
required GestureTapCancelCallback? onTapCancel,
|
||||
required MaterialStateProperty<Color?>? overlayColor,
|
||||
}) {
|
||||
final ThemeData themeData = Theme.of(context);
|
||||
@ -840,9 +882,17 @@ class DataTable extends StatelessWidget {
|
||||
child: DropdownButtonHideUnderline(child: label),
|
||||
),
|
||||
);
|
||||
if (onTap != null) {
|
||||
if (onTap != null ||
|
||||
onDoubleTap != null ||
|
||||
onLongPress != null ||
|
||||
onTapDown != null ||
|
||||
onTapCancel != null) {
|
||||
label = InkWell(
|
||||
onTap: onTap,
|
||||
onDoubleTap: onDoubleTap,
|
||||
onLongPress: onLongPress,
|
||||
onTapCancel: onTapCancel,
|
||||
onTapDown: onTapDown,
|
||||
child: label,
|
||||
overlayColor: overlayColor,
|
||||
);
|
||||
@ -1000,6 +1050,10 @@ class DataTable extends StatelessWidget {
|
||||
placeholder: cell.placeholder,
|
||||
showEditIcon: cell.showEditIcon,
|
||||
onTap: cell.onTap,
|
||||
onDoubleTap: cell.onDoubleTap,
|
||||
onLongPress: cell.onLongPress,
|
||||
onTapCancel: cell.onTapCancel,
|
||||
onTapDown: cell.onTapDown,
|
||||
onSelectChanged: () => row.onSelectChanged != null ? row.onSelectChanged!(!row.selected) : null,
|
||||
overlayColor: row.color ?? effectiveDataRowColor,
|
||||
);
|
||||
|
@ -54,6 +54,18 @@ void main() {
|
||||
onTap: () {
|
||||
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.tap(find.text('375'));
|
||||
await tester.pump(const Duration(milliseconds: 100));
|
||||
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();
|
||||
|
||||
await tester.tap(find.byType(Checkbox).last);
|
||||
|
Loading…
x
Reference in New Issue
Block a user