Unverified Commit bfd27f6b authored by Ian Hickson's avatar Ian Hickson Committed by GitHub

Audit use of defaultTargetPlatform (#36871)

parent 398ac1f6
...@@ -218,8 +218,18 @@ class _CupertinoPickerState extends State<CupertinoPicker> { ...@@ -218,8 +218,18 @@ class _CupertinoPickerState extends State<CupertinoPicker> {
void _handleSelectedItemChanged(int index) { void _handleSelectedItemChanged(int index) {
// Only the haptic engine hardware on iOS devices would produce the // Only the haptic engine hardware on iOS devices would produce the
// intended effects. // intended effects.
if (defaultTargetPlatform == TargetPlatform.iOS bool hasSuitableHapticHardware;
&& index != _lastHapticIndex) { switch (defaultTargetPlatform) {
case TargetPlatform.iOS:
hasSuitableHapticHardware = true;
break;
case TargetPlatform.android:
case TargetPlatform.fuchsia:
hasSuitableHapticHardware = false;
break;
}
assert(hasSuitableHapticHardware != null);
if (hasSuitableHapticHardware && index != _lastHapticIndex) {
_lastHapticIndex = index; _lastHapticIndex = index;
HapticFeedback.selectionClick(); HapticFeedback.selectionClick();
} }
......
...@@ -425,7 +425,7 @@ class _RenderCupertinoSwitch extends RenderConstrainedBox { ...@@ -425,7 +425,7 @@ class _RenderCupertinoSwitch extends RenderConstrainedBox {
} }
void _emitVibration() { void _emitVibration() {
switch(defaultTargetPlatform) { switch (defaultTargetPlatform) {
case TargetPlatform.iOS: case TargetPlatform.iOS:
HapticFeedback.lightImpact(); HapticFeedback.lightImpact();
break; break;
......
...@@ -11,11 +11,11 @@ import '_platform_io.dart' ...@@ -11,11 +11,11 @@ import '_platform_io.dart'
/// This is the default value of [ThemeData.platform] (hence the name). Widgets /// This is the default value of [ThemeData.platform] (hence the name). Widgets
/// from the material library should use [Theme.of] to determine the current /// from the material library should use [Theme.of] to determine the current
/// platform for styling purposes, rather than using [defaultTargetPlatform]. /// platform for styling purposes, rather than using [defaultTargetPlatform].
/// However, if there is widget behavior that depends on the actual underlying /// Widgets and render objects at lower layers that try to emulate the
/// platform, then depending on [defaultTargetPlatform] makes sense. /// underlying platform can depend on [defaultTargetPlatform] directly. The
/// [dart.io.Platform.environment] should be used directly only when it's /// [dart.io.Platform] object should only be used directly when it's critical to
/// critical to actually know the current platform, without any overrides /// actually know the current platform, without any overrides possible (for
/// possible (for example, when a system API is about to be called). /// example, when a system API is about to be called).
/// ///
/// In a test environment, the platform returned is [TargetPlatform.android] /// In a test environment, the platform returned is [TargetPlatform.android]
/// regardless of the host platform. (Android was chosen because the tests were /// regardless of the host platform. (Android was chosen because the tests were
......
...@@ -384,11 +384,11 @@ class AppBar extends StatefulWidget implements PreferredSizeWidget { ...@@ -384,11 +384,11 @@ class AppBar extends StatefulWidget implements PreferredSizeWidget {
@override @override
final Size preferredSize; final Size preferredSize;
bool _getEffectiveCenterTitle(ThemeData themeData) { bool _getEffectiveCenterTitle(ThemeData theme) {
if (centerTitle != null) if (centerTitle != null)
return centerTitle; return centerTitle;
assert(themeData.platform != null); assert(theme.platform != null);
switch (themeData.platform) { switch (theme.platform) {
case TargetPlatform.android: case TargetPlatform.android:
case TargetPlatform.fuchsia: case TargetPlatform.fuchsia:
return false; return false;
...@@ -417,7 +417,7 @@ class _AppBarState extends State<AppBar> { ...@@ -417,7 +417,7 @@ class _AppBarState extends State<AppBar> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
assert(!widget.primary || debugCheckHasMediaQuery(context)); assert(!widget.primary || debugCheckHasMediaQuery(context));
assert(debugCheckHasMaterialLocalizations(context)); assert(debugCheckHasMaterialLocalizations(context));
final ThemeData themeData = Theme.of(context); final ThemeData theme = Theme.of(context);
final AppBarTheme appBarTheme = AppBarTheme.of(context); final AppBarTheme appBarTheme = AppBarTheme.of(context);
final ScaffoldState scaffold = Scaffold.of(context, nullOk: true); final ScaffoldState scaffold = Scaffold.of(context, nullOk: true);
final ModalRoute<dynamic> parentRoute = ModalRoute.of(context); final ModalRoute<dynamic> parentRoute = ModalRoute.of(context);
...@@ -429,16 +429,16 @@ class _AppBarState extends State<AppBar> { ...@@ -429,16 +429,16 @@ class _AppBarState extends State<AppBar> {
IconThemeData overallIconTheme = widget.iconTheme IconThemeData overallIconTheme = widget.iconTheme
?? appBarTheme.iconTheme ?? appBarTheme.iconTheme
?? themeData.primaryIconTheme; ?? theme.primaryIconTheme;
IconThemeData actionsIconTheme = widget.actionsIconTheme IconThemeData actionsIconTheme = widget.actionsIconTheme
?? appBarTheme.actionsIconTheme ?? appBarTheme.actionsIconTheme
?? overallIconTheme; ?? overallIconTheme;
TextStyle centerStyle = widget.textTheme?.title TextStyle centerStyle = widget.textTheme?.title
?? appBarTheme.textTheme?.title ?? appBarTheme.textTheme?.title
?? themeData.primaryTextTheme.title; ?? theme.primaryTextTheme.title;
TextStyle sideStyle = widget.textTheme?.body1 TextStyle sideStyle = widget.textTheme?.body1
?? appBarTheme.textTheme?.body1 ?? appBarTheme.textTheme?.body1
?? themeData.primaryTextTheme.body1; ?? theme.primaryTextTheme.body1;
if (widget.toolbarOpacity != 1.0) { if (widget.toolbarOpacity != 1.0) {
final double opacity = const Interval(0.25, 1.0, curve: Curves.fastOutSlowIn).transform(widget.toolbarOpacity); final double opacity = const Interval(0.25, 1.0, curve: Curves.fastOutSlowIn).transform(widget.toolbarOpacity);
...@@ -477,7 +477,7 @@ class _AppBarState extends State<AppBar> { ...@@ -477,7 +477,7 @@ class _AppBarState extends State<AppBar> {
Widget title = widget.title; Widget title = widget.title;
if (title != null) { if (title != null) {
bool namesRoute; bool namesRoute;
switch (defaultTargetPlatform) { switch (theme.platform) {
case TargetPlatform.android: case TargetPlatform.android:
case TargetPlatform.fuchsia: case TargetPlatform.fuchsia:
namesRoute = true; namesRoute = true;
...@@ -524,7 +524,7 @@ class _AppBarState extends State<AppBar> { ...@@ -524,7 +524,7 @@ class _AppBarState extends State<AppBar> {
leading: leading, leading: leading,
middle: title, middle: title,
trailing: actions, trailing: actions,
centerMiddle: widget._getEffectiveCenterTitle(themeData), centerMiddle: widget._getEffectiveCenterTitle(theme),
middleSpacing: widget.titleSpacing, middleSpacing: widget.titleSpacing,
); );
...@@ -584,7 +584,7 @@ class _AppBarState extends State<AppBar> { ...@@ -584,7 +584,7 @@ class _AppBarState extends State<AppBar> {
} }
final Brightness brightness = widget.brightness final Brightness brightness = widget.brightness
?? appBarTheme.brightness ?? appBarTheme.brightness
?? themeData.primaryColorBrightness; ?? theme.primaryColorBrightness;
final SystemUiOverlayStyle overlayStyle = brightness == Brightness.dark final SystemUiOverlayStyle overlayStyle = brightness == Brightness.dark
? SystemUiOverlayStyle.light ? SystemUiOverlayStyle.light
: SystemUiOverlayStyle.dark; : SystemUiOverlayStyle.dark;
...@@ -596,7 +596,7 @@ class _AppBarState extends State<AppBar> { ...@@ -596,7 +596,7 @@ class _AppBarState extends State<AppBar> {
child: Material( child: Material(
color: widget.backgroundColor color: widget.backgroundColor
?? appBarTheme.color ?? appBarTheme.color
?? themeData.primaryColor, ?? theme.primaryColor,
elevation: widget.elevation elevation: widget.elevation
?? appBarTheme.elevation ?? appBarTheme.elevation
?? _defaultElevation, ?? _defaultElevation,
......
...@@ -263,7 +263,7 @@ class _ModalBottomSheet<T> extends StatefulWidget { ...@@ -263,7 +263,7 @@ class _ModalBottomSheet<T> extends StatefulWidget {
class _ModalBottomSheetState<T> extends State<_ModalBottomSheet<T>> { class _ModalBottomSheetState<T> extends State<_ModalBottomSheet<T>> {
String _getRouteLabel(MaterialLocalizations localizations) { String _getRouteLabel(MaterialLocalizations localizations) {
switch (defaultTargetPlatform) { switch (Theme.of(context).platform) {
case TargetPlatform.iOS: case TargetPlatform.iOS:
return ''; return '';
case TargetPlatform.android: case TargetPlatform.android:
......
...@@ -319,7 +319,7 @@ class AlertDialog extends StatelessWidget { ...@@ -319,7 +319,7 @@ class AlertDialog extends StatelessWidget {
), ),
)); ));
} else { } else {
switch (defaultTargetPlatform) { switch (theme.platform) {
case TargetPlatform.iOS: case TargetPlatform.iOS:
label = semanticLabel; label = semanticLabel;
break; break;
...@@ -587,16 +587,18 @@ class SimpleDialog extends StatelessWidget { ...@@ -587,16 +587,18 @@ class SimpleDialog extends StatelessWidget {
final List<Widget> body = <Widget>[]; final List<Widget> body = <Widget>[];
String label = semanticLabel; String label = semanticLabel;
final ThemeData theme = Theme.of(context);
if (title != null) { if (title != null) {
body.add(Padding( body.add(Padding(
padding: titlePadding, padding: titlePadding,
child: DefaultTextStyle( child: DefaultTextStyle(
style: Theme.of(context).textTheme.title, style: theme.textTheme.title,
child: Semantics(namesRoute: true, child: title), child: Semantics(namesRoute: true, child: title),
), ),
)); ));
} else { } else {
switch (defaultTargetPlatform) { switch (theme.platform) {
case TargetPlatform.iOS: case TargetPlatform.iOS:
label = semanticLabel; label = semanticLabel;
break; break;
......
...@@ -11,6 +11,7 @@ import 'debug.dart'; ...@@ -11,6 +11,7 @@ import 'debug.dart';
import 'list_tile.dart'; import 'list_tile.dart';
import 'material.dart'; import 'material.dart';
import 'material_localizations.dart'; import 'material_localizations.dart';
import 'theme.dart';
/// The possible alignments of a [Drawer]. /// The possible alignments of a [Drawer].
enum DrawerAlignment { enum DrawerAlignment {
...@@ -125,7 +126,7 @@ class Drawer extends StatelessWidget { ...@@ -125,7 +126,7 @@ class Drawer extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
assert(debugCheckHasMaterialLocalizations(context)); assert(debugCheckHasMaterialLocalizations(context));
String label = semanticLabel; String label = semanticLabel;
switch (defaultTargetPlatform) { switch (Theme.of(context).platform) {
case TargetPlatform.iOS: case TargetPlatform.iOS:
label = semanticLabel; label = semanticLabel;
break; break;
...@@ -469,6 +470,17 @@ class DrawerControllerState extends State<DrawerController> with SingleTickerPro ...@@ -469,6 +470,17 @@ class DrawerControllerState extends State<DrawerController> with SingleTickerPro
), ),
); );
} else { } else {
bool platformHasBackButton;
switch (Theme.of(context).platform) {
case TargetPlatform.android:
platformHasBackButton = true;
break;
case TargetPlatform.iOS:
case TargetPlatform.fuchsia:
platformHasBackButton = false;
break;
}
assert(platformHasBackButton != null);
return GestureDetector( return GestureDetector(
key: _gestureDetectorKey, key: _gestureDetectorKey,
onHorizontalDragDown: _handleDragDown, onHorizontalDragDown: _handleDragDown,
...@@ -483,7 +495,7 @@ class DrawerControllerState extends State<DrawerController> with SingleTickerPro ...@@ -483,7 +495,7 @@ class DrawerControllerState extends State<DrawerController> with SingleTickerPro
BlockSemantics( BlockSemantics(
child: GestureDetector( child: GestureDetector(
// On Android, the back button is used to dismiss a modal. // On Android, the back button is used to dismiss a modal.
excludeFromSemantics: defaultTargetPlatform == TargetPlatform.android, excludeFromSemantics: platformHasBackButton,
onTap: close, onTap: close,
child: Semantics( child: Semantics(
label: MaterialLocalizations.of(context)?.modalBarrierDismissLabel, label: MaterialLocalizations.of(context)?.modalBarrierDismissLabel,
......
...@@ -199,8 +199,10 @@ class _FlexibleSpaceBarState extends State<FlexibleSpaceBar> { ...@@ -199,8 +199,10 @@ class _FlexibleSpaceBarState extends State<FlexibleSpaceBar> {
} }
if (widget.title != null) { if (widget.title != null) {
final ThemeData theme = Theme.of(context);
Widget title; Widget title;
switch (defaultTargetPlatform) { switch (theme.platform) {
case TargetPlatform.iOS: case TargetPlatform.iOS:
title = widget.title; title = widget.title;
break; break;
...@@ -212,7 +214,6 @@ class _FlexibleSpaceBarState extends State<FlexibleSpaceBar> { ...@@ -212,7 +214,6 @@ class _FlexibleSpaceBarState extends State<FlexibleSpaceBar> {
); );
} }
final ThemeData theme = Theme.of(context);
final double opacity = settings.toolbarOpacity; final double opacity = settings.toolbarOpacity;
if (opacity > 0.0) { if (opacity > 0.0) {
TextStyle titleStyle = theme.primaryTextTheme.title; TextStyle titleStyle = theme.primaryTextTheme.title;
......
...@@ -748,8 +748,9 @@ Future<T> showMenu<T>({ ...@@ -748,8 +748,9 @@ Future<T> showMenu<T>({
assert(position != null); assert(position != null);
assert(items != null && items.isNotEmpty); assert(items != null && items.isNotEmpty);
assert(debugCheckHasMaterialLocalizations(context)); assert(debugCheckHasMaterialLocalizations(context));
String label = semanticLabel; String label = semanticLabel;
switch (defaultTargetPlatform) { switch (Theme.of(context).platform) {
case TargetPlatform.iOS: case TargetPlatform.iOS:
label = semanticLabel; label = semanticLabel;
break; break;
......
...@@ -53,10 +53,9 @@ class Scrollbar extends StatefulWidget { ...@@ -53,10 +53,9 @@ class Scrollbar extends StatefulWidget {
class _ScrollbarState extends State<Scrollbar> with TickerProviderStateMixin { class _ScrollbarState extends State<Scrollbar> with TickerProviderStateMixin {
ScrollbarPainter _materialPainter; ScrollbarPainter _materialPainter;
TargetPlatform _currentPlatform;
TextDirection _textDirection; TextDirection _textDirection;
Color _themeColor; Color _themeColor;
bool _useCupertinoScrollbar;
AnimationController _fadeoutAnimationController; AnimationController _fadeoutAnimationController;
Animation<double> _fadeoutOpacityAnimation; Animation<double> _fadeoutOpacityAnimation;
Timer _fadeoutTimer; Timer _fadeoutTimer;
...@@ -77,35 +76,36 @@ class _ScrollbarState extends State<Scrollbar> with TickerProviderStateMixin { ...@@ -77,35 +76,36 @@ class _ScrollbarState extends State<Scrollbar> with TickerProviderStateMixin {
@override @override
void didChangeDependencies() { void didChangeDependencies() {
super.didChangeDependencies(); super.didChangeDependencies();
assert((() { _useCupertinoScrollbar = null; return true; })());
final ThemeData theme = Theme.of(context); final ThemeData theme = Theme.of(context);
_currentPlatform = theme.platform; switch (theme.platform) {
switch (_currentPlatform) {
case TargetPlatform.iOS: case TargetPlatform.iOS:
// On iOS, stop all local animations. CupertinoScrollbar has its own // On iOS, stop all local animations. CupertinoScrollbar has its own
// animations. // animations.
_fadeoutTimer?.cancel(); _fadeoutTimer?.cancel();
_fadeoutTimer = null; _fadeoutTimer = null;
_fadeoutAnimationController.reset(); _fadeoutAnimationController.reset();
_useCupertinoScrollbar = true;
break; break;
case TargetPlatform.android: case TargetPlatform.android:
case TargetPlatform.fuchsia: case TargetPlatform.fuchsia:
_themeColor = theme.highlightColor.withOpacity(1.0); _themeColor = theme.highlightColor.withOpacity(1.0);
_textDirection = Directionality.of(context); _textDirection = Directionality.of(context);
_materialPainter = _buildMaterialScrollbarPainter(); _materialPainter = _buildMaterialScrollbarPainter();
_useCupertinoScrollbar = false;
break; break;
} }
assert(_useCupertinoScrollbar != null);
} }
ScrollbarPainter _buildMaterialScrollbarPainter() { ScrollbarPainter _buildMaterialScrollbarPainter() {
return ScrollbarPainter( return ScrollbarPainter(
color: _themeColor, color: _themeColor,
textDirection: _textDirection, textDirection: _textDirection,
thickness: _kScrollbarThickness, thickness: _kScrollbarThickness,
fadeoutOpacityAnimation: _fadeoutOpacityAnimation, fadeoutOpacityAnimation: _fadeoutOpacityAnimation,
padding: MediaQuery.of(context).padding, padding: MediaQuery.of(context).padding,
); );
} }
bool _handleScrollNotification(ScrollNotification notification) { bool _handleScrollNotification(ScrollNotification notification) {
...@@ -116,9 +116,8 @@ class _ScrollbarState extends State<Scrollbar> with TickerProviderStateMixin { ...@@ -116,9 +116,8 @@ class _ScrollbarState extends State<Scrollbar> with TickerProviderStateMixin {
// iOS sub-delegates to the CupertinoScrollbar instead and doesn't handle // iOS sub-delegates to the CupertinoScrollbar instead and doesn't handle
// scroll notifications here. // scroll notifications here.
if (_currentPlatform != TargetPlatform.iOS if (!_useCupertinoScrollbar &&
&& (notification is ScrollUpdateNotification (notification is ScrollUpdateNotification || notification is OverscrollNotification)) {
|| notification is OverscrollNotification)) {
if (_fadeoutAnimationController.status != AnimationStatus.forward) { if (_fadeoutAnimationController.status != AnimationStatus.forward) {
_fadeoutAnimationController.forward(); _fadeoutAnimationController.forward();
} }
...@@ -143,25 +142,21 @@ class _ScrollbarState extends State<Scrollbar> with TickerProviderStateMixin { ...@@ -143,25 +142,21 @@ class _ScrollbarState extends State<Scrollbar> with TickerProviderStateMixin {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
switch (_currentPlatform) { if (_useCupertinoScrollbar) {
case TargetPlatform.iOS: return CupertinoScrollbar(
return CupertinoScrollbar( child: widget.child,
child: widget.child, );
); }
case TargetPlatform.android: return NotificationListener<ScrollNotification>(
case TargetPlatform.fuchsia: onNotification: _handleScrollNotification,
return NotificationListener<ScrollNotification>( child: RepaintBoundary(
onNotification: _handleScrollNotification, child: CustomPaint(
foregroundPainter: _materialPainter,
child: RepaintBoundary( child: RepaintBoundary(
child: CustomPaint( child: widget.child,
foregroundPainter: _materialPainter,
child: RepaintBoundary(
child: widget.child,
),
),
), ),
); ),
} ),
throw FlutterError('Unknown platform for scrollbar insertion'); );
} }
} }
...@@ -485,7 +485,7 @@ class _SearchPageState<T> extends State<_SearchPage<T>> { ...@@ -485,7 +485,7 @@ class _SearchPageState<T> extends State<_SearchPage<T>> {
break; break;
} }
String routeName; String routeName;
switch (defaultTargetPlatform) { switch (theme.platform) {
case TargetPlatform.iOS: case TargetPlatform.iOS:
routeName = ''; routeName = '';
break; break;
......
...@@ -774,14 +774,26 @@ class ThemeData extends Diagnosticable { ...@@ -774,14 +774,26 @@ class ThemeData extends Diagnosticable {
/// The platform the material widgets should adapt to target. /// The platform the material widgets should adapt to target.
/// ///
/// Defaults to the current platform. This should be used in order to style UI /// Defaults to the current platform, as exposed by [defaultTargetPlatform].
/// elements according to platform conventions. /// This should be used in order to style UI elements according to platform
/// conventions.
/// ///
/// [Platform.defaultTargetPlatform] should be used directly instead only in /// Widgets from the material library should use this getter (via [Theme.of])
/// rare cases where it's necessary to determine behavior based on the /// to determine the current platform for the purpose of emulating the
/// platform. [dart.io.Platform.environment] should be used when it's critical /// platform behavior (e.g. scrolling or haptic effects). Widgets and render
/// objects at lower layers that try to emulate the underlying platform
/// platform can depend on [defaultTargetPlatform] directly, or may require
/// that the target platform be provided as an argument. The
/// [dart.io.Platform] object should only be used directly when it's critical
/// to actually know the current platform, without any overrides possible (for /// to actually know the current platform, without any overrides possible (for
/// example, when a system API is about to be called). /// example, when a system API is about to be called).
///
/// In a test environment, the platform returned is [TargetPlatform.android]
/// regardless of the host platform. (Android was chosen because the tests
/// were originally written assuming Android-like behavior, and we added
/// platform adaptations for iOS later). Tests can check iOS behavior by
/// setting the [platform] of the [Theme] explicitly to [TargetPlatform.iOS],
/// or by setting [debugDefaultTargetPlatformOverride].
final TargetPlatform platform; final TargetPlatform platform;
/// Configures the hit test size of certain Material widgets. /// Configures the hit test size of certain Material widgets.
......
...@@ -203,8 +203,13 @@ class _DayPeriodControl extends StatelessWidget { ...@@ -203,8 +203,13 @@ class _DayPeriodControl extends StatelessWidget {
if (fragmentContext.selectedTime.period == DayPeriod.am) { if (fragmentContext.selectedTime.period == DayPeriod.am) {
return; return;
} }
if (fragmentContext.targetPlatform == TargetPlatform.android) { switch (fragmentContext.targetPlatform) {
_announceToAccessibility(context, MaterialLocalizations.of(context).anteMeridiemAbbreviation); case TargetPlatform.android:
case TargetPlatform.fuchsia:
_announceToAccessibility(context, MaterialLocalizations.of(context).anteMeridiemAbbreviation);
break;
case TargetPlatform.iOS:
break;
} }
_togglePeriod(); _togglePeriod();
} }
...@@ -213,8 +218,13 @@ class _DayPeriodControl extends StatelessWidget { ...@@ -213,8 +218,13 @@ class _DayPeriodControl extends StatelessWidget {
if (fragmentContext.selectedTime.period == DayPeriod.pm) { if (fragmentContext.selectedTime.period == DayPeriod.pm) {
return; return;
} }
if (fragmentContext.targetPlatform == TargetPlatform.android) { switch (fragmentContext.targetPlatform) {
_announceToAccessibility(context, MaterialLocalizations.of(context).postMeridiemAbbreviation); case TargetPlatform.android:
case TargetPlatform.fuchsia:
_announceToAccessibility(context, MaterialLocalizations.of(context).postMeridiemAbbreviation);
break;
case TargetPlatform.iOS:
break;
} }
_togglePeriod(); _togglePeriod();
} }
......
...@@ -391,13 +391,8 @@ class RenderEditable extends RenderBox { ...@@ -391,13 +391,8 @@ class RenderEditable extends RenderBox {
// TODO(goderbauer): doesn't handle extended grapheme clusters with more than one Unicode scalar value (https://github.com/flutter/flutter/issues/13404). // TODO(goderbauer): doesn't handle extended grapheme clusters with more than one Unicode scalar value (https://github.com/flutter/flutter/issues/13404).
void _handleKeyEvent(RawKeyEvent keyEvent) { void _handleKeyEvent(RawKeyEvent keyEvent) {
// Only handle key events on Android. // Only handle key events on Android.
switch (defaultTargetPlatform) { if (keyEvent.data is! RawKeyEventDataAndroid)
case TargetPlatform.android: return;
break;
case TargetPlatform.iOS:
case TargetPlatform.fuchsia:
return;
}
if (keyEvent is RawKeyUpEvent) if (keyEvent is RawKeyUpEvent)
return; return;
...@@ -1594,12 +1589,15 @@ class RenderEditable extends RenderBox { ...@@ -1594,12 +1589,15 @@ class RenderEditable extends RenderBox {
/// of the cursor for iOS is approximate and obtained through an eyeball /// of the cursor for iOS is approximate and obtained through an eyeball
/// comparison. /// comparison.
Rect get _getCaretPrototype { Rect get _getCaretPrototype {
switch(defaultTargetPlatform){ assert(defaultTargetPlatform != null);
switch (defaultTargetPlatform) {
case TargetPlatform.iOS: case TargetPlatform.iOS:
return Rect.fromLTWH(0.0, 0.0, cursorWidth, preferredLineHeight + 2); return Rect.fromLTWH(0.0, 0.0, cursorWidth, preferredLineHeight + 2);
default: case TargetPlatform.android:
case TargetPlatform.fuchsia:
return Rect.fromLTWH(0.0, _kCaretHeightOffset, cursorWidth, preferredLineHeight - 2.0 * _kCaretHeightOffset); return Rect.fromLTWH(0.0, _kCaretHeightOffset, cursorWidth, preferredLineHeight - 2.0 * _kCaretHeightOffset);
} }
return null;
} }
@override @override
void performLayout() { void performLayout() {
...@@ -1647,10 +1645,11 @@ class RenderEditable extends RenderBox { ...@@ -1647,10 +1645,11 @@ class RenderEditable extends RenderBox {
if (_cursorOffset != null) if (_cursorOffset != null)
caretRect = caretRect.shift(_cursorOffset); caretRect = caretRect.shift(_cursorOffset);
if (_textPainter.getFullHeightForCaret(textPosition, _caretPrototype) != null) { final double caretHeight = _textPainter.getFullHeightForCaret(textPosition, _caretPrototype);
if (caretHeight != null) {
switch (defaultTargetPlatform) { switch (defaultTargetPlatform) {
case TargetPlatform.iOS: { case TargetPlatform.iOS:
final double heightDiff = _textPainter.getFullHeightForCaret(textPosition, _caretPrototype) - caretRect.height; final double heightDiff = caretHeight - caretRect.height;
// Center the caret vertically along the text. // Center the caret vertically along the text.
caretRect = Rect.fromLTWH( caretRect = Rect.fromLTWH(
caretRect.left, caretRect.left,
...@@ -1659,8 +1658,8 @@ class RenderEditable extends RenderBox { ...@@ -1659,8 +1658,8 @@ class RenderEditable extends RenderBox {
caretRect.height, caretRect.height,
); );
break; break;
} case TargetPlatform.android:
default: { case TargetPlatform.fuchsia:
// Override the height to take the full height of the glyph at the TextPosition // Override the height to take the full height of the glyph at the TextPosition
// when not on iOS. iOS has special handling that creates a taller caret. // when not on iOS. iOS has special handling that creates a taller caret.
// TODO(garyq): See the TODO for _getCaretPrototype. // TODO(garyq): See the TODO for _getCaretPrototype.
...@@ -1668,10 +1667,9 @@ class RenderEditable extends RenderBox { ...@@ -1668,10 +1667,9 @@ class RenderEditable extends RenderBox {
caretRect.left, caretRect.left,
caretRect.top - _kCaretHeightOffset, caretRect.top - _kCaretHeightOffset,
caretRect.width, caretRect.width,
_textPainter.getFullHeightForCaret(textPosition, _caretPrototype), caretHeight,
); );
break; break;
}
} }
} }
......
...@@ -75,7 +75,18 @@ class ModalBarrier extends StatelessWidget { ...@@ -75,7 +75,18 @@ class ModalBarrier extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
assert(!dismissible || semanticsLabel == null || debugCheckHasDirectionality(context)); assert(!dismissible || semanticsLabel == null || debugCheckHasDirectionality(context));
final bool semanticsDismissible = dismissible && defaultTargetPlatform != TargetPlatform.android; bool platformSupportsDismissingBarrier;
switch (defaultTargetPlatform) {
case TargetPlatform.android:
case TargetPlatform.fuchsia:
platformSupportsDismissingBarrier = false;
break;
case TargetPlatform.iOS:
platformSupportsDismissingBarrier = true;
break;
}
assert(platformSupportsDismissingBarrier != null);
final bool semanticsDismissible = dismissible && platformSupportsDismissingBarrier;
final bool modalBarrierSemanticsDismissible = barrierSemanticsDismissible ?? semanticsDismissible; final bool modalBarrierSemanticsDismissible = barrierSemanticsDismissible ?? semanticsDismissible;
return BlockSemantics( return BlockSemantics(
child: ExcludeSemantics( child: ExcludeSemantics(
......
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