Commit fbabb264 authored by NikitaZhelonkin's avatar NikitaZhelonkin Committed by Shi-Hao Hong

Add enableFeedback param to MaterialButton, RawMaterialButton and IconButton (#41972)

* Wire enableFeedback parameter through MaterialButton, RawMaterialButton, and IconButton.
Co-Authored-By: 's avatarShi-Hao Hong <shihaohong@google.com>
parent 2e7d9130
...@@ -60,6 +60,7 @@ class RawMaterialButton extends StatefulWidget { ...@@ -60,6 +60,7 @@ class RawMaterialButton extends StatefulWidget {
this.autofocus = false, this.autofocus = false,
MaterialTapTargetSize materialTapTargetSize, MaterialTapTargetSize materialTapTargetSize,
this.child, this.child,
this.enableFeedback = true,
}) : materialTapTargetSize = materialTapTargetSize ?? MaterialTapTargetSize.padded, }) : materialTapTargetSize = materialTapTargetSize ?? MaterialTapTargetSize.padded,
assert(shape != null), assert(shape != null),
assert(elevation != null && elevation >= 0.0), assert(elevation != null && elevation >= 0.0),
...@@ -259,6 +260,16 @@ class RawMaterialButton extends StatefulWidget { ...@@ -259,6 +260,16 @@ class RawMaterialButton extends StatefulWidget {
/// Defaults to [Clip.none], and must not be null. /// Defaults to [Clip.none], and must not be null.
final Clip clipBehavior; final Clip clipBehavior;
/// Whether detected gestures should provide acoustic and/or haptic feedback.
///
/// For example, on Android a tap will produce a clicking sound and a
/// long-press will produce a short vibration, when feedback is enabled.
///
/// See also:
///
/// * [Feedback] for providing platform-specific feedback to certain actions.
final bool enableFeedback;
@override @override
_RawMaterialButtonState createState() => _RawMaterialButtonState(); _RawMaterialButtonState createState() => _RawMaterialButtonState();
} }
...@@ -367,6 +378,7 @@ class _RawMaterialButtonState extends State<RawMaterialButton> { ...@@ -367,6 +378,7 @@ class _RawMaterialButtonState extends State<RawMaterialButton> {
onHover: _handleHoveredChanged, onHover: _handleHoveredChanged,
onTap: widget.onPressed, onTap: widget.onPressed,
onLongPress: widget.onLongPress, onLongPress: widget.onLongPress,
enableFeedback: widget.enableFeedback,
customBorder: effectiveShape, customBorder: effectiveShape,
child: IconTheme.merge( child: IconTheme.merge(
data: IconThemeData(color: effectiveTextColor), data: IconThemeData(color: effectiveTextColor),
......
...@@ -151,6 +151,7 @@ class IconButton extends StatelessWidget { ...@@ -151,6 +151,7 @@ class IconButton extends StatelessWidget {
this.focusNode, this.focusNode,
this.autofocus = false, this.autofocus = false,
this.tooltip, this.tooltip,
this.enableFeedback = true,
}) : assert(iconSize != null), }) : assert(iconSize != null),
assert(padding != null), assert(padding != null),
assert(alignment != null), assert(alignment != null),
...@@ -269,6 +270,16 @@ class IconButton extends StatelessWidget { ...@@ -269,6 +270,16 @@ class IconButton extends StatelessWidget {
/// used for accessibility. /// used for accessibility.
final String tooltip; final String tooltip;
/// Whether detected gestures should provide acoustic and/or haptic feedback.
///
/// For example, on Android a tap will produce a clicking sound and a
/// long-press will produce a short vibration, when feedback is enabled.
///
/// See also:
///
/// * [Feedback] for providing platform-specific feedback to certain actions.
final bool enableFeedback;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
assert(debugCheckHasMaterial(context)); assert(debugCheckHasMaterial(context));
...@@ -314,6 +325,7 @@ class IconButton extends StatelessWidget { ...@@ -314,6 +325,7 @@ class IconButton extends StatelessWidget {
autofocus: autofocus, autofocus: autofocus,
canRequestFocus: onPressed != null, canRequestFocus: onPressed != null,
onTap: onPressed, onTap: onPressed,
enableFeedback: enableFeedback,
child: result, child: result,
focusColor: focusColor ?? Theme.of(context).focusColor, focusColor: focusColor ?? Theme.of(context).focusColor,
hoverColor: hoverColor ?? Theme.of(context).hoverColor, hoverColor: hoverColor ?? Theme.of(context).hoverColor,
......
...@@ -77,6 +77,7 @@ class MaterialButton extends StatelessWidget { ...@@ -77,6 +77,7 @@ class MaterialButton extends StatelessWidget {
this.animationDuration, this.animationDuration,
this.minWidth, this.minWidth,
this.height, this.height,
this.enableFeedback = true,
this.child, this.child,
}) : assert(clipBehavior != null), }) : assert(clipBehavior != null),
assert(autofocus != null), assert(autofocus != null),
...@@ -355,6 +356,16 @@ class MaterialButton extends StatelessWidget { ...@@ -355,6 +356,16 @@ class MaterialButton extends StatelessWidget {
/// Defaults to the value from the current [ButtonTheme]. /// Defaults to the value from the current [ButtonTheme].
final double height; final double height;
/// Whether detected gestures should provide acoustic and/or haptic feedback.
///
/// For example, on Android a tap will produce a clicking sound and a
/// long-press will produce a short vibration, when feedback is enabled.
///
/// See also:
///
/// * [Feedback] for providing platform-specific feedback to certain actions.
final bool enableFeedback;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final ThemeData theme = Theme.of(context); final ThemeData theme = Theme.of(context);
...@@ -363,6 +374,7 @@ class MaterialButton extends StatelessWidget { ...@@ -363,6 +374,7 @@ class MaterialButton extends StatelessWidget {
return RawMaterialButton( return RawMaterialButton(
onPressed: onPressed, onPressed: onPressed,
onLongPress: onLongPress, onLongPress: onLongPress,
enableFeedback: enableFeedback,
onHighlightChanged: onHighlightChanged, onHighlightChanged: onHighlightChanged,
fillColor: buttonTheme.getFillColor(this), fillColor: buttonTheme.getFillColor(this),
textStyle: theme.textTheme.button.copyWith(color: buttonTheme.getTextColor(this)), textStyle: theme.textTheme.button.copyWith(color: buttonTheme.getTextColor(this)),
......
...@@ -10,6 +10,7 @@ import 'package:flutter_test/flutter_test.dart'; ...@@ -10,6 +10,7 @@ import 'package:flutter_test/flutter_test.dart';
import '../rendering/mock_canvas.dart'; import '../rendering/mock_canvas.dart';
import '../widgets/semantics_tester.dart'; import '../widgets/semantics_tester.dart';
import 'feedback_tester.dart';
class MockOnPressedFunction implements Function { class MockOnPressedFunction implements Function {
int called = 0; int called = 0;
...@@ -398,6 +399,74 @@ void main() { ...@@ -398,6 +399,74 @@ void main() {
expect(focusNode1.hasPrimaryFocus, isTrue); expect(focusNode1.hasPrimaryFocus, isTrue);
expect(focusNode2.hasPrimaryFocus, isFalse); expect(focusNode2.hasPrimaryFocus, isFalse);
}); });
group('feedback', () {
FeedbackTester feedback;
setUp(() {
feedback = FeedbackTester();
});
tearDown(() {
feedback?.dispose();
});
testWidgets('IconButton with disabled feedback', (WidgetTester tester) async {
await tester.pumpWidget(Material(
child: Directionality(
textDirection: TextDirection.ltr,
child: Center(
child: IconButton(
onPressed: () {},
enableFeedback: false,
icon: const Icon(Icons.link),
),
),
),
));
await tester.tap(find.byType(IconButton), pointer: 1);
await tester.pump(const Duration(seconds: 1));
expect(feedback.clickSoundCount, 0);
expect(feedback.hapticCount, 0);
});
testWidgets('IconButton with enabled feedback', (WidgetTester tester) async {
await tester.pumpWidget(Material(
child: Directionality(
textDirection: TextDirection.ltr,
child: Center(
child: IconButton(
onPressed: () {},
enableFeedback: true,
icon: const Icon(Icons.link),
),
),
),
));
await tester.tap(find.byType(IconButton), pointer: 1);
await tester.pump(const Duration(seconds: 1));
expect(feedback.clickSoundCount, 1);
expect(feedback.hapticCount, 0);
});
testWidgets('IconButton with enabled feedback by default', (WidgetTester tester) async {
await tester.pumpWidget(Material(
child: Directionality(
textDirection: TextDirection.ltr,
child: Center(
child: IconButton(
onPressed: () {},
icon: const Icon(Icons.link),
),
),
),
));
await tester.tap(find.byType(IconButton), pointer: 1);
await tester.pump(const Duration(seconds: 1));
expect(feedback.clickSoundCount, 1);
expect(feedback.hapticCount, 0);
});
});
} }
Widget wrap({ Widget child }) { Widget wrap({ Widget child }) {
......
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