Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions packages/flutter/lib/src/cupertino/nav_bar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -294,9 +294,18 @@ Widget _wrapWithBackground({
);

final bool darkBackground = backgroundColor.computeLuminance() < 0.179;
SystemChrome.setSystemUIOverlayStyle(
darkBackground ? SystemUiOverlayStyle.light : SystemUiOverlayStyle.dark
);
// TODO(jonahwilliams): remove once we have platform themes.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in general i wouldn't bother with this kind of TODO. Either we eventually add platform themes and remove it, or we don't and this TODO isn't necessary.

I recommend reserving TODOs for more fundamental things where we know there's a limitation to the current implementation but we are intentionally cutting corners for some reason (e.g. because we are waiting an upstream fix).

switch (defaultTargetPlatform) {
case TargetPlatform.iOS:
SystemChrome.setSystemUIOverlayStyle(
darkBackground ? SystemUiOverlayStyle.light : SystemUiOverlayStyle.dark
);
break;
case TargetPlatform.android:
case TargetPlatform.fuchsia:
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.dark);
}


if (backgroundColor.alpha == 0xFF)
return childWithBackground;
Expand Down
14 changes: 11 additions & 3 deletions packages/flutter/lib/src/material/app_bar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -346,9 +346,17 @@ class _AppBarState extends State<AppBar> {
TextStyle sideStyle = widget.textTheme?.body1 ?? themeData.primaryTextTheme.body1;

final Brightness brightness = widget.brightness ?? themeData.primaryColorBrightness;
SystemChrome.setSystemUIOverlayStyle(brightness == Brightness.dark
? SystemUiOverlayStyle.light
: SystemUiOverlayStyle.dark);
// TODO(jonahwilliams): remove once we have platform themes.
switch (defaultTargetPlatform) {
case TargetPlatform.iOS:
SystemChrome.setSystemUIOverlayStyle(brightness == Brightness.dark
? SystemUiOverlayStyle.light
: SystemUiOverlayStyle.dark);
break;
case TargetPlatform.android:
case TargetPlatform.fuchsia:
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.dark);
}

if (widget.toolbarOpacity != 1.0) {
final double opacity = const Interval(0.25, 1.0, curve: Curves.fastOutSlowIn).transform(widget.toolbarOpacity);
Expand Down
16 changes: 2 additions & 14 deletions packages/flutter/lib/src/material/theme_data.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import 'dart:ui' show Color, hashValues;

import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';

import 'button_theme.dart';
Expand All @@ -16,20 +17,7 @@ import 'input_decorator.dart';
import 'slider_theme.dart';
import 'typography.dart';

/// Describes the contrast needs of a color.
enum Brightness {
/// The color is dark and will require a light text color to achieve readable
/// contrast.
///
/// For example, the color might be dark grey, requiring white text.
dark,

/// The color is light and will require a dark text color to achieve readable
/// contrast.
///
/// For example, the color might be bright white, requiring black text.
light,
}
export 'package:flutter/services.dart' show Brightness;

// Deriving these values is black magic. The spec claims that pressed buttons
// have a highlight of 0x66999999, but that's clearly wrong. The videos in the
Expand Down
139 changes: 130 additions & 9 deletions packages/flutter/lib/src/services/system_chrome.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// found in the LICENSE file.

import 'dart:async';
import 'dart:ui';

import 'package:flutter/foundation.dart';

Expand Down Expand Up @@ -77,17 +78,142 @@ enum SystemUiOverlay {
bottom,
}

/// Describes the contrast needs of a color.
enum Brightness {
/// The color is dark and will require a light text color to achieve readable
/// contrast.
///
/// For example, the color might be dark grey, requiring white text.
dark,

/// The color is light and will require a dark text color to achieve readable
/// contrast.
///
/// For example, the color might be bright white, requiring black text.
light,
}

/// Specifies a preference for the style of the system overlays.
///
/// Used by [SystemChrome.setSystemUIOverlayStyle].
enum SystemUiOverlayStyle {
class SystemUiOverlayStyle {
/// System overlays should be drawn with a light color. Intended for
/// applications with a dark background.
light,
static const SystemUiOverlayStyle light = const SystemUiOverlayStyle(
systemNavigationBarColor: const Color(0xFFFFFFFF),
systemNavigationBarDividerColor: null,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't we want a shade of gray here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since I haven't gotten a chance to play with the P preview I don't really know what the behavior is. null makes sure the API isn't invoked yet.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. I imagine that we'll have to render this divider on the framework side anyway.

statusBarColor: null,
systemNavigationBarIconBrightness: Brightness.dark,
statusBarIconBrightness: Brightness.dark,
statusBarBrightness: Brightness.dark,
);

/// System overlays should be drawn with a dark color. Intended for
/// applications with a light background.
dark,
static const SystemUiOverlayStyle dark = const SystemUiOverlayStyle(
systemNavigationBarColor: const Color(0xFF000000),
systemNavigationBarDividerColor: null,
statusBarColor: null,
systemNavigationBarIconBrightness: Brightness.light,
statusBarIconBrightness: Brightness.light,
statusBarBrightness: Brightness.light,
);

/// Creates a new [SystemUiOverlayStyle].
const SystemUiOverlayStyle({
this.systemNavigationBarColor,
this.systemNavigationBarDividerColor,
this.systemNavigationBarIconBrightness,
this.statusBarColor,
this.statusBarBrightness,
this.statusBarIconBrightness,
});

/// The color of the system bottom navigation bar.
///
/// Only honored in Android versions O and greater.
final Color systemNavigationBarColor;

/// The color of the divider between the system's bottom navigation bar and the app's content.
///
/// Only honored in Android versions P and greater.
final Color systemNavigationBarDividerColor;

/// The brightness of the system navigation bar icons.
///
/// Only honored in Android versions O and greater.
final Brightness systemNavigationBarIconBrightness;

/// The color of top status bar.
///
/// Only honored in Android version M and greater.
final Color statusBarColor;

/// The brightness of top status bar.
///
/// Only honored in iOS .
final Brightness statusBarBrightness;

/// The brightness of the top status bar icons.
///
/// Only honored in Android version M and greater.
final Brightness statusBarIconBrightness;

/// Convert this event to a map for serialization.
Map<String, dynamic> _toMap() {
return <String, dynamic>{
'systemNavigationBarColor': systemNavigationBarColor?.value,
'systemNavigationBarDividerColor': systemNavigationBarDividerColor?.value,
'statusBarColor': statusBarColor?.value,
'statusBarBrightness': statusBarBrightness?.toString(),
'statusBarIconBrightness': statusBarIconBrightness?.toString(),
'systemNavigationBarIconBrightness': systemNavigationBarIconBrightness?.toString(),
};
}

/// Creates a copy of this theme with the given fields replaced with new values.
SystemUiOverlayStyle copyWith({
Color systemNavigationBarColor,
Color systemNavigationBarDividerColor,
Color statusBarColor,
Brightness statusBarBrightness,
Brightness statusBarIconBrightness,
Brightness systemNavigationBarIconBrightness,
}) {
return new SystemUiOverlayStyle(
systemNavigationBarColor: systemNavigationBarColor ?? this.systemNavigationBarColor,
systemNavigationBarDividerColor: systemNavigationBarDividerColor ?? this.systemNavigationBarDividerColor,
statusBarColor: statusBarColor ?? this.statusBarColor,
statusBarIconBrightness: statusBarIconBrightness ?? this.statusBarIconBrightness,
statusBarBrightness: statusBarBrightness ?? this.statusBarBrightness,
systemNavigationBarIconBrightness: systemNavigationBarIconBrightness ?? this.systemNavigationBarIconBrightness,
);
}

@override
int get hashCode {
return hashValues(
systemNavigationBarColor,
systemNavigationBarDividerColor,
statusBarColor,
statusBarBrightness,
statusBarIconBrightness,
systemNavigationBarIconBrightness,
);
}

@override
bool operator ==(dynamic other) {
if (other.runtimeType != runtimeType)
return false;
final SystemUiOverlayStyle typedOther = other;
return typedOther.systemNavigationBarColor == systemNavigationBarColor
&& typedOther.systemNavigationBarDividerColor == systemNavigationBarDividerColor
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these should be indented so that the expressions line up

&& typedOther.statusBarColor == statusBarColor
&& typedOther.statusBarIconBrightness == statusBarIconBrightness
&& typedOther.statusBarBrightness == statusBarBrightness
&& typedOther.systemNavigationBarIconBrightness == systemNavigationBarIconBrightness;
}
}

List<String> _stringify(List<dynamic> list) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function could be written or just inlined as

list.map((item) => item.toString()).toList()

The toList() might not be needed either, depending the implementation of invokeMethod.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't write this code so I'm going to leave it as is

Expand Down Expand Up @@ -193,14 +319,9 @@ class SystemChrome {
scheduleMicrotask(() {
assert(_pendingStyle != null);
if (_pendingStyle != _latestStyle) {
// TODO(jonahwilliams): remove when rolling chrome change.
SystemChannels.platform.invokeMethod(
'SystemChrome.setSystemUIOverlayStyle',
<String, dynamic>{
'statusBarBrightness': _pendingStyle == SystemUiOverlayStyle.light
? 'Brightness.light'
: 'Brightness.dark',
}
_pendingStyle._toMap(),
);
_latestStyle = _pendingStyle;
}
Expand Down