Unverified Commit c12d120b authored by Ian Hickson's avatar Ian Hickson Committed by GitHub

Provide a way to override global InheritedWidgets (#14348)

For example, so that the gallery can override the media query globally.
parent 12ceaefb
......@@ -51,6 +51,7 @@ class GalleryAppState extends State<GalleryApp> {
bool _showPerformanceOverlay = false;
bool _checkerboardRasterCacheImages = false;
bool _checkerboardOffscreenLayers = false;
TextDirection _overrideDirection = TextDirection.ltr;
double _timeDilation = 1.0;
TargetPlatform _platform;
......@@ -139,6 +140,12 @@ class GalleryAppState extends State<GalleryApp> {
_textScaleFactor = value;
});
},
overrideDirection: _overrideDirection,
onOverrideDirectionChanged: (TextDirection value) {
setState(() {
_overrideDirection = value;
});
},
onSendFeedback: widget.onSendFeedback,
);
......@@ -155,7 +162,7 @@ class GalleryAppState extends State<GalleryApp> {
// using named routes, consider the example in the Navigator class documentation:
// https://docs.flutter.io/flutter/widgets/Navigator-class.html
_kRoutes[item.routeName] = (BuildContext context) {
return _applyScaleFactor(item.buildRoute(context));
return item.buildRoute(context);
};
}
......@@ -168,6 +175,12 @@ class GalleryAppState extends State<GalleryApp> {
checkerboardOffscreenLayers: _checkerboardOffscreenLayers,
routes: _kRoutes,
home: _applyScaleFactor(home),
builder: (BuildContext context, Widget child) {
return new Directionality(
textDirection: _overrideDirection,
child: _applyScaleFactor(child),
);
},
);
}
}
......@@ -120,6 +120,8 @@ class GalleryDrawer extends StatelessWidget {
this.checkerboardOffscreenLayers,
this.onCheckerboardOffscreenLayersChanged,
this.onPlatformChanged,
this.overrideDirection: TextDirection.ltr,
this.onOverrideDirectionChanged,
this.onSendFeedback,
}) : assert(onThemeChanged != null),
assert(onTimeDilationChanged != null),
......@@ -145,6 +147,9 @@ class GalleryDrawer extends StatelessWidget {
final ValueChanged<TargetPlatform> onPlatformChanged;
final TextDirection overrideDirection;
final ValueChanged<TextDirection> onOverrideDirectionChanged;
final VoidCallback onSendFeedback;
@override
......@@ -220,6 +225,16 @@ class GalleryDrawer extends StatelessWidget {
selected: timeDilation != 1.0,
);
final Widget overrideDirectionItem = new CheckboxListTile(
title: const Text('Force RTL'),
value: overrideDirection == TextDirection.rtl,
onChanged: (bool value) {
onOverrideDirectionChanged(value ? TextDirection.rtl : TextDirection.ltr);
},
secondary: const Icon(Icons.format_textdirection_r_to_l),
selected: overrideDirection == TextDirection.rtl,
);
final Widget sendFeedbackItem = new ListTile(
leading: const Icon(Icons.report),
title: const Text('Send feedback'),
......@@ -285,6 +300,7 @@ class GalleryDrawer extends StatelessWidget {
allDrawerItems.addAll(textSizeItems);
allDrawerItems..addAll(<Widget>[
overrideDirectionItem,
const Divider(),
animateSlowlyItem,
const Divider(),
......
......@@ -77,6 +77,8 @@ class GalleryHome extends StatefulWidget {
this.checkerboardOffscreenLayers,
this.onCheckerboardOffscreenLayersChanged,
this.onPlatformChanged,
this.overrideDirection: TextDirection.ltr,
this.onOverrideDirectionChanged,
this.onSendFeedback,
}) : assert(onThemeChanged != null),
assert(onTimeDilationChanged != null),
......@@ -102,6 +104,9 @@ class GalleryHome extends StatefulWidget {
final ValueChanged<TargetPlatform> onPlatformChanged;
final TextDirection overrideDirection;
final ValueChanged<TextDirection> onOverrideDirectionChanged;
final VoidCallback onSendFeedback;
@override
......@@ -177,6 +182,8 @@ class GalleryHomeState extends State<GalleryHome> with SingleTickerProviderState
checkerboardOffscreenLayers: widget.checkerboardOffscreenLayers,
onCheckerboardOffscreenLayersChanged: widget.onCheckerboardOffscreenLayersChanged,
onPlatformChanged: widget.onPlatformChanged,
overrideDirection: widget.overrideDirection,
onOverrideDirectionChanged: widget.onOverrideDirectionChanged,
onSendFeedback: widget.onSendFeedback,
),
body: new CustomScrollView(
......
......@@ -69,7 +69,7 @@ void main() {
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.drag(find.text('Small'), const Offset(0.0, -1000.0));
await tester.pump();
await tester.pump(const Duration(seconds: 1)); // Wait until it's changed.
......
......@@ -159,7 +159,7 @@ Future<Null> runSmokeTest(WidgetTester tester) async {
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.drag(find.text('Small'), const Offset(0.0, -1000.0));
await tester.pump();
await tester.pump(const Duration(seconds: 1)); // Wait until it's changed.
......
This diff is collapsed.
This diff is collapsed.
......@@ -3557,6 +3557,14 @@ typedef Widget WidgetBuilder(BuildContext context);
/// Used by [ListView.builder] and other APIs that use lazily-generated widgets.
typedef Widget IndexedWidgetBuilder(BuildContext context, int index);
/// A builder that builds a widget given a child.
///
/// The child should typically be part of the returned widget tree.
///
/// Used by [AnimatedBuilder.builder], as well as [WidgetsApp.builder] and
/// [MaterialApp.builder].
typedef Widget TransitionBuilder(BuildContext context, Widget child);
/// An [Element] that composes other [Element]s.
///
/// Rather than creating a [RenderObject] directly, a [ComponentElement] creates
......
......@@ -527,13 +527,6 @@ class AlignTransition extends AnimatedWidget {
}
}
/// A builder that builds a widget given a child.
///
/// The child should typically be part of the returned widget tree.
///
/// Used by [AnimatedBuilder.builder].
typedef Widget TransitionBuilder(BuildContext context, Widget child);
/// A general-purpose widget for building animations.
///
/// AnimatedBuilder is useful for more complex widgets that wish to include
......
// Copyright 2018 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_test/flutter_test.dart';
import 'package:flutter/material.dart';
void main() {
testWidgets('builder doesn\'t get called if app doesn\'t change', (WidgetTester tester) async {
final List<String> log = <String>[];
final Widget app = new MaterialApp(
theme: new ThemeData(
primarySwatch: Colors.green,
),
home: const Placeholder(),
builder: (BuildContext context, Widget child) {
log.add('build');
expect(Theme.of(context).primaryColor, Colors.green.shade500);
expect(Directionality.of(context), TextDirection.ltr);
expect(child, const isInstanceOf<Navigator>());
return const Placeholder();
},
);
await tester.pumpWidget(
new Directionality(
textDirection: TextDirection.rtl,
child: app,
),
);
expect(log, <String>['build']);
await tester.pumpWidget(
new Directionality(
textDirection: TextDirection.ltr,
child: app,
),
);
expect(log, <String>['build']);
});
testWidgets('builder doesn\'t get called if app doesn\'t change', (WidgetTester tester) async {
final List<String> log = <String>[];
await tester.pumpWidget(
new MaterialApp(
theme: new ThemeData(
primarySwatch: Colors.yellow,
),
home: new Builder(
builder: (BuildContext context) {
log.add('build');
expect(Theme.of(context).primaryColor, Colors.yellow.shade500);
expect(Directionality.of(context), TextDirection.rtl);
return const Placeholder();
},
),
builder: (BuildContext context, Widget child) {
return new Directionality(
textDirection: TextDirection.rtl,
child: child,
);
},
),
);
expect(log, <String>['build']);
});
}
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