mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00

This lets us preview widgets in the gallery using small, normal, large, and HUGE text. Added selections to the main drawer for these options. Defaults to "normal", obviously.
334 lines
11 KiB
Dart
334 lines
11 KiB
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.
|
|
|
|
import 'dart:math' as math;
|
|
|
|
import 'package:flutter/foundation.dart' show defaultTargetPlatform, required;
|
|
import 'package:flutter/gestures.dart';
|
|
import 'package:flutter/material.dart';
|
|
|
|
import 'package:url_launcher/url_launcher.dart';
|
|
|
|
class LinkTextSpan extends TextSpan {
|
|
|
|
// Beware!
|
|
//
|
|
// This class is only safe because the TapGestureRecognizer is not
|
|
// given a deadline and therefore never allocates any resources.
|
|
//
|
|
// In any other situation -- setting a deadline, using any of the less trivial
|
|
// recognizers, etc -- you would have to manage the gesture recognizer's
|
|
// lifetime and call dispose() when the TextSpan was no longer being rendered.
|
|
//
|
|
// Since TextSpan itself is @immutable, this means that you would have to
|
|
// manage the recognizer from outside the TextSpan, e.g. in the State of a
|
|
// stateful widget that then hands the recognizer to the TextSpan.
|
|
|
|
LinkTextSpan({ TextStyle style, String url, String text }) : super(
|
|
style: style,
|
|
text: text ?? url,
|
|
recognizer: new TapGestureRecognizer()..onTap = () {
|
|
launch(url);
|
|
}
|
|
);
|
|
}
|
|
|
|
class GalleryDrawerHeader extends StatefulWidget {
|
|
const GalleryDrawerHeader({ Key key, this.light }) : super(key: key);
|
|
|
|
final bool light;
|
|
|
|
@override
|
|
_GalleryDrawerHeaderState createState() => new _GalleryDrawerHeaderState();
|
|
}
|
|
|
|
class _GalleryDrawerHeaderState extends State<GalleryDrawerHeader> {
|
|
bool _logoHasName = true;
|
|
bool _logoHorizontal = true;
|
|
MaterialColor _logoColor = Colors.blue;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final double systemTopPadding = MediaQuery.of(context).padding.top;
|
|
|
|
return new DrawerHeader(
|
|
decoration: new FlutterLogoDecoration(
|
|
margin: new EdgeInsets.fromLTRB(12.0, 12.0 + systemTopPadding, 12.0, 12.0),
|
|
style: _logoHasName ? _logoHorizontal ? FlutterLogoStyle.horizontal
|
|
: FlutterLogoStyle.stacked
|
|
: FlutterLogoStyle.markOnly,
|
|
lightColor: _logoColor.shade400,
|
|
darkColor: _logoColor.shade900,
|
|
textColor: widget.light ? const Color(0xFF616161) : const Color(0xFF9E9E9E),
|
|
),
|
|
duration: const Duration(milliseconds: 750),
|
|
child: new GestureDetector(
|
|
onLongPress: () {
|
|
setState(() {
|
|
_logoHorizontal = !_logoHorizontal;
|
|
if (!_logoHasName)
|
|
_logoHasName = true;
|
|
});
|
|
},
|
|
onTap: () {
|
|
setState(() {
|
|
_logoHasName = !_logoHasName;
|
|
});
|
|
},
|
|
onDoubleTap: () {
|
|
setState(() {
|
|
final List<MaterialColor> options = <MaterialColor>[];
|
|
if (_logoColor != Colors.blue)
|
|
options.addAll(<MaterialColor>[Colors.blue, Colors.blue, Colors.blue, Colors.blue, Colors.blue, Colors.blue, Colors.blue]);
|
|
if (_logoColor != Colors.amber)
|
|
options.addAll(<MaterialColor>[Colors.amber, Colors.amber, Colors.amber]);
|
|
if (_logoColor != Colors.red)
|
|
options.addAll(<MaterialColor>[Colors.red, Colors.red, Colors.red]);
|
|
if (_logoColor != Colors.indigo)
|
|
options.addAll(<MaterialColor>[Colors.indigo, Colors.indigo, Colors.indigo]);
|
|
if (_logoColor != Colors.pink)
|
|
options.addAll(<MaterialColor>[Colors.pink]);
|
|
if (_logoColor != Colors.purple)
|
|
options.addAll(<MaterialColor>[Colors.purple]);
|
|
if (_logoColor != Colors.cyan)
|
|
options.addAll(<MaterialColor>[Colors.cyan]);
|
|
_logoColor = options[new math.Random().nextInt(options.length)];
|
|
});
|
|
}
|
|
)
|
|
);
|
|
}
|
|
}
|
|
|
|
class GalleryDrawer extends StatelessWidget {
|
|
const GalleryDrawer({
|
|
Key key,
|
|
this.useLightTheme,
|
|
@required this.onThemeChanged,
|
|
this.timeDilation,
|
|
@required this.onTimeDilationChanged,
|
|
this.textScaleFactor,
|
|
this.onTextScaleFactorChanged,
|
|
this.showPerformanceOverlay,
|
|
this.onShowPerformanceOverlayChanged,
|
|
this.checkerboardRasterCacheImages,
|
|
this.onCheckerboardRasterCacheImagesChanged,
|
|
this.checkerboardOffscreenLayers,
|
|
this.onCheckerboardOffscreenLayersChanged,
|
|
this.onPlatformChanged,
|
|
this.onSendFeedback,
|
|
}) : assert(onThemeChanged != null),
|
|
assert(onTimeDilationChanged != null),
|
|
super(key: key);
|
|
|
|
final bool useLightTheme;
|
|
final ValueChanged<bool> onThemeChanged;
|
|
|
|
final double timeDilation;
|
|
final ValueChanged<double> onTimeDilationChanged;
|
|
|
|
final double textScaleFactor;
|
|
final ValueChanged<double> onTextScaleFactorChanged;
|
|
|
|
final bool showPerformanceOverlay;
|
|
final ValueChanged<bool> onShowPerformanceOverlayChanged;
|
|
|
|
final bool checkerboardRasterCacheImages;
|
|
final ValueChanged<bool> onCheckerboardRasterCacheImagesChanged;
|
|
|
|
final bool checkerboardOffscreenLayers;
|
|
final ValueChanged<bool> onCheckerboardOffscreenLayersChanged;
|
|
|
|
final ValueChanged<TargetPlatform> onPlatformChanged;
|
|
|
|
final VoidCallback onSendFeedback;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final ThemeData themeData = Theme.of(context);
|
|
final TextStyle aboutTextStyle = themeData.textTheme.body2;
|
|
final TextStyle linkStyle = themeData.textTheme.body2.copyWith(color: themeData.accentColor);
|
|
|
|
final Widget lightThemeItem = new RadioListTile<bool>(
|
|
secondary: const Icon(Icons.brightness_5),
|
|
title: const Text('Light'),
|
|
value: true,
|
|
groupValue: useLightTheme,
|
|
onChanged: onThemeChanged,
|
|
selected: useLightTheme,
|
|
);
|
|
|
|
final Widget darkThemeItem = new RadioListTile<bool>(
|
|
secondary: const Icon(Icons.brightness_7),
|
|
title: const Text('Dark'),
|
|
value: false,
|
|
groupValue: useLightTheme,
|
|
onChanged: onThemeChanged,
|
|
selected: !useLightTheme,
|
|
);
|
|
|
|
final Widget mountainViewItem = new RadioListTile<TargetPlatform>(
|
|
// on iOS, we don't want to show an Android phone icon
|
|
secondary: new Icon(defaultTargetPlatform == TargetPlatform.iOS ? Icons.star : Icons.phone_android),
|
|
title: const Text('Android'),
|
|
value: TargetPlatform.android,
|
|
groupValue: Theme.of(context).platform,
|
|
onChanged: onPlatformChanged,
|
|
selected: Theme.of(context).platform == TargetPlatform.android,
|
|
);
|
|
|
|
final Widget cupertinoItem = new RadioListTile<TargetPlatform>(
|
|
// on iOS, we don't want to show the iPhone icon
|
|
secondary: new Icon(defaultTargetPlatform == TargetPlatform.iOS ? Icons.star_border : Icons.phone_iphone),
|
|
title: const Text('iOS'),
|
|
value: TargetPlatform.iOS,
|
|
groupValue: Theme.of(context).platform,
|
|
onChanged: onPlatformChanged,
|
|
selected: Theme.of(context).platform == TargetPlatform.iOS,
|
|
);
|
|
|
|
final List<Widget> textSizeItems = <Widget>[];
|
|
final Map<double, String> textSizes = <double, String>{
|
|
null: 'System Default',
|
|
0.8: 'Small',
|
|
1.0: 'Normal',
|
|
1.3: 'Large',
|
|
2.0: 'Huge',
|
|
};
|
|
for (double size in textSizes.keys) {
|
|
textSizeItems.add(new RadioListTile<double>(
|
|
secondary: const Icon(Icons.text_fields),
|
|
title: new Text(textSizes[size]),
|
|
value: size,
|
|
groupValue: textScaleFactor,
|
|
onChanged: onTextScaleFactorChanged,
|
|
selected: textScaleFactor == size,
|
|
));
|
|
}
|
|
|
|
final Widget animateSlowlyItem = new CheckboxListTile(
|
|
title: const Text('Animate Slowly'),
|
|
value: timeDilation != 1.0,
|
|
onChanged: (bool value) {
|
|
onTimeDilationChanged(value ? 20.0 : 1.0);
|
|
},
|
|
secondary: const Icon(Icons.hourglass_empty),
|
|
selected: timeDilation != 1.0,
|
|
);
|
|
|
|
final Widget sendFeedbackItem = new ListTile(
|
|
leading: const Icon(Icons.report),
|
|
title: const Text('Send feedback'),
|
|
onTap: onSendFeedback ?? () {
|
|
launch('https://github.com/flutter/flutter/issues/new');
|
|
},
|
|
);
|
|
|
|
final Widget aboutItem = new AboutListTile(
|
|
icon: const FlutterLogo(),
|
|
applicationVersion: 'April 2017 Preview',
|
|
applicationIcon: const FlutterLogo(),
|
|
applicationLegalese: '© 2017 The Chromium Authors',
|
|
aboutBoxChildren: <Widget>[
|
|
new Padding(
|
|
padding: const EdgeInsets.only(top: 24.0),
|
|
child: new RichText(
|
|
text: new TextSpan(
|
|
children: <TextSpan>[
|
|
new TextSpan(
|
|
style: aboutTextStyle,
|
|
text: 'Flutter is an early-stage, open-source project to help '
|
|
'developers build high-performance, high-fidelity, mobile '
|
|
'apps for iOS and Android from a single codebase. This '
|
|
"gallery is a preview of Flutter's many widgets, behaviors, "
|
|
'animations, layouts, and more. Learn more about Flutter at '
|
|
),
|
|
new LinkTextSpan(
|
|
style: linkStyle,
|
|
url: 'https://flutter.io'
|
|
),
|
|
new TextSpan(
|
|
style: aboutTextStyle,
|
|
text: '.\n\nTo see the source code for this app, please visit the '
|
|
),
|
|
new LinkTextSpan(
|
|
style: linkStyle,
|
|
url: 'https://goo.gl/iv1p4G',
|
|
text: 'flutter github repo'
|
|
),
|
|
new TextSpan(
|
|
style: aboutTextStyle,
|
|
text: '.'
|
|
)
|
|
]
|
|
)
|
|
)
|
|
)
|
|
]
|
|
);
|
|
|
|
final List<Widget> allDrawerItems = <Widget>[
|
|
new GalleryDrawerHeader(light: useLightTheme),
|
|
lightThemeItem,
|
|
darkThemeItem,
|
|
const Divider(),
|
|
mountainViewItem,
|
|
cupertinoItem,
|
|
const Divider(),
|
|
];
|
|
|
|
allDrawerItems.addAll(textSizeItems);
|
|
|
|
allDrawerItems..addAll(<Widget>[
|
|
const Divider(),
|
|
animateSlowlyItem,
|
|
const Divider(),
|
|
]);
|
|
|
|
bool addedOptionalItem = false;
|
|
if (onCheckerboardOffscreenLayersChanged != null) {
|
|
allDrawerItems.add(new CheckboxListTile(
|
|
title: const Text('Checkerboard Offscreen Layers'),
|
|
value: checkerboardOffscreenLayers,
|
|
onChanged: onCheckerboardOffscreenLayersChanged,
|
|
secondary: const Icon(Icons.assessment),
|
|
selected: checkerboardOffscreenLayers,
|
|
));
|
|
addedOptionalItem = true;
|
|
}
|
|
|
|
if (onCheckerboardRasterCacheImagesChanged != null) {
|
|
allDrawerItems.add(new CheckboxListTile(
|
|
title: const Text('Checkerboard Raster Cache Images'),
|
|
value: checkerboardRasterCacheImages,
|
|
onChanged: onCheckerboardRasterCacheImagesChanged,
|
|
secondary: const Icon(Icons.assessment),
|
|
selected: checkerboardRasterCacheImages,
|
|
));
|
|
addedOptionalItem = true;
|
|
}
|
|
|
|
if (onShowPerformanceOverlayChanged != null) {
|
|
allDrawerItems.add(new CheckboxListTile(
|
|
title: const Text('Performance Overlay'),
|
|
value: showPerformanceOverlay,
|
|
onChanged: onShowPerformanceOverlayChanged,
|
|
secondary: const Icon(Icons.assessment),
|
|
selected: showPerformanceOverlay,
|
|
));
|
|
addedOptionalItem = true;
|
|
}
|
|
|
|
if (addedOptionalItem)
|
|
allDrawerItems.add(const Divider());
|
|
|
|
allDrawerItems.addAll(<Widget>[
|
|
sendFeedbackItem,
|
|
aboutItem,
|
|
]);
|
|
|
|
return new Drawer(child: new ListView(primary: false, children: allDrawerItems));
|
|
}
|
|
}
|