mirror of
https://github.com/flutter/flutter
synced 2024-10-13 11:42:54 +00:00
Clean up matters related to "offstageness". (#27425)
In particular, make debugVisitOnstageChildren only work in debug mode, and add documentation.
This commit is contained in:
parent
8de5a07c3f
commit
1d93e924b7
|
@ -2465,8 +2465,11 @@ class _OffstageElement extends SingleChildRenderObjectElement {
|
|||
|
||||
@override
|
||||
void debugVisitOnstageChildren(ElementVisitor visitor) {
|
||||
if (!widget.offstage)
|
||||
super.debugVisitOnstageChildren(visitor);
|
||||
assert(() {
|
||||
if (!widget.offstage)
|
||||
super.debugVisitOnstageChildren(visitor);
|
||||
return true;
|
||||
}());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2666,6 +2666,11 @@ abstract class Element extends DiagnosticableTree implements BuildContext {
|
|||
/// The default implementation defers to [visitChildren] and therefore treats
|
||||
/// the element as onstage.
|
||||
///
|
||||
/// This method should only be used in tests and debug code. In production,
|
||||
/// the vague concept of "onstage" vs "offstage" is meaningless and should not
|
||||
/// be used to affect widget behavior; this method does nothing in release
|
||||
/// builds.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [Offstage] widget that hides its children.
|
||||
|
@ -2673,7 +2678,9 @@ abstract class Element extends DiagnosticableTree implements BuildContext {
|
|||
/// * [RenderObject.visitChildrenForSemantics], in contrast to this method,
|
||||
/// designed specifically for excluding parts of the UI from the semantics
|
||||
/// tree.
|
||||
void debugVisitOnstageChildren(ElementVisitor visitor) => visitChildren(visitor);
|
||||
void debugVisitOnstageChildren(ElementVisitor visitor) {
|
||||
assert(() { visitChildren(visitor); return true; }());
|
||||
}
|
||||
|
||||
/// Wrapper around [visitChildren] for [BuildContext].
|
||||
@override
|
||||
|
|
|
@ -472,8 +472,11 @@ class _TheatreElement extends RenderObjectElement {
|
|||
|
||||
@override
|
||||
void debugVisitOnstageChildren(ElementVisitor visitor) {
|
||||
if (_onstage != null)
|
||||
visitor(_onstage);
|
||||
assert(() {
|
||||
if (_onstage != null)
|
||||
visitor(_onstage);
|
||||
return true;
|
||||
}());
|
||||
}
|
||||
|
||||
@override
|
||||
|
|
|
@ -1179,21 +1179,24 @@ class SliverMultiBoxAdaptorElement extends RenderObjectElement implements Render
|
|||
|
||||
@override
|
||||
void debugVisitOnstageChildren(ElementVisitor visitor) {
|
||||
_childElements.values.where((Element child) {
|
||||
final SliverMultiBoxAdaptorParentData parentData = child.renderObject.parentData;
|
||||
double itemExtent;
|
||||
switch (renderObject.constraints.axis) {
|
||||
case Axis.horizontal:
|
||||
itemExtent = child.renderObject.paintBounds.width;
|
||||
break;
|
||||
case Axis.vertical:
|
||||
itemExtent = child.renderObject.paintBounds.height;
|
||||
break;
|
||||
}
|
||||
|
||||
return parentData.layoutOffset < renderObject.constraints.scrollOffset + renderObject.constraints.remainingPaintExtent &&
|
||||
parentData.layoutOffset + itemExtent > renderObject.constraints.scrollOffset;
|
||||
}).forEach(visitor);
|
||||
assert(() {
|
||||
_childElements.values.where((Element child) {
|
||||
final SliverMultiBoxAdaptorParentData parentData = child.renderObject.parentData;
|
||||
double itemExtent;
|
||||
switch (renderObject.constraints.axis) {
|
||||
case Axis.horizontal:
|
||||
itemExtent = child.renderObject.paintBounds.width;
|
||||
break;
|
||||
case Axis.vertical:
|
||||
itemExtent = child.renderObject.paintBounds.height;
|
||||
break;
|
||||
}
|
||||
final SliverConstraints constraints = renderObject.constraints;
|
||||
return parentData.layoutOffset < constraints.scrollOffset + constraints.remainingPaintExtent
|
||||
&& parentData.layoutOffset + itemExtent > constraints.scrollOffset;
|
||||
}).forEach(visitor);
|
||||
return true;
|
||||
}());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -208,10 +208,13 @@ class _ViewportElement extends MultiChildRenderObjectElement {
|
|||
|
||||
@override
|
||||
void debugVisitOnstageChildren(ElementVisitor visitor) {
|
||||
children.where((Element e) {
|
||||
final RenderSliver renderSliver = e.renderObject;
|
||||
return renderSliver.geometry.visible;
|
||||
}).forEach(visitor);
|
||||
assert(() {
|
||||
children.where((Element e) {
|
||||
final RenderSliver renderSliver = e.renderObject;
|
||||
return renderSliver.geometry.visible;
|
||||
}).forEach(visitor);
|
||||
return true;
|
||||
}());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -32,8 +32,7 @@ class CommonFinders {
|
|||
/// expect(find.text('Back'), findsOneWidget);
|
||||
/// ```
|
||||
///
|
||||
/// If the `skipOffstage` argument is true (the default), then this skips
|
||||
/// nodes that are [Offstage] or that are from inactive [Route]s.
|
||||
/// The `skipOffstage` argument maps to [Finder.skipOffstage] (q.v.).
|
||||
Finder text(String text, { bool skipOffstage = true }) => _TextFinder(text, skipOffstage: skipOffstage);
|
||||
|
||||
/// Looks for widgets that contain a [Text] descendant with `text`
|
||||
|
@ -51,8 +50,7 @@ class CommonFinders {
|
|||
/// tester.tap(find.widgetWithText(Button, 'Update'));
|
||||
/// ```
|
||||
///
|
||||
/// If the `skipOffstage` argument is true (the default), then this skips
|
||||
/// nodes that are [Offstage] or that are from inactive [Route]s.
|
||||
/// The `skipOffstage` argument maps to [Finder.skipOffstage] (q.v.).
|
||||
Finder widgetWithText(Type widgetType, String text, { bool skipOffstage = true }) {
|
||||
return find.ancestor(
|
||||
of: find.text(text, skipOffstage: skipOffstage),
|
||||
|
@ -68,8 +66,7 @@ class CommonFinders {
|
|||
/// expect(find.byKey(backKey), findsOneWidget);
|
||||
/// ```
|
||||
///
|
||||
/// If the `skipOffstage` argument is true (the default), then this skips
|
||||
/// nodes that are [Offstage] or that are from inactive [Route]s.
|
||||
/// The `skipOffstage` argument maps to [Finder.skipOffstage] (q.v.).
|
||||
Finder byKey(Key key, { bool skipOffstage = true }) => _KeyFinder(key, skipOffstage: skipOffstage);
|
||||
|
||||
/// Finds widgets by searching for widgets with a particular type.
|
||||
|
@ -86,8 +83,7 @@ class CommonFinders {
|
|||
/// expect(find.byType(IconButton), findsOneWidget);
|
||||
/// ```
|
||||
///
|
||||
/// If the `skipOffstage` argument is true (the default), then this skips
|
||||
/// nodes that are [Offstage] or that are from inactive [Route]s.
|
||||
/// The `skipOffstage` argument maps to [Finder.skipOffstage] (q.v.).
|
||||
Finder byType(Type type, { bool skipOffstage = true }) => _WidgetTypeFinder(type, skipOffstage: skipOffstage);
|
||||
|
||||
/// Finds [Icon] widgets containing icon data equal to the `icon`
|
||||
|
@ -99,8 +95,7 @@ class CommonFinders {
|
|||
/// expect(find.byIcon(Icons.inbox), findsOneWidget);
|
||||
/// ```
|
||||
///
|
||||
/// If the `skipOffstage` argument is true (the default), then this skips
|
||||
/// nodes that are [Offstage] or that are from inactive [Route]s.
|
||||
/// The `skipOffstage` argument maps to [Finder.skipOffstage] (q.v.).
|
||||
Finder byIcon(IconData icon, { bool skipOffstage = true }) => _WidgetIconFinder(icon, skipOffstage: skipOffstage);
|
||||
|
||||
/// Looks for widgets that contain an [Icon] descendant displaying [IconData]
|
||||
|
@ -118,8 +113,7 @@ class CommonFinders {
|
|||
/// tester.tap(find.widgetWithIcon(Button, Icons.arrow_forward));
|
||||
/// ```
|
||||
///
|
||||
/// If the `skipOffstage` argument is true (the default), then this skips
|
||||
/// nodes that are [Offstage] or that are from inactive [Route]s.
|
||||
/// The `skipOffstage` argument maps to [Finder.skipOffstage] (q.v.).
|
||||
Finder widgetWithIcon(Type widgetType, IconData icon, { bool skipOffstage = true }) {
|
||||
return find.ancestor(
|
||||
of: find.byIcon(icon),
|
||||
|
@ -141,8 +135,7 @@ class CommonFinders {
|
|||
/// expect(find.byElementType(SingleChildRenderObjectElement), findsOneWidget);
|
||||
/// ```
|
||||
///
|
||||
/// If the `skipOffstage` argument is true (the default), then this skips
|
||||
/// nodes that are [Offstage] or that are from inactive [Route]s.
|
||||
/// The `skipOffstage` argument maps to [Finder.skipOffstage] (q.v.).
|
||||
Finder byElementType(Type type, { bool skipOffstage = true }) => _ElementTypeFinder(type, skipOffstage: skipOffstage);
|
||||
|
||||
/// Finds widgets whose current widget is the instance given by the
|
||||
|
@ -160,8 +153,7 @@ class CommonFinders {
|
|||
/// tester.tap(find.byWidget(myButton));
|
||||
/// ```
|
||||
///
|
||||
/// If the `skipOffstage` argument is true (the default), then this skips
|
||||
/// nodes that are [Offstage] or that are from inactive [Route]s.
|
||||
/// The `skipOffstage` argument maps to [Finder.skipOffstage] (q.v.).
|
||||
Finder byWidget(Widget widget, { bool skipOffstage = true }) => _WidgetFinder(widget, skipOffstage: skipOffstage);
|
||||
|
||||
/// Finds widgets using a widget [predicate].
|
||||
|
@ -180,8 +172,7 @@ class CommonFinders {
|
|||
/// fails to locate the desired widget. Otherwise, the description prints the
|
||||
/// signature of the predicate function.
|
||||
///
|
||||
/// If the `skipOffstage` argument is true (the default), then this skips
|
||||
/// nodes that are [Offstage] or that are from inactive [Route]s.
|
||||
/// The `skipOffstage` argument maps to [Finder.skipOffstage] (q.v.).
|
||||
Finder byWidgetPredicate(WidgetPredicate predicate, { String description, bool skipOffstage = true }) {
|
||||
return _WidgetPredicateFinder(predicate, description: description, skipOffstage: skipOffstage);
|
||||
}
|
||||
|
@ -194,8 +185,7 @@ class CommonFinders {
|
|||
/// expect(find.byTooltip('Back'), findsOneWidget);
|
||||
/// ```
|
||||
///
|
||||
/// If the `skipOffstage` argument is true (the default), then this skips
|
||||
/// nodes that are [Offstage] or that are from inactive [Route]s.
|
||||
/// The `skipOffstage` argument maps to [Finder.skipOffstage] (q.v.).
|
||||
Finder byTooltip(String message, { bool skipOffstage = true }) {
|
||||
return byWidgetPredicate(
|
||||
(Widget widget) => widget is Tooltip && widget.message == message,
|
||||
|
@ -222,8 +212,7 @@ class CommonFinders {
|
|||
/// fails to locate the desired widget. Otherwise, the description prints the
|
||||
/// signature of the predicate function.
|
||||
///
|
||||
/// If the `skipOffstage` argument is true (the default), then this skips
|
||||
/// nodes that are [Offstage] or that are from inactive [Route]s.
|
||||
/// The `skipOffstage` argument maps to [Finder.skipOffstage] (q.v.).
|
||||
Finder byElementPredicate(ElementPredicate predicate, { String description, bool skipOffstage = true }) {
|
||||
return _ElementPredicateFinder(predicate, description: description, skipOffstage: skipOffstage);
|
||||
}
|
||||
|
@ -242,9 +231,13 @@ class CommonFinders {
|
|||
/// If the [matchRoot] argument is true then the widget(s) specified by [of]
|
||||
/// will be matched along with the descendants.
|
||||
///
|
||||
/// If the [skipOffstage] argument is true (the default), then nodes that are
|
||||
/// [Offstage] or that are from inactive [Route]s are skipped.
|
||||
Finder descendant({ Finder of, Finder matching, bool matchRoot = false, bool skipOffstage = true }) {
|
||||
/// The `skipOffstage` argument maps to [Finder.skipOffstage] (q.v.).
|
||||
Finder descendant({
|
||||
@required Finder of,
|
||||
@required Finder matching,
|
||||
bool matchRoot = false,
|
||||
bool skipOffstage = true,
|
||||
}) {
|
||||
return _DescendantFinder(of, matching, matchRoot: matchRoot, skipOffstage: skipOffstage);
|
||||
}
|
||||
|
||||
|
@ -296,9 +289,25 @@ abstract class Finder {
|
|||
|
||||
/// Whether this finder skips nodes that are offstage.
|
||||
///
|
||||
/// If this is true, then the elements are walked using
|
||||
/// [Element.debugVisitOnstageChildren]. This skips offstage children of
|
||||
/// [Offstage] widgets, as well as children of inactive [Route]s.
|
||||
/// By default, finders skip nodes that are considered "offstage". The term is
|
||||
/// very loosely defined and is only meaningful in a debug environment; it is
|
||||
/// not a term that applies in production. A widget is considered "offstage"
|
||||
/// if it is "not really visible".
|
||||
///
|
||||
/// If [skipOffstage] is true, then the elements are walked using
|
||||
/// [Element.debugVisitOnstageChildren]. This skips hidden children of
|
||||
/// [Offstage] widgets, children of inactive [Route]s, some non-visible
|
||||
/// children in viewports, and other nodes that are generally considered to be
|
||||
/// "not there" when considering what the user can see.
|
||||
///
|
||||
/// The [skipOffstage] argument can be set to `false` to match _all_ nodes
|
||||
/// regardless of this status. This is useful to test for the presence of
|
||||
/// widgets being kept alive using [KeepAlive], for instance.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [Element.debugVisitOnstageChildren], which can be overriden to
|
||||
/// decide whether a child is onstage or offstage.
|
||||
final bool skipOffstage;
|
||||
|
||||
/// Returns all the [Element]s that will be considered by this finder.
|
||||
|
|
Loading…
Reference in a new issue