diff --git a/examples/flutter_gallery/lib/gallery/app.dart b/examples/flutter_gallery/lib/gallery/app.dart index 08b42167b25..b2b136eab99 100644 --- a/examples/flutter_gallery/lib/gallery/app.dart +++ b/examples/flutter_gallery/lib/gallery/app.dart @@ -43,6 +43,8 @@ class GalleryAppState extends State { bool _useLightTheme = true; bool _showPerformanceOverlay = false; + TargetPlatform platform = defaultTargetPlatform; + @override Widget build(BuildContext context) { Widget home = new GalleryHome( @@ -58,6 +60,11 @@ class GalleryAppState extends State { _showPerformanceOverlay = value; }); } : null, + onPlatformChanged: (TargetPlatform value) { + setState(() { + platform = value; + }); + }, timeDilation: timeDilation, onTimeDilationChanged: (double value) { setState(() { @@ -76,7 +83,7 @@ class GalleryAppState extends State { return new MaterialApp( title: 'Flutter Gallery', color: Colors.grey[500], - theme: _useLightTheme ? _kGalleryLightTheme : _kGalleryDarkTheme, + theme: (_useLightTheme ? _kGalleryLightTheme : _kGalleryDarkTheme).copyWith(platform: platform), showPerformanceOverlay: _showPerformanceOverlay, routes: _kRoutes, home: home, diff --git a/examples/flutter_gallery/lib/gallery/drawer.dart b/examples/flutter_gallery/lib/gallery/drawer.dart index cfe88b44608..8249d531939 100644 --- a/examples/flutter_gallery/lib/gallery/drawer.dart +++ b/examples/flutter_gallery/lib/gallery/drawer.dart @@ -92,7 +92,8 @@ class GalleryDrawer extends StatelessWidget { this.timeDilation, this.onTimeDilationChanged, this.showPerformanceOverlay, - this.onShowPerformanceOverlayChanged + this.onShowPerformanceOverlayChanged, + this.onPlatformChanged, }) : super(key: key) { assert(onThemeChanged != null); assert(onTimeDilationChanged != null); @@ -107,6 +108,8 @@ class GalleryDrawer extends StatelessWidget { final bool showPerformanceOverlay; final ValueChanged onShowPerformanceOverlayChanged; + final ValueChanged onPlatformChanged; + @override Widget build(BuildContext context) { final ThemeData themeData = Theme.of(context); @@ -145,6 +148,40 @@ class GalleryDrawer extends StatelessWidget { ) ); + final Widget mountainViewItem = new DrawerItem( + // on iOS, we don't want to show an Android phone icon + icon: new Icon(defaultTargetPlatform == TargetPlatform.iOS ? Icons.star : Icons.phone_android), + onPressed: () { onPlatformChanged(TargetPlatform.android); }, + selected: Theme.of(context).platform == TargetPlatform.android, + child: new Row( + children: [ + new Flexible(child: new Text('Android')), + new Radio( + value: TargetPlatform.android, + groupValue: Theme.of(context).platform, + onChanged: onPlatformChanged, + ) + ] + ) + ); + + final Widget cupertinoItem = new DrawerItem( + // on iOS, we don't want to show the iPhone icon + icon: new Icon(defaultTargetPlatform == TargetPlatform.iOS ? Icons.star_border : Icons.phone_iphone), + onPressed: () { onPlatformChanged(TargetPlatform.iOS); }, + selected: Theme.of(context).platform == TargetPlatform.iOS, + child: new Row( + children: [ + new Flexible(child: new Text('iOS')), + new Radio( + value: TargetPlatform.iOS, + groupValue: Theme.of(context).platform, + onChanged: onPlatformChanged, + ) + ] + ) + ); + final Widget animateSlowlyItem = new DrawerItem( icon: new Icon(Icons.hourglass_empty), selected: timeDilation != 1.0, @@ -216,14 +253,17 @@ class GalleryDrawer extends StatelessWidget { lightThemeItem, darkThemeItem, new Divider(), + mountainViewItem, + cupertinoItem, + new Divider(), animateSlowlyItem, - // index 5, optional: Performance Overlay + // index 8, optional: Performance Overlay fileAnIssueItem, aboutItem ]; if (onShowPerformanceOverlayChanged != null) { - allDrawerItems.insert(5, new DrawerItem( + allDrawerItems.insert(8, new DrawerItem( icon: new Icon(Icons.assessment), onPressed: () { onShowPerformanceOverlayChanged(!showPerformanceOverlay); }, selected: showPerformanceOverlay, diff --git a/examples/flutter_gallery/lib/gallery/home.dart b/examples/flutter_gallery/lib/gallery/home.dart index 024824bad13..48c7df8f385 100644 --- a/examples/flutter_gallery/lib/gallery/home.dart +++ b/examples/flutter_gallery/lib/gallery/home.dart @@ -76,7 +76,8 @@ class GalleryHome extends StatefulWidget { this.timeDilation, this.onTimeDilationChanged, this.showPerformanceOverlay, - this.onShowPerformanceOverlayChanged + this.onShowPerformanceOverlayChanged, + this.onPlatformChanged, }) : super(key: key) { assert(onThemeChanged != null); assert(onTimeDilationChanged != null); @@ -91,6 +92,8 @@ class GalleryHome extends StatefulWidget { final bool showPerformanceOverlay; final ValueChanged onShowPerformanceOverlayChanged; + final ValueChanged onPlatformChanged; + @override GalleryHomeState createState() => new GalleryHomeState(); } @@ -153,7 +156,8 @@ class GalleryHomeState extends State with SingleTickerProviderState timeDilation: config.timeDilation, onTimeDilationChanged: config.onTimeDilationChanged, showPerformanceOverlay: config.showPerformanceOverlay, - onShowPerformanceOverlayChanged: config.onShowPerformanceOverlayChanged + onShowPerformanceOverlayChanged: config.onShowPerformanceOverlayChanged, + onPlatformChanged: config.onPlatformChanged, ), appBar: new AppBar( expandedHeight: _kFlexibleSpaceMaxHeight, diff --git a/packages/flutter/lib/src/foundation/platform.dart b/packages/flutter/lib/src/foundation/platform.dart index b722842e39e..98224ba691b 100644 --- a/packages/flutter/lib/src/foundation/platform.dart +++ b/packages/flutter/lib/src/foundation/platform.dart @@ -7,6 +7,8 @@ import 'dart:io' show Platform; import 'assertions.dart'; /// The platform that user interaction should adapt to target. +/// +/// The [defaultTargetPlatform] getter returns the current platform. enum TargetPlatform { /// Android: android, @@ -25,7 +27,7 @@ enum TargetPlatform { /// 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 using the -/// platform override APIs (like in [ThemeData.platform] in the material +/// platform override APIs (such as [ThemeData.platform] in the material /// library). TargetPlatform get defaultTargetPlatform { TargetPlatform result; diff --git a/packages/flutter/lib/src/material/theme_data.dart b/packages/flutter/lib/src/material/theme_data.dart index f0723bcccd6..5c48e6a2b37 100644 --- a/packages/flutter/lib/src/material/theme_data.dart +++ b/packages/flutter/lib/src/material/theme_data.dart @@ -332,6 +332,66 @@ class ThemeData { /// Defaults to the current platform. final TargetPlatform platform; + /// Creates a copy of this theme but with the given fields replaced with the new values. + ThemeData copyWith({ + Brightness brightness, + Map primarySwatch, + Color primaryColor, + Brightness primaryColorBrightness, + Color accentColor, + Brightness accentColorBrightness, + Color canvasColor, + Color cardColor, + Color dividerColor, + Color highlightColor, + Color splashColor, + Color selectedRowColor, + Color unselectedWidgetColor, + Color disabledColor, + Color buttonColor, + Color secondaryHeaderColor, + Color textSelectionColor, + Color textSelectionHandleColor, + Color backgroundColor, + Color indicatorColor, + Color hintColor, + Color errorColor, + TextTheme textTheme, + TextTheme primaryTextTheme, + IconThemeData iconTheme, + IconThemeData primaryIconTheme, + TargetPlatform platform, + }) { + return new ThemeData( + brightness: brightness ?? this.brightness, + primaryColor: primaryColor ?? this.primaryColor, + primaryColorBrightness: primaryColorBrightness ?? this.primaryColorBrightness, + accentColor: accentColor ?? this.accentColor, + accentColorBrightness: accentColorBrightness ?? this.accentColorBrightness, + canvasColor: canvasColor ?? this.canvasColor, + cardColor: cardColor ?? this.cardColor, + dividerColor: dividerColor ?? this.dividerColor, + highlightColor: highlightColor ?? this.highlightColor, + splashColor: splashColor ?? this.splashColor, + selectedRowColor: selectedRowColor ?? this.selectedRowColor, + unselectedWidgetColor: unselectedWidgetColor ?? this.unselectedWidgetColor, + disabledColor: disabledColor ?? this.disabledColor, + buttonColor: buttonColor ?? this.buttonColor, + secondaryHeaderColor: secondaryHeaderColor ?? this.secondaryHeaderColor, + textSelectionColor: textSelectionColor ?? this.textSelectionColor, + textSelectionHandleColor: textSelectionHandleColor ?? this.textSelectionHandleColor, + backgroundColor: backgroundColor ?? this.backgroundColor, + indicatorColor: indicatorColor ?? this.indicatorColor, + hintColor: hintColor ?? this.hintColor, + errorColor: errorColor ?? this.errorColor, + textTheme: textTheme ?? this.textTheme, + primaryTextTheme: primaryTextTheme ?? this.primaryTextTheme, + iconTheme: iconTheme ?? this.iconTheme, + primaryIconTheme: primaryIconTheme ?? this.primaryIconTheme, + platform: platform ?? this.platform, + ); + } + /// Linearly interpolate between two themes. static ThemeData lerp(ThemeData begin, ThemeData end, double t) { return new ThemeData.raw( @@ -393,7 +453,8 @@ class ThemeData { (otherData.textTheme == textTheme) && (otherData.primaryTextTheme == primaryTextTheme) && (otherData.iconTheme == iconTheme) && - (otherData.primaryIconTheme == primaryIconTheme); + (otherData.primaryIconTheme == primaryIconTheme) && + (otherData.platform == platform); } @override @@ -417,14 +478,15 @@ class ThemeData { backgroundColor, accentColor, accentColorBrightness, + indicatorColor, hashValues( // Too many values. - indicatorColor, hintColor, errorColor, textTheme, primaryTextTheme, iconTheme, - primaryIconTheme + primaryIconTheme, + platform, ) ); }