Commit 5717cd54 authored by Adam Barth's avatar Adam Barth Committed by GitHub

Add a platform field to Theme (#5024)

We'll use this field to adapt material widgets to iOS.
parent 486b7830
...@@ -14,5 +14,6 @@ export 'src/foundation/basic_types.dart'; ...@@ -14,5 +14,6 @@ export 'src/foundation/basic_types.dart';
export 'src/foundation/binding.dart'; export 'src/foundation/binding.dart';
export 'src/foundation/change_notifier.dart'; export 'src/foundation/change_notifier.dart';
export 'src/foundation/licenses.dart'; export 'src/foundation/licenses.dart';
export 'src/foundation/platform.dart';
export 'src/foundation/print.dart'; export 'src/foundation/print.dart';
export 'src/foundation/synchronous_future.dart'; export 'src/foundation/synchronous_future.dart';
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/// The platform that user interaction should adapt to target.
enum TargetPlatform {
/// Android: <https://www.android.com/>
android,
/// iOS: <http://www.apple.com/ios/>
iOS,
}
...@@ -2,8 +2,6 @@ ...@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:io' show Platform;
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
...@@ -25,6 +23,15 @@ const TextStyle _errorTextStyle = const TextStyle( ...@@ -25,6 +23,15 @@ const TextStyle _errorTextStyle = const TextStyle(
decorationStyle: TextDecorationStyle.double decorationStyle: TextDecorationStyle.double
); );
/// The visual and interaction design for overscroll.
enum OverscrollStyle {
/// Overscrolls are clamped and indicated with a glow.
glow,
/// Overscrolls are not clamped and indicated with elastic physics.
bounce
}
/// An application that uses material design. /// An application that uses material design.
/// ///
/// A convenience widget that wraps a number of widgets that are commonly /// A convenience widget that wraps a number of widgets that are commonly
...@@ -53,6 +60,7 @@ class MaterialApp extends StatefulWidget { ...@@ -53,6 +60,7 @@ class MaterialApp extends StatefulWidget {
this.theme, this.theme,
this.home, this.home,
this.routes: const <String, WidgetBuilder>{}, this.routes: const <String, WidgetBuilder>{},
this.overscrollStyle,
this.onGenerateRoute, this.onGenerateRoute,
this.onLocaleChanged, this.onLocaleChanged,
this.debugShowMaterialGrid: false, this.debugShowMaterialGrid: false,
...@@ -104,6 +112,11 @@ class MaterialApp extends StatefulWidget { ...@@ -104,6 +112,11 @@ class MaterialApp extends StatefulWidget {
/// build the page instead. /// build the page instead.
final Map<String, WidgetBuilder> routes; final Map<String, WidgetBuilder> routes;
/// The visual and interaction design for overscroll.
///
/// Defaults to being adapted to the current [TargetPlatform].
final OverscrollStyle overscrollStyle;
/// The route generator callback used when the app is navigated to a /// The route generator callback used when the app is navigated to a
/// named route. /// named route.
final RouteFactory onGenerateRoute; final RouteFactory onGenerateRoute;
...@@ -149,7 +162,8 @@ class _IndicatorScrollConfigurationDelegate extends ScrollConfigurationDelegate ...@@ -149,7 +162,8 @@ class _IndicatorScrollConfigurationDelegate extends ScrollConfigurationDelegate
@override @override
Widget wrapScrollWidget(Widget scrollWidget) => new OverscrollIndicator(child: scrollWidget); Widget wrapScrollWidget(Widget scrollWidget) => new OverscrollIndicator(child: scrollWidget);
} }
final ScrollConfigurationDelegate _indicatorScroll = new _IndicatorScrollConfigurationDelegate();
final ScrollConfigurationDelegate _glowScroll = new _IndicatorScrollConfigurationDelegate();
final ScrollConfigurationDelegate _bounceScroll = new ScrollConfigurationDelegate(); final ScrollConfigurationDelegate _bounceScroll = new ScrollConfigurationDelegate();
class _MaterialAppState extends State<MaterialApp> { class _MaterialAppState extends State<MaterialApp> {
...@@ -180,6 +194,24 @@ class _MaterialAppState extends State<MaterialApp> { ...@@ -180,6 +194,24 @@ class _MaterialAppState extends State<MaterialApp> {
return null; return null;
} }
ScrollConfigurationDelegate _getScrollDelegate(TargetPlatform platform) {
if (config.overscrollStyle != null) {
switch (config.overscrollStyle) {
case OverscrollStyle.glow:
return _glowScroll;
case OverscrollStyle.bounce:
return _bounceScroll;
}
}
switch (platform) {
case TargetPlatform.android:
return _glowScroll;
case TargetPlatform.iOS:
return _bounceScroll;
}
return null;
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
ThemeData theme = config.theme ?? new ThemeData.fallback(); ThemeData theme = config.theme ?? new ThemeData.fallback();
...@@ -213,7 +245,7 @@ class _MaterialAppState extends State<MaterialApp> { ...@@ -213,7 +245,7 @@ class _MaterialAppState extends State<MaterialApp> {
}); });
return new ScrollConfiguration( return new ScrollConfiguration(
delegate: (Platform.isIOS || Platform.isMacOS) ? _bounceScroll : _indicatorScroll, delegate: _getScrollDelegate(theme.platform),
child: result child: result
); );
} }
......
...@@ -2,8 +2,11 @@ ...@@ -2,8 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
import 'dart:io' show Platform;
import 'dart:ui' show Color, hashValues; import 'dart:ui' show Color, hashValues;
import 'package:flutter/foundation.dart';
import 'colors.dart'; import 'colors.dart';
import 'icon_theme_data.dart'; import 'icon_theme_data.dart';
import 'typography.dart'; import 'typography.dart';
...@@ -90,7 +93,8 @@ class ThemeData { ...@@ -90,7 +93,8 @@ class ThemeData {
TextTheme textTheme, TextTheme textTheme,
TextTheme primaryTextTheme, TextTheme primaryTextTheme,
IconThemeData iconTheme, IconThemeData iconTheme,
IconThemeData primaryIconTheme IconThemeData primaryIconTheme,
TargetPlatform platform
}) { }) {
brightness ??= Brightness.light; brightness ??= Brightness.light;
final bool isDark = brightness == Brightness.dark; final bool isDark = brightness == Brightness.dark;
...@@ -121,6 +125,7 @@ class ThemeData { ...@@ -121,6 +125,7 @@ class ThemeData {
primaryTextTheme ??= primaryIsDark ? Typography.white : Typography.black; primaryTextTheme ??= primaryIsDark ? Typography.white : Typography.black;
iconTheme ??= isDark ? const IconThemeData(color: Colors.white) : const IconThemeData(color: Colors.black); iconTheme ??= isDark ? const IconThemeData(color: Colors.white) : const IconThemeData(color: Colors.black);
primaryIconTheme ??= primaryIsDark ? const IconThemeData(color: Colors.white) : const IconThemeData(color: Colors.black); primaryIconTheme ??= primaryIsDark ? const IconThemeData(color: Colors.white) : const IconThemeData(color: Colors.black);
platform ??= (Platform.isIOS || Platform.isMacOS) ? TargetPlatform.iOS : TargetPlatform.android;
return new ThemeData.raw( return new ThemeData.raw(
brightness: brightness, brightness: brightness,
primaryColor: primaryColor, primaryColor: primaryColor,
...@@ -146,7 +151,8 @@ class ThemeData { ...@@ -146,7 +151,8 @@ class ThemeData {
textTheme: textTheme, textTheme: textTheme,
primaryTextTheme: primaryTextTheme, primaryTextTheme: primaryTextTheme,
iconTheme: iconTheme, iconTheme: iconTheme,
primaryIconTheme: primaryIconTheme primaryIconTheme: primaryIconTheme,
platform: platform
); );
} }
...@@ -181,7 +187,8 @@ class ThemeData { ...@@ -181,7 +187,8 @@ class ThemeData {
this.textTheme, this.textTheme,
this.primaryTextTheme, this.primaryTextTheme,
this.iconTheme, this.iconTheme,
this.primaryIconTheme this.primaryIconTheme,
this.platform
}) { }) {
assert(brightness != null); assert(brightness != null);
assert(primaryColor != null); assert(primaryColor != null);
...@@ -208,6 +215,7 @@ class ThemeData { ...@@ -208,6 +215,7 @@ class ThemeData {
assert(primaryTextTheme != null); assert(primaryTextTheme != null);
assert(iconTheme != null); assert(iconTheme != null);
assert(primaryIconTheme != null); assert(primaryIconTheme != null);
assert(platform != null);
} }
/// A default light blue theme. /// A default light blue theme.
...@@ -320,6 +328,11 @@ class ThemeData { ...@@ -320,6 +328,11 @@ class ThemeData {
/// An icon theme that contrasts with the primary color. /// An icon theme that contrasts with the primary color.
final IconThemeData primaryIconTheme; final IconThemeData primaryIconTheme;
/// The platform the material widgets should adapt to target.
///
/// Defaults to the current platform.
final TargetPlatform platform;
/// Linearly interpolate between two themes. /// Linearly interpolate between two themes.
static ThemeData lerp(ThemeData begin, ThemeData end, double t) { static ThemeData lerp(ThemeData begin, ThemeData end, double t) {
return new ThemeData.raw( return new ThemeData.raw(
...@@ -347,7 +360,8 @@ class ThemeData { ...@@ -347,7 +360,8 @@ class ThemeData {
textTheme: TextTheme.lerp(begin.textTheme, end.textTheme, t), textTheme: TextTheme.lerp(begin.textTheme, end.textTheme, t),
primaryTextTheme: TextTheme.lerp(begin.primaryTextTheme, end.primaryTextTheme, t), primaryTextTheme: TextTheme.lerp(begin.primaryTextTheme, end.primaryTextTheme, t),
iconTheme: IconThemeData.lerp(begin.iconTheme, end.iconTheme, t), iconTheme: IconThemeData.lerp(begin.iconTheme, end.iconTheme, t),
primaryIconTheme: IconThemeData.lerp(begin.primaryIconTheme, end.primaryIconTheme, t) primaryIconTheme: IconThemeData.lerp(begin.primaryIconTheme, end.primaryIconTheme, t),
platform: t < 0.5 ? begin.platform : end.platform
); );
} }
......
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