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.
This commit is contained in:
@@ -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,
|
||||
secondary: const Icon(Icons.assessment),
|
||||
selected: showPerformanceOverlay,
|
||||
));
|
||||
}
|
||||
allDrawerItems.addAll(textSizeItems);
|
||||
|
||||
if (onCheckerboardRasterCacheImagesChanged != null) {
|
||||
allDrawerItems.insert(8, new CheckboxListTile(
|
||||
title: const Text('Checkerboard Raster Cache Images'),
|
||||
value: checkerboardRasterCacheImages,
|
||||
onChanged: onCheckerboardRasterCacheImagesChanged,
|
||||
secondary: const Icon(Icons.assessment),
|
||||
selected: checkerboardRasterCacheImages,
|
||||
));
|
||||
}
|
||||
allDrawerItems..addAll(<Widget>[
|
||||
const Divider(),
|
||||
animateSlowlyItem,
|
||||
const Divider(),
|
||||
]);
|
||||
|
||||
bool addedOptionalItem = false;
|
||||
if (onCheckerboardOffscreenLayersChanged != null) {
|
||||
allDrawerItems.insert(8, new CheckboxListTile(
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
100
examples/flutter_gallery/test/drawer_test.dart
Normal file
100
examples/flutter_gallery/test/drawer_test.dart
Normal file
@@ -0,0 +1,100 @@
|
||||
// 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.
|
||||
|
||||
// send feedback
|
||||
// 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.
|
||||
expect(hasFeedback, false);
|
||||
await tester.tap(find.text('Send feedback'));
|
||||
await tester.pump();
|
||||
|
||||
Reference in New Issue
Block a user