Add support for system alert sound (#62086)

* Add SystemSoundType.alert (supported in the engine in flutter/engine#19970)
* Play system alert sound when user tries to dismiss a non-dismissable modal
  barrier
This commit is contained in:
Todd Volkert 2020-07-24 15:49:41 -07:00 committed by GitHub
parent 7782845edd
commit 6e252772d1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 43 additions and 0 deletions

View file

@ -9,9 +9,19 @@ import 'dart:async';
import 'system_channels.dart';
/// A sound provided by the system.
///
/// These sounds may be played with [SystemSound.play].
enum SystemSoundType {
/// A short indication that a button was pressed.
click,
/// A short system alert sound indicating the need for user attention.
///
/// Desktop platforms are the only platforms that support a system alert
/// sound, so on mobile platforms (Android, iOS), this will be ignored. The
/// web platform does not support playing any sounds, so this will be
/// ignored on the web as well.
alert,
}
/// Provides access to the library of short system specific sounds for common
@ -24,6 +34,9 @@ class SystemSound {
/// Play the specified system sound. If that sound is not present on the
/// system, the call is ignored.
///
/// The web platform currently does not support playing sounds, so this call
/// will yield no behavior on that platform.
static Future<void> play(SystemSoundType type) async {
await SystemChannels.platform.invokeMethod<void>(
'SystemSound.play',

View file

@ -7,6 +7,7 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'basic.dart';
import 'container.dart';
@ -103,6 +104,8 @@ class ModalBarrier extends StatelessWidget {
onDismiss: () {
if (dismissible)
Navigator.maybePop(context);
else
SystemSound.play(SystemSoundType.alert);
},
child: Semantics(
label: semanticsDismissible ? semanticsLabel : null,

View file

@ -8,6 +8,7 @@ import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter/gestures.dart' show kSecondaryButton, PointerDeviceKind;
@ -165,6 +166,32 @@ void main() {
hovered = false;
});
testWidgets('ModalBarrier plays system alert sound when user tries to dismiss it', (WidgetTester tester) async {
final List<String> playedSystemSounds = <String>[];
try {
SystemChannels.platform.setMockMethodCallHandler((MethodCall methodCall) async {
if (methodCall.method == 'SystemSound.play')
playedSystemSounds.add(methodCall.arguments as String);
});
final Widget subject = Stack(
textDirection: TextDirection.ltr,
children: <Widget>[
tapTarget,
const ModalBarrier(dismissible: false),
],
);
await tester.pumpWidget(subject);
await tester.tap(find.text('target'));
await tester.pumpWidget(subject);
} finally {
SystemChannels.platform.setMockMethodCallHandler(null);
}
expect(playedSystemSounds, hasLength(1));
expect(playedSystemSounds[0], SystemSoundType.alert.toString());
});
testWidgets('ModalBarrier pops the Navigator when dismissed by primary tap', (WidgetTester tester) async {
final Map<String, WidgetBuilder> routes = <String, WidgetBuilder>{
'/': (BuildContext context) => const FirstWidget(),