Add a platform field to Theme (#5024)
We'll use this field to adapt material widgets to iOS.
This commit is contained in:
parent
486b783076
commit
5717cd54e0
@ -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';
|
||||||
|
12
packages/flutter/lib/src/foundation/platform.dart
Normal file
12
packages/flutter/lib/src/foundation/platform.dart
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// 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 @@
|
|||||||
// 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(
|
|||||||
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 {
|
|||||||
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 {
|
|||||||
/// 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
|
|||||||
@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> {
|
|||||||
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> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
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 @@
|
|||||||
// 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 {
|
|||||||
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 {
|
|||||||
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 {
|
|||||||
textTheme: textTheme,
|
textTheme: textTheme,
|
||||||
primaryTextTheme: primaryTextTheme,
|
primaryTextTheme: primaryTextTheme,
|
||||||
iconTheme: iconTheme,
|
iconTheme: iconTheme,
|
||||||
primaryIconTheme: primaryIconTheme
|
primaryIconTheme: primaryIconTheme,
|
||||||
|
platform: platform
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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 {
|
|||||||
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 {
|
|||||||
/// 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 {
|
|||||||
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
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user