Commit e697e552 authored by Greg Spencer's avatar Greg Spencer Committed by GitHub

Add large text switching to Gallery app. (#12443)

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.
parent c2dfa6a1
......@@ -22,7 +22,7 @@ final List<_Page> _allPages = <_Page>[
new _Page(icon: Icons.android, text: 'ANDROID'),
new _Page(icon: Icons.alarm, text: 'ALARM'),
new _Page(icon: Icons.face, text: 'FACE'),
new _Page(icon: Icons.language, text: 'LANGAUGE'),
new _Page(icon: Icons.language, text: 'LANGUAGE'),
];
class ScrollableTabsDemo extends StatefulWidget {
......
......@@ -12,15 +12,6 @@ import 'home.dart';
import 'item.dart';
import 'updates.dart';
final Map<String, WidgetBuilder> _kRoutes = new Map<String, WidgetBuilder>.fromIterable(
// For a different example of how to set up an application routing table,
// consider the Stocks example:
// https://github.com/flutter/flutter/blob/master/examples/stocks/lib/main.dart
kAllGalleryItems,
key: (GalleryItem item) => item.routeName,
value: (GalleryItem item) => item.buildRoute,
);
final ThemeData _kGalleryLightTheme = new ThemeData(
brightness: Brightness.light,
primarySwatch: Colors.blue,
......@@ -63,6 +54,9 @@ class GalleryAppState extends State<GalleryApp> {
double _timeDilation = 1.0;
TargetPlatform _platform;
// A null value indicates "use system default".
double _textScaleFactor;
Timer _timeDilationTimer;
@override
......@@ -128,6 +122,12 @@ class GalleryAppState extends State<GalleryApp> {
}
});
},
textScaleFactor: _textScaleFactor,
onTextScaleFactorChanged: (double value) {
setState(() {
_textScaleFactor = value;
});
},
onSendFeedback: widget.onSendFeedback,
);
......@@ -138,6 +138,33 @@ class GalleryAppState extends State<GalleryApp> {
);
}
final Map<String, WidgetBuilder> _kRoutes = new Map<String,
WidgetBuilder>.fromIterable(
// For a different example of how to set up an application routing table
// using named routes, consider the example in the Navigator class documentation:
// https://docs.flutter.io/flutter/widgets/Navigator-class.html
kAllGalleryItems,
key: (GalleryItem item) => item.routeName,
value: (GalleryItem item) =>
(BuildContext context) {
if (_textScaleFactor != null) {
return new MediaQuery(
data: new MediaQueryData(textScaleFactor: _textScaleFactor),
child: item.buildRoute(context),
);
} else {
return item.buildRoute(context);
}
}
);
if (_textScaleFactor != null) {
home = new MediaQuery(
data: new MediaQueryData(textScaleFactor: _textScaleFactor),
child: home,
);
}
return new MaterialApp(
title: 'Flutter Gallery',
color: Colors.grey,
......
......@@ -108,6 +108,8 @@ class GalleryDrawer extends StatelessWidget {
@required this.onThemeChanged,
this.timeDilation,
@required this.onTimeDilationChanged,
this.textScaleFactor,
this.onTextScaleFactorChanged,
this.showPerformanceOverlay,
this.onShowPerformanceOverlayChanged,
this.checkerboardRasterCacheImages,
......@@ -126,6 +128,9 @@ class GalleryDrawer extends StatelessWidget {
final double timeDilation;
final ValueChanged<double> onTimeDilationChanged;
final double textScaleFactor;
final ValueChanged<double> onTextScaleFactorChanged;
final bool showPerformanceOverlay;
final ValueChanged<bool> onShowPerformanceOverlayChanged;
......@@ -183,6 +188,25 @@ class GalleryDrawer extends StatelessWidget {
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,
......@@ -214,11 +238,11 @@ class GalleryDrawer extends StatelessWidget {
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 "
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,
......@@ -226,7 +250,7 @@ class GalleryDrawer extends StatelessWidget {
),
new TextSpan(
style: aboutTextStyle,
text: ".\n\nTo see the source code for this app, please visit the "
text: '.\n\nTo see the source code for this app, please visit the '
),
new LinkTextSpan(
style: linkStyle,
......@@ -235,7 +259,7 @@ class GalleryDrawer extends StatelessWidget {
),
new TextSpan(
style: aboutTextStyle,
text: "."
text: '.'
)
]
)
......@@ -252,42 +276,58 @@ class GalleryDrawer extends StatelessWidget {
mountainViewItem,
cupertinoItem,
const Divider(),
animateSlowlyItem,
// index 8, optional: Performance Overlay
sendFeedbackItem,
aboutItem
];
if (onShowPerformanceOverlayChanged != null) {
allDrawerItems.insert(8, new CheckboxListTile(
title: const Text('Performance Overlay'),
value: showPerformanceOverlay,
onChanged: onShowPerformanceOverlayChanged,
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: showPerformanceOverlay,
selected: checkerboardOffscreenLayers,
));
addedOptionalItem = true;
}
if (onCheckerboardRasterCacheImagesChanged != null) {
allDrawerItems.insert(8, new CheckboxListTile(
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 (onCheckerboardOffscreenLayersChanged != null) {
allDrawerItems.insert(8, new CheckboxListTile(
title: const Text('Checkerboard Offscreen Layers'),
value: checkerboardOffscreenLayers,
onChanged: onCheckerboardOffscreenLayersChanged,
if (onShowPerformanceOverlayChanged != null) {
allDrawerItems.add(new CheckboxListTile(
title: const Text('Performance Overlay'),
value: showPerformanceOverlay,
onChanged: onShowPerformanceOverlayChanged,
secondary: const Icon(Icons.assessment),
selected: checkerboardOffscreenLayers,
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));
}
}
......@@ -68,6 +68,8 @@ class GalleryHome extends StatefulWidget {
@required this.onThemeChanged,
this.timeDilation,
@required this.onTimeDilationChanged,
this.textScaleFactor,
this.onTextScaleFactorChanged,
this.showPerformanceOverlay,
this.onShowPerformanceOverlayChanged,
this.checkerboardRasterCacheImages,
......@@ -86,6 +88,9 @@ class GalleryHome extends StatefulWidget {
final double timeDilation;
final ValueChanged<double> onTimeDilationChanged;
final double textScaleFactor;
final ValueChanged<double> onTextScaleFactorChanged;
final bool showPerformanceOverlay;
final ValueChanged<bool> onShowPerformanceOverlayChanged;
......@@ -159,6 +164,8 @@ class GalleryHomeState extends State<GalleryHome> with SingleTickerProviderState
onThemeChanged: widget.onThemeChanged,
timeDilation: widget.timeDilation,
onTimeDilationChanged: widget.onTimeDilationChanged,
textScaleFactor: widget.textScaleFactor,
onTextScaleFactorChanged: widget.onTextScaleFactorChanged,
showPerformanceOverlay: widget.showPerformanceOverlay,
onShowPerformanceOverlayChanged: widget.onShowPerformanceOverlayChanged,
checkerboardRasterCacheImages: widget.checkerboardRasterCacheImages,
......
// Copyright 2017 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 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:flutter_gallery/gallery/app.dart';
void main() {
final TestWidgetsFlutterBinding binding = TestWidgetsFlutterBinding.ensureInitialized();
if (binding is LiveTestWidgetsFlutterBinding)
binding.framePolicy = LiveTestWidgetsFlutterBindingFramePolicy.fullyLive;
testWidgets('Flutter Gallery drawer item test', (WidgetTester tester) async {
bool hasFeedback = false;
void mockOnSendFeedback() {
hasFeedback = true;
}
await tester.pumpWidget(new GalleryApp(onSendFeedback: mockOnSendFeedback));
await tester.pump(); // see https://github.com/flutter/flutter/issues/1865
await tester.pump(); // triggers a frame
final Finder finder = find.byWidgetPredicate((Widget widget) {
return widget is Tooltip && widget.message == 'Open navigation menu';
});
expect(finder, findsOneWidget);
// Open drawer
await tester.tap(finder);
await tester.pump(); // start animation
await tester.pump(const Duration(seconds: 1)); // end animation
MaterialApp app = find.byType(MaterialApp).evaluate().first.widget;
expect(app.theme.brightness, equals(Brightness.light));
// Change theme
await tester.tap(find.text('Dark'));
await tester.pump(); // start animation
await tester.pump(const Duration(seconds: 1)); // end animation
app = find.byType(MaterialApp).evaluate().first.widget;
expect(app.theme.brightness, equals(Brightness.dark));
expect(app.theme.platform, equals(TargetPlatform.android));
// Change platform
await tester.tap(find.text('iOS'));
await tester.pump(); // start animation
await tester.pump(const Duration(seconds: 1)); // end animation
app = find.byType(MaterialApp).evaluate().first.widget;
expect(app.theme.platform, equals(TargetPlatform.iOS));
// Verify the font scale.
final Size origTextSize = tester.getSize(find.text("Small"));
expect(origTextSize, equals(const Size(176.0, 14.0)));
// Switch font scale.
await tester.tap(find.text('Small'));
await tester.pump();
await tester.pump(const Duration(seconds: 1)); // Wait until it's changed.
final Size textSize = tester.getSize(find.text("Small"));
expect(textSize, equals(const Size(176.0, 11.0)));
// Set font scale back to default.
await tester.tap(find.text('System Default'));
await tester.pump();
await tester.pump(const Duration(seconds: 1)); // Wait until it's changed.
final Size newTextSize = tester.getSize(find.text("Small"));
expect(newTextSize, equals(origTextSize));
// Scroll to the bottom of the menu.
await tester.drag(find.text('Small'), const Offset(0.0, -450.0));
await tester.pump();
await tester.pump(const Duration(seconds: 1)); // Wait until it's changed.
// Test slow animations.
expect(timeDilation, equals(1.0));
await tester.tap(find.text('Animate Slowly'));
await tester.pump();
await tester.pump(const Duration(seconds: 1)); // Wait until it's changed.
expect(timeDilation, greaterThan(1.0));
// Put back time dilation (so as not to throw off tests after this one).
await tester.tap(find.text('Animate Slowly'));
await tester.pump();
await tester.pump(const Duration(seconds: 1)); // Wait until it's changed.
expect(timeDilation, equals(1.0));
// Send feedback.
expect(hasFeedback, false);
await tester.tap(find.text('Send feedback'));
await tester.pump();
expect(hasFeedback, true);
// Close drawer
await tester.tap(find.byType(DrawerController));
await tester.pump(); // start animation
await tester.pump(const Duration(seconds: 1)); // end animation
});
}
......@@ -139,22 +139,31 @@ Future<Null> runSmokeTest(WidgetTester tester) async {
await tester.pump(); // Start opening drawer.
await tester.pump(const Duration(seconds: 1)); // Wait until it's really opened.
// switch theme
// Switch theme.
await tester.tap(find.text('Dark'));
await tester.pump();
await tester.pump(const Duration(seconds: 1)); // Wait until it's changed.
// switch theme
// Switch theme.
await tester.tap(find.text('Light'));
await tester.pump();
await tester.pump(const Duration(seconds: 1)); // Wait until it's changed.
// scroll the 'Send feedback' item into view
await tester.drag(find.text('Light'), const Offset(0.0, -200.0));
// Switch font scale.
await tester.tap(find.text('Small'));
await tester.pump();
await tester.pump(const Duration(seconds: 1)); // Wait until it's changed.
// Switch font scale back to default.
await tester.tap(find.text('System Default'));
await tester.pump();
await tester.pump(const Duration(seconds: 1)); // Wait until it's changed.
// Scroll the 'Send feedback' item into view.
await tester.drag(find.text('Small'), const Offset(0.0, -450.0));
await tester.pump();
await tester.pump(const Duration(seconds: 1)); // Wait until it's changed.
// send feedback
// Send feedback.
expect(hasFeedback, false);
await tester.tap(find.text('Send feedback'));
await tester.pump();
......
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