Added enableFeedback property to FloatingActionButton (#69826)
This commit is contained in:
parent
02efffc134
commit
d118748737
@ -147,6 +147,7 @@ class FloatingActionButton extends StatelessWidget {
|
||||
this.autofocus = false,
|
||||
this.materialTapTargetSize,
|
||||
this.isExtended = false,
|
||||
this.enableFeedback,
|
||||
}) : assert(elevation == null || elevation >= 0.0),
|
||||
assert(focusElevation == null || focusElevation >= 0.0),
|
||||
assert(hoverElevation == null || hoverElevation >= 0.0),
|
||||
@ -189,6 +190,7 @@ class FloatingActionButton extends StatelessWidget {
|
||||
this.autofocus = false,
|
||||
Widget? icon,
|
||||
required Widget label,
|
||||
this.enableFeedback,
|
||||
}) : assert(elevation == null || elevation >= 0.0),
|
||||
assert(focusElevation == null || focusElevation >= 0.0),
|
||||
assert(hoverElevation == null || hoverElevation >= 0.0),
|
||||
@ -409,6 +411,19 @@ class FloatingActionButton extends StatelessWidget {
|
||||
/// * [MaterialTapTargetSize], for a description of how this affects tap targets.
|
||||
final MaterialTapTargetSize? materialTapTargetSize;
|
||||
|
||||
/// 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.
|
||||
///
|
||||
/// If null, [FloatingActionButtonThemeData.enableFeedback] is used.
|
||||
/// If both are null, then default value is true.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [Feedback] for providing platform-specific feedback to certain actions.
|
||||
final bool? enableFeedback;
|
||||
|
||||
final BoxConstraints _sizeConstraints;
|
||||
|
||||
static const double _defaultElevation = 6;
|
||||
@ -455,6 +470,8 @@ class FloatingActionButton extends StatelessWidget {
|
||||
?? _defaultHighlightElevation;
|
||||
final MaterialTapTargetSize materialTapTargetSize = this.materialTapTargetSize
|
||||
?? theme.materialTapTargetSize;
|
||||
final bool enableFeedback = this.enableFeedback
|
||||
?? floatingActionButtonTheme.enableFeedback ?? true;
|
||||
final TextStyle textStyle = theme.textTheme.button!.copyWith(
|
||||
color: foregroundColor,
|
||||
letterSpacing: 1.2,
|
||||
@ -483,6 +500,7 @@ class FloatingActionButton extends StatelessWidget {
|
||||
focusNode: focusNode,
|
||||
autofocus: autofocus,
|
||||
child: child,
|
||||
enableFeedback: enableFeedback,
|
||||
);
|
||||
|
||||
if (tooltip != null) {
|
||||
|
@ -42,6 +42,7 @@ class FloatingActionButtonThemeData with Diagnosticable {
|
||||
this.disabledElevation,
|
||||
this.highlightElevation,
|
||||
this.shape,
|
||||
this.enableFeedback,
|
||||
});
|
||||
|
||||
/// Color to be used for the unselected, enabled [FloatingActionButton]'s
|
||||
@ -89,6 +90,12 @@ class FloatingActionButtonThemeData with Diagnosticable {
|
||||
/// The shape to be used for the floating action button's [Material].
|
||||
final ShapeBorder? shape;
|
||||
|
||||
/// If specified, defines the feedback property for [FloatingActionButton].
|
||||
///
|
||||
/// If [FloatingActionButton.enableFeedback] is provided, [enableFeedback] is
|
||||
/// ignored.
|
||||
final bool? enableFeedback;
|
||||
|
||||
/// Creates a copy of this object with the given fields replaced with the
|
||||
/// new values.
|
||||
FloatingActionButtonThemeData copyWith({
|
||||
@ -103,6 +110,7 @@ class FloatingActionButtonThemeData with Diagnosticable {
|
||||
double? disabledElevation,
|
||||
double? highlightElevation,
|
||||
ShapeBorder? shape,
|
||||
bool? enableFeedback,
|
||||
}) {
|
||||
return FloatingActionButtonThemeData(
|
||||
foregroundColor: foregroundColor ?? this.foregroundColor,
|
||||
@ -116,6 +124,7 @@ class FloatingActionButtonThemeData with Diagnosticable {
|
||||
disabledElevation: disabledElevation ?? this.disabledElevation,
|
||||
highlightElevation: highlightElevation ?? this.highlightElevation,
|
||||
shape: shape ?? this.shape,
|
||||
enableFeedback: enableFeedback ?? this.enableFeedback,
|
||||
);
|
||||
}
|
||||
|
||||
@ -140,6 +149,7 @@ class FloatingActionButtonThemeData with Diagnosticable {
|
||||
disabledElevation: lerpDouble(a?.disabledElevation, b?.disabledElevation, t),
|
||||
highlightElevation: lerpDouble(a?.highlightElevation, b?.highlightElevation, t),
|
||||
shape: ShapeBorder.lerp(a?.shape, b?.shape, t),
|
||||
enableFeedback: t < 0.5 ? a?.enableFeedback : b?.enableFeedback,
|
||||
);
|
||||
}
|
||||
|
||||
@ -157,6 +167,7 @@ class FloatingActionButtonThemeData with Diagnosticable {
|
||||
disabledElevation,
|
||||
highlightElevation,
|
||||
shape,
|
||||
enableFeedback,
|
||||
);
|
||||
}
|
||||
|
||||
@ -177,7 +188,8 @@ class FloatingActionButtonThemeData with Diagnosticable {
|
||||
&& other.hoverElevation == hoverElevation
|
||||
&& other.disabledElevation == disabledElevation
|
||||
&& other.highlightElevation == highlightElevation
|
||||
&& other.shape == shape;
|
||||
&& other.shape == shape
|
||||
&& other.enableFeedback == enableFeedback;
|
||||
}
|
||||
|
||||
@override
|
||||
@ -196,5 +208,6 @@ class FloatingActionButtonThemeData with Diagnosticable {
|
||||
properties.add(DoubleProperty('disabledElevation', disabledElevation, defaultValue: defaultData.disabledElevation));
|
||||
properties.add(DoubleProperty('highlightElevation', highlightElevation, defaultValue: defaultData.highlightElevation));
|
||||
properties.add(DiagnosticsProperty<ShapeBorder>('shape', shape, defaultValue: defaultData.shape));
|
||||
properties.add(DiagnosticsProperty<bool>('enableFeedback', enableFeedback, defaultValue: defaultData.enableFeedback));
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import 'package:flutter_test/flutter_test.dart';
|
||||
|
||||
import '../rendering/mock_canvas.dart';
|
||||
import '../widgets/semantics_tester.dart';
|
||||
import 'feedback_tester.dart';
|
||||
|
||||
void main() {
|
||||
testWidgets('Floating Action Button control test', (WidgetTester tester) async {
|
||||
@ -963,6 +964,116 @@ void main() {
|
||||
expect(find.byKey(iconKey), findsOneWidget);
|
||||
expect(find.byKey(labelKey), findsNothing);
|
||||
});
|
||||
|
||||
group('feedback', () {
|
||||
late FeedbackTester feedback;
|
||||
|
||||
setUp(() {
|
||||
feedback = FeedbackTester();
|
||||
});
|
||||
|
||||
tearDown(() {
|
||||
feedback.dispose();
|
||||
});
|
||||
|
||||
testWidgets('FloatingActionButton with enabled feedback', (WidgetTester tester) async {
|
||||
const bool enableFeedback = true;
|
||||
|
||||
await tester.pumpWidget(MaterialApp(
|
||||
home: FloatingActionButton(
|
||||
onPressed: () {},
|
||||
enableFeedback: enableFeedback,
|
||||
child: const Icon(Icons.access_alarm),
|
||||
),
|
||||
));
|
||||
|
||||
await tester.tap(find.byType(RawMaterialButton));
|
||||
await tester.pump(const Duration(seconds: 1));
|
||||
expect(feedback.clickSoundCount, 1);
|
||||
expect(feedback.hapticCount, 0);
|
||||
});
|
||||
|
||||
testWidgets('FloatingActionButton with disabled feedback', (WidgetTester tester) async {
|
||||
const bool enableFeedback = false;
|
||||
|
||||
await tester.pumpWidget(MaterialApp(
|
||||
home: FloatingActionButton(
|
||||
onPressed: () {},
|
||||
enableFeedback: enableFeedback,
|
||||
child: const Icon(Icons.access_alarm),
|
||||
),
|
||||
));
|
||||
|
||||
await tester.tap(find.byType(RawMaterialButton));
|
||||
await tester.pump(const Duration(seconds: 1));
|
||||
expect(feedback.clickSoundCount, 0);
|
||||
expect(feedback.hapticCount, 0);
|
||||
});
|
||||
|
||||
testWidgets('FloatingActionButton with enabled feedback by default', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(MaterialApp(
|
||||
home: FloatingActionButton(
|
||||
onPressed: () {},
|
||||
child: const Icon(Icons.access_alarm),
|
||||
),
|
||||
));
|
||||
|
||||
await tester.tap(find.byType(RawMaterialButton));
|
||||
await tester.pump(const Duration(seconds: 1));
|
||||
expect(feedback.clickSoundCount, 1);
|
||||
expect(feedback.hapticCount, 0);
|
||||
});
|
||||
|
||||
testWidgets('FloatingActionButton with disabled feedback using FloatingActionButtonTheme', (WidgetTester tester) async {
|
||||
const bool enableFeedbackTheme = false;
|
||||
final ThemeData theme = ThemeData(
|
||||
floatingActionButtonTheme: const FloatingActionButtonThemeData(
|
||||
enableFeedback: enableFeedbackTheme,
|
||||
),
|
||||
);
|
||||
|
||||
await tester.pumpWidget(MaterialApp(
|
||||
home: Theme(
|
||||
data: theme,
|
||||
child: FloatingActionButton(
|
||||
onPressed: () {},
|
||||
child: const Icon(Icons.access_alarm),
|
||||
),
|
||||
),
|
||||
));
|
||||
|
||||
await tester.tap(find.byType(RawMaterialButton));
|
||||
await tester.pump(const Duration(seconds: 1));
|
||||
expect(feedback.clickSoundCount, 0);
|
||||
expect(feedback.hapticCount, 0);
|
||||
});
|
||||
|
||||
testWidgets('FloatingActionButton.enableFeedback is overriden by FloatingActionButtonThemeData.enableFeedback', (WidgetTester tester) async {
|
||||
const bool enableFeedbackTheme = false;
|
||||
const bool enableFeedback = true;
|
||||
final ThemeData theme = ThemeData(
|
||||
floatingActionButtonTheme: const FloatingActionButtonThemeData(
|
||||
enableFeedback: enableFeedbackTheme,
|
||||
),
|
||||
);
|
||||
|
||||
await tester.pumpWidget(MaterialApp(
|
||||
home: Theme(
|
||||
data: theme,
|
||||
child: FloatingActionButton(
|
||||
enableFeedback: enableFeedback,
|
||||
onPressed: () {},
|
||||
child: const Icon(Icons.access_alarm),
|
||||
),
|
||||
),
|
||||
));
|
||||
|
||||
await tester.tap(find.byType(RawMaterialButton));
|
||||
await tester.pump(const Duration(seconds: 1));
|
||||
expect(feedback.clickSoundCount, 1);
|
||||
expect(feedback.hapticCount, 0);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Offset _rightEdgeOfFab(WidgetTester tester) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user