Unverified Commit e9736efb authored by Kate Lovett's avatar Kate Lovett Committed by GitHub

[Framework] Support for Android Fullscreen Modes (#81303)

parent de36e511
......@@ -15,6 +15,36 @@
version: 1
transforms:
# Changes made in https://github.com/flutter/flutter/pull/81303
- title: "Migrate to 'setEnabledSystemUIMode'"
date: 2021-06-08
element:
uris: [ 'services.dart' ]
method: 'setEnabledSystemUIOverlays'
inClass: 'SystemChrome'
changes:
- kind: 'rename'
newName: 'setEnabledSystemUIMode'
- kind: 'removeParameter'
index: 0
- kind: 'addParameter'
index: 0
name: 'mode'
style: required_positional
argumentValue:
expression: 'SystemUiMode.manual'
- kind: 'addParameter'
index: 1
name: 'overlays'
style: optional_named
argumentValue:
expression: '{% overlays %}'
requiredIf: "overlays != ''"
variables:
overlays:
kind: 'fragment'
value: 'arguments[0]'
# Changes made in https://github.com/flutter/flutter/pull/64254
- title: "Migrate to 'removeRenderObjectChild'"
date: 2020-08-20
......
......@@ -14,6 +14,7 @@ import 'package:flutter/scheduler.dart';
import 'asset_bundle.dart';
import 'binary_messenger.dart';
import 'message_codec.dart';
import 'restoration.dart';
import 'system_channels.dart';
......@@ -33,6 +34,7 @@ mixin ServicesBinding on BindingBase, SchedulerBinding {
initLicenses();
SystemChannels.system.setMessageHandler((dynamic message) => handleSystemMessage(message as Object));
SystemChannels.lifecycle.setMessageHandler(_handleLifecycleMessage);
SystemChannels.platform.setMethodCallHandler(_handlePlatformMessage);
readInitialLifecycleStateFromNativeWindow();
}
......@@ -229,6 +231,16 @@ mixin ServicesBinding on BindingBase, SchedulerBinding {
return null;
}
Future<void> _handlePlatformMessage(MethodCall methodCall) async {
final String method = methodCall.method;
// There is only one incoming method call currently possible.
assert(method == 'SystemChrome.systemUIChange');
final List<dynamic> args = methodCall.arguments as List<dynamic>;
if (_systemUiChangeCallback != null) {
await _systemUiChangeCallback!(args[0] as bool);
}
}
static AppLifecycleState? _parseAppLifecycleMessage(String message) {
switch (message) {
case 'AppLifecycleState.paused':
......@@ -263,8 +275,32 @@ mixin ServicesBinding on BindingBase, SchedulerBinding {
RestorationManager createRestorationManager() {
return RestorationManager();
}
SystemUiChangeCallback? _systemUiChangeCallback;
/// Sets the callback for the `SystemChrome.systemUIChange` method call
/// received on the [SystemChannels.platform] channel.
///
/// This is typically not called directly. System UI changes that this method
/// responds to are associated with [SystemUiMode]s, which are configured
/// using [SystemChrome]. Use [SystemChrome.setSystemUIChangeCallback] to configure
/// along with other SystemChrome settings.
///
/// See also:
///
/// * [SystemChrome.setEnabledSystemUIMode], which specifies the
/// [SystemUiMode] to have visible when the application is running.
void setSystemUiChangeCallback(SystemUiChangeCallback? callback) {
_systemUiChangeCallback = callback;
}
}
/// Signature for listening to changes in the [SystemUiMode].
///
/// Set by [SystemChrome.setSystemUIChangeCallback].
typedef SystemUiChangeCallback = Future<void> Function(bool systemOverlaysAreVisible);
/// The default implementation of [BinaryMessenger].
///
/// This messenger sends messages from the app-side to the platform-side and
......
......@@ -100,7 +100,15 @@ class SystemChannels {
/// * `SystemChrome.setEnabledSystemUIOverlays`: Specifies the set of system
/// overlays to have visible when the application is running. The argument
/// is a [List] of values which are string representations of values of the
/// [SystemUiOverlay] enum. See [SystemChrome.setEnabledSystemUIOverlays].
/// [SystemUiOverlay] enum. See [SystemChrome.setEnabledSystemUIMode].
/// [SystemUiOverlay]s can only be configured individually when using
/// [SystemUiMode.manual].
///
/// * `SystemChrome.setEnabledSystemUIMode`: Specifies the [SystemUiMode] for
/// the application. The optional `overlays` argument is a [List] of values
/// which are string representations of values of the [SystemUiOverlay]
/// enum when using [SystemUiMode.manual]. See
/// [SystemChrome.setEnabledSystemUIMode].
///
/// * `SystemChrome.setSystemUIOverlayStyle`: Specifies whether system
/// overlays (e.g. the status bar on Android or iOS) should be `light` or
......@@ -110,6 +118,15 @@ class SystemChannels {
/// * `SystemNavigator.pop`: Tells the operating system to close the
/// application, or the closest equivalent. See [SystemNavigator.pop].
///
/// The following incoming methods are defined for this channel (registered
/// using [MethodChannel.setMethodCallHandler]):
///
/// * `SystemChrome.systemUIChange`: The user has changed the visibility of
/// the system overlays. This is relevant when using [SystemUiMode]s
/// through [SystemChrome.setEnabledSystemUIMode]. See
/// [SystemChrome.setSystemUIChangeCallback] to respond to this change in
/// application state.
///
/// Calls to methods that are not implemented on the shell side are ignored
/// (so it is safe to call methods when the relevant plugin might be missing).
static const MethodChannel platform = OptionalMethodChannel(
......
......@@ -89,16 +89,80 @@ void main() {
));
});
test('setEnabledSystemUIMode control test', () async {
final List<MethodCall> log = <MethodCall>[];
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async {
log.add(methodCall);
});
await SystemChrome.setEnabledSystemUIMode(SystemUiMode.leanBack);
expect(log, hasLength(1));
expect(log.single, isMethodCall(
'SystemChrome.setEnabledSystemUIMode',
arguments: 'SystemUiMode.leanBack',
));
});
test('setEnabledSystemUIMode asserts for overlays in manual configuration', () async {
expect(
() async {
await SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual);
},
throwsA(
isA<AssertionError>().having((AssertionError error) => error.toString(),
'description', contains('mode == SystemUiMode.manual && overlays != null')),
),
);
});
test('setEnabledSystemUIMode passes correct overlays for manual configuration', () async {
final List<MethodCall> log = <MethodCall>[];
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async {
log.add(methodCall);
});
await SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: <SystemUiOverlay>[SystemUiOverlay.top]);
expect(log, hasLength(1));
expect(log.single, isMethodCall(
'SystemChrome.setEnabledSystemUIOverlays',
arguments: <String>['SystemUiOverlay.top'],
));
});
test('setSystemUIChangeCallback control test', () async {
final List<MethodCall> log = <MethodCall>[];
TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger.setMockMethodCallHandler(SystemChannels.platform, (MethodCall methodCall) async {
log.add(methodCall);
});
await SystemChrome.setSystemUIChangeCallback(null);
expect(log, hasLength(0));
await SystemChrome.setSystemUIChangeCallback((bool overlaysAreVisible) async {});
expect(log, hasLength(1));
expect(log.single, isMethodCall(
'SystemChrome.setSystemUIChangeListener',
arguments: null,
));
});
test('toString works as intended', () async {
const SystemUiOverlayStyle systemUiOverlayStyle = SystemUiOverlayStyle();
expect(systemUiOverlayStyle.toString(), 'SystemUiOverlayStyle({'
'systemNavigationBarColor: null, '
'systemNavigationBarDividerColor: null, '
'systemStatusBarContrastEnforced: true, '
'statusBarColor: null, '
'statusBarBrightness: null, '
'statusBarIconBrightness: null, '
'systemNavigationBarIconBrightness: null})',
'systemNavigationBarIconBrightness: null, '
'systemNavigationBarContrastEnforced: true})',
);
});
}
......@@ -18,4 +18,10 @@ void main() {
layoutDirection: TextDirection.ltr,
);
viewId = textureController.id;
// Changes made in https://github.com/flutter/flutter/pull/81303
await SystemChrome.setEnabledSystemUIOverlays(<SystemUiOverlay>[SystemUiOverlay.top]);
await SystemChrome.setEnabledSystemUIOverlays(<SystemUiOverlay>[SystemUiOverlay.bottom]);
await SystemChrome.setEnabledSystemUIOverlays(<SystemUiOverlay>[SystemUiOverlay.top, SystemUiOverlay.bottom]);
await SystemChrome.setEnabledSystemUIOverlays(<SystemUiOverlay>[]);
}
......@@ -18,4 +18,10 @@ void main() {
layoutDirection: TextDirection.ltr,
);
viewId = textureController.viewId;
// Changes made in https://github.com/flutter/flutter/pull/81303
await SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: <SystemUiOverlay>[SystemUiOverlay.top]);
await SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: <SystemUiOverlay>[SystemUiOverlay.bottom]);
await SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: <SystemUiOverlay>[SystemUiOverlay.top, SystemUiOverlay.bottom]);
await SystemChrome.setEnabledSystemUIMode(SystemUiMode.manual, overlays: <SystemUiOverlay>[]);
}
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