Skip to content

Commit e1eb1b9

Browse files
authored
Added onSecondaryTap in InkWell. (#119058)
Exposes onSecondaryTap in InkWell.
1 parent 055769e commit e1eb1b9

2 files changed

Lines changed: 116 additions & 2 deletions

File tree

packages/flutter/lib/src/material/ink_well.dart

Lines changed: 79 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,10 @@ class InkResponse extends StatelessWidget {
294294
this.onTapCancel,
295295
this.onDoubleTap,
296296
this.onLongPress,
297+
this.onSecondaryTap,
298+
this.onSecondaryTapUp,
299+
this.onSecondaryTapDown,
300+
this.onSecondaryTapCancel,
297301
this.onHighlightChanged,
298302
this.onHover,
299303
this.mouseCursor,
@@ -342,6 +346,21 @@ class InkResponse extends StatelessWidget {
342346
/// Called when the user long-presses on this part of the material.
343347
final GestureLongPressCallback? onLongPress;
344348

349+
/// Called when the user taps this part of the material with a secondary button.
350+
final GestureTapCallback? onSecondaryTap;
351+
352+
/// Called when the user taps down on this part of the material with a
353+
/// secondary button.
354+
final GestureTapDownCallback? onSecondaryTapDown;
355+
356+
/// Called when the user releases a secondary button tap that was started on
357+
/// this part of the material. [onSecondaryTap] is called immediately after.
358+
final GestureTapUpCallback? onSecondaryTapUp;
359+
360+
/// Called when the user cancels a secondary button tap that was started on
361+
/// this part of the material.
362+
final GestureTapCallback? onSecondaryTapCancel;
363+
345364
/// Called when this part of the material either becomes highlighted or stops
346365
/// being highlighted.
347366
///
@@ -599,6 +618,10 @@ class InkResponse extends StatelessWidget {
599618
onTapCancel: onTapCancel,
600619
onDoubleTap: onDoubleTap,
601620
onLongPress: onLongPress,
621+
onSecondaryTap: onSecondaryTap,
622+
onSecondaryTapUp: onSecondaryTapUp,
623+
onSecondaryTapDown: onSecondaryTapDown,
624+
onSecondaryTapCancel: onSecondaryTapCancel,
602625
onHighlightChanged: onHighlightChanged,
603626
onHover: onHover,
604627
mouseCursor: mouseCursor,
@@ -651,6 +674,10 @@ class _InkResponseStateWidget extends StatefulWidget {
651674
this.onTapCancel,
652675
this.onDoubleTap,
653676
this.onLongPress,
677+
this.onSecondaryTap,
678+
this.onSecondaryTapUp,
679+
this.onSecondaryTapDown,
680+
this.onSecondaryTapCancel,
654681
this.onHighlightChanged,
655682
this.onHover,
656683
this.mouseCursor,
@@ -684,6 +711,10 @@ class _InkResponseStateWidget extends StatefulWidget {
684711
final GestureTapCallback? onTapCancel;
685712
final GestureTapCallback? onDoubleTap;
686713
final GestureLongPressCallback? onLongPress;
714+
final GestureTapCallback? onSecondaryTap;
715+
final GestureTapUpCallback? onSecondaryTapUp;
716+
final GestureTapDownCallback? onSecondaryTapDown;
717+
final GestureTapCallback? onSecondaryTapCancel;
687718
final ValueChanged<bool>? onHighlightChanged;
688719
final ValueChanged<bool>? onHover;
689720
final MouseCursor? mouseCursor;
@@ -722,6 +753,10 @@ class _InkResponseStateWidget extends StatefulWidget {
722753
if (onTapDown != null) 'tap down',
723754
if (onTapUp != null) 'tap up',
724755
if (onTapCancel != null) 'tap cancel',
756+
if (onSecondaryTap != null) 'secondary tap',
757+
if (onSecondaryTapUp != null) 'secondary tap up',
758+
if (onSecondaryTapDown != null) 'secondary tap down',
759+
if (onSecondaryTapCancel != null) 'secondary tap cancel'
725760
];
726761
properties.add(IterableProperty<String>('gestures', gestures, ifEmpty: '<none>'));
727762
properties.add(DiagnosticsProperty<MouseCursor>('mouseCursor', mouseCursor));
@@ -1040,18 +1075,31 @@ class _InkResponseState extends State<_InkResponseStateWidget>
10401075
widget.onFocusChange?.call(hasFocus);
10411076
}
10421077

1043-
void handleTapDown(TapDownDetails details) {
1078+
void handleAnyTapDown(TapDownDetails details) {
10441079
if (_anyChildInkResponsePressed) {
10451080
return;
10461081
}
10471082
_startNewSplash(details: details);
1083+
}
1084+
1085+
void handleTapDown(TapDownDetails details) {
1086+
handleAnyTapDown(details);
10481087
widget.onTapDown?.call(details);
10491088
}
10501089

10511090
void handleTapUp(TapUpDetails details) {
10521091
widget.onTapUp?.call(details);
10531092
}
10541093

1094+
void handleSecondaryTapDown(TapDownDetails details) {
1095+
handleAnyTapDown(details);
1096+
widget.onSecondaryTapDown?.call(details);
1097+
}
1098+
1099+
void handleSecondaryTapUp(TapUpDetails details) {
1100+
widget.onSecondaryTapUp?.call(details);
1101+
}
1102+
10551103
void _startNewSplash({TapDownDetails? details, BuildContext? context}) {
10561104
assert(details != null || context != null);
10571105

@@ -1110,6 +1158,20 @@ class _InkResponseState extends State<_InkResponseStateWidget>
11101158
}
11111159
}
11121160

1161+
void handleSecondaryTap() {
1162+
_currentSplash?.confirm();
1163+
_currentSplash = null;
1164+
updateHighlight(_HighlightType.pressed, value: false);
1165+
widget.onSecondaryTap?.call();
1166+
}
1167+
1168+
void handleSecondaryTapCancel() {
1169+
_currentSplash?.cancel();
1170+
_currentSplash = null;
1171+
widget.onSecondaryTapCancel?.call();
1172+
updateHighlight(_HighlightType.pressed, value: false);
1173+
}
1174+
11131175
@override
11141176
void deactivate() {
11151177
if (_splashes != null) {
@@ -1130,7 +1192,14 @@ class _InkResponseState extends State<_InkResponseStateWidget>
11301192
}
11311193

11321194
bool isWidgetEnabled(_InkResponseStateWidget widget) {
1133-
return widget.onTap != null || widget.onDoubleTap != null || widget.onLongPress != null || widget.onTapDown != null;
1195+
return widget.onTap != null
1196+
|| widget.onDoubleTap != null
1197+
|| widget.onLongPress != null
1198+
|| widget.onTapUp != null
1199+
|| widget.onTapDown != null
1200+
|| widget.onSecondaryTap != null
1201+
|| widget.onSecondaryTapUp != null
1202+
|| widget.onSecondaryTapDown != null;
11341203
}
11351204

11361205
bool get enabled => isWidgetEnabled(widget);
@@ -1220,6 +1289,10 @@ class _InkResponseState extends State<_InkResponseStateWidget>
12201289
onTapCancel: enabled ? handleTapCancel : null,
12211290
onDoubleTap: widget.onDoubleTap != null ? handleDoubleTap : null,
12221291
onLongPress: widget.onLongPress != null ? handleLongPress : null,
1292+
onSecondaryTapDown: enabled ? handleSecondaryTapDown : null,
1293+
onSecondaryTapUp: enabled ? handleSecondaryTapUp: null,
1294+
onSecondaryTap: enabled ? handleSecondaryTap : null,
1295+
onSecondaryTapCancel: enabled ? handleSecondaryTapCancel : null,
12231296
behavior: HitTestBehavior.opaque,
12241297
excludeFromSemantics: true,
12251298
child: widget.child,
@@ -1326,6 +1399,10 @@ class InkWell extends InkResponse {
13261399
super.onTapDown,
13271400
super.onTapUp,
13281401
super.onTapCancel,
1402+
super.onSecondaryTap,
1403+
super.onSecondaryTapUp,
1404+
super.onSecondaryTapDown,
1405+
super.onSecondaryTapCancel,
13291406
super.onHighlightChanged,
13301407
super.onHover,
13311408
super.mouseCursor,

packages/flutter/test/material/ink_well_test.dart

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2015,4 +2015,41 @@ testWidgets('InkResponse radius can be updated', (WidgetTester tester) async {
20152015
await tester.pump(const Duration(milliseconds: 25));
20162016
expect(inkFeatures, paints..rect(rect: const Rect.fromLTRB(350.0, 250.0, 450.0, 350.0), color: const Color(0x8000ff00)));
20172017
});
2018+
2019+
testWidgets('InkWell secondary tap test', (WidgetTester tester) async {
2020+
final List<String> log = <String>[];
2021+
2022+
await tester.pumpWidget(Directionality(
2023+
textDirection: TextDirection.ltr,
2024+
child: Material(
2025+
child: Center(
2026+
child: InkWell(
2027+
onSecondaryTap: () {
2028+
log.add('secondary-tap');
2029+
},
2030+
onSecondaryTapDown: (TapDownDetails details) {
2031+
log.add('secondary-tap-down');
2032+
},
2033+
onSecondaryTapUp: (TapUpDetails details) {
2034+
log.add('secondary-tap-up');
2035+
},
2036+
onSecondaryTapCancel: () {
2037+
log.add('secondary-tap-cancel');
2038+
},
2039+
),
2040+
),
2041+
),
2042+
));
2043+
2044+
await tester.tap(find.byType(InkWell), pointer: 1, buttons: kSecondaryButton);
2045+
2046+
expect(log, equals(<String>['secondary-tap-down', 'secondary-tap-up', 'secondary-tap']));
2047+
log.clear();
2048+
2049+
final TestGesture gesture = await tester.startGesture(tester.getCenter(find.byType(InkWell)), pointer: 2, buttons: kSecondaryButton);
2050+
await gesture.moveTo(const Offset(100, 100));
2051+
await gesture.up();
2052+
2053+
expect(log, equals(<String>['secondary-tap-down', 'secondary-tap-cancel']));
2054+
});
20182055
}

0 commit comments

Comments
 (0)