mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +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
|
@override
|
||||||
void debugVisitOnstageChildren(ElementVisitor visitor) {
|
void debugVisitOnstageChildren(ElementVisitor visitor) {
|
||||||
if (!widget.offstage)
|
assert(() {
|
||||||
super.debugVisitOnstageChildren(visitor);
|
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 default implementation defers to [visitChildren] and therefore treats
|
||||||
/// the element as onstage.
|
/// 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:
|
/// See also:
|
||||||
///
|
///
|
||||||
/// * [Offstage] widget that hides its children.
|
/// * [Offstage] widget that hides its children.
|
||||||
@ -2673,7 +2678,9 @@ abstract class Element extends DiagnosticableTree implements BuildContext {
|
|||||||
/// * [RenderObject.visitChildrenForSemantics], in contrast to this method,
|
/// * [RenderObject.visitChildrenForSemantics], in contrast to this method,
|
||||||
/// designed specifically for excluding parts of the UI from the semantics
|
/// designed specifically for excluding parts of the UI from the semantics
|
||||||
/// tree.
|
/// tree.
|
||||||
void debugVisitOnstageChildren(ElementVisitor visitor) => visitChildren(visitor);
|
void debugVisitOnstageChildren(ElementVisitor visitor) {
|
||||||
|
assert(() { visitChildren(visitor); return true; }());
|
||||||
|
}
|
||||||
|
|
||||||
/// Wrapper around [visitChildren] for [BuildContext].
|
/// Wrapper around [visitChildren] for [BuildContext].
|
||||||
@override
|
@override
|
||||||
|
@ -472,8 +472,11 @@ class _TheatreElement extends RenderObjectElement {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void debugVisitOnstageChildren(ElementVisitor visitor) {
|
void debugVisitOnstageChildren(ElementVisitor visitor) {
|
||||||
if (_onstage != null)
|
assert(() {
|
||||||
visitor(_onstage);
|
if (_onstage != null)
|
||||||
|
visitor(_onstage);
|
||||||
|
return true;
|
||||||
|
}());
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -1179,21 +1179,24 @@ class SliverMultiBoxAdaptorElement extends RenderObjectElement implements Render
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void debugVisitOnstageChildren(ElementVisitor visitor) {
|
void debugVisitOnstageChildren(ElementVisitor visitor) {
|
||||||
_childElements.values.where((Element child) {
|
assert(() {
|
||||||
final SliverMultiBoxAdaptorParentData parentData = child.renderObject.parentData;
|
_childElements.values.where((Element child) {
|
||||||
double itemExtent;
|
final SliverMultiBoxAdaptorParentData parentData = child.renderObject.parentData;
|
||||||
switch (renderObject.constraints.axis) {
|
double itemExtent;
|
||||||
case Axis.horizontal:
|
switch (renderObject.constraints.axis) {
|
||||||
itemExtent = child.renderObject.paintBounds.width;
|
case Axis.horizontal:
|
||||||
break;
|
itemExtent = child.renderObject.paintBounds.width;
|
||||||
case Axis.vertical:
|
break;
|
||||||
itemExtent = child.renderObject.paintBounds.height;
|
case Axis.vertical:
|
||||||
break;
|
itemExtent = child.renderObject.paintBounds.height;
|
||||||
}
|
break;
|
||||||
|
}
|
||||||
return parentData.layoutOffset < renderObject.constraints.scrollOffset + renderObject.constraints.remainingPaintExtent &&
|
final SliverConstraints constraints = renderObject.constraints;
|
||||||
parentData.layoutOffset + itemExtent > renderObject.constraints.scrollOffset;
|
return parentData.layoutOffset < constraints.scrollOffset + constraints.remainingPaintExtent
|
||||||
}).forEach(visitor);
|
&& parentData.layoutOffset + itemExtent > constraints.scrollOffset;
|
||||||
|
}).forEach(visitor);
|
||||||
|
return true;
|
||||||
|
}());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,10 +208,13 @@ class _ViewportElement extends MultiChildRenderObjectElement {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void debugVisitOnstageChildren(ElementVisitor visitor) {
|
void debugVisitOnstageChildren(ElementVisitor visitor) {
|
||||||
children.where((Element e) {
|
assert(() {
|
||||||
final RenderSliver renderSliver = e.renderObject;
|
children.where((Element e) {
|
||||||
return renderSliver.geometry.visible;
|
final RenderSliver renderSliver = e.renderObject;
|
||||||
}).forEach(visitor);
|
return renderSliver.geometry.visible;
|
||||||
|
}).forEach(visitor);
|
||||||
|
return true;
|
||||||
|
}());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,8 +32,7 @@ class CommonFinders {
|
|||||||
/// expect(find.text('Back'), findsOneWidget);
|
/// expect(find.text('Back'), findsOneWidget);
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// If the `skipOffstage` argument is true (the default), then this skips
|
/// The `skipOffstage` argument maps to [Finder.skipOffstage] (q.v.).
|
||||||
/// nodes that are [Offstage] or that are from inactive [Route]s.
|
|
||||||
Finder text(String text, { bool skipOffstage = true }) => _TextFinder(text, skipOffstage: skipOffstage);
|
Finder text(String text, { bool skipOffstage = true }) => _TextFinder(text, skipOffstage: skipOffstage);
|
||||||
|
|
||||||
/// Looks for widgets that contain a [Text] descendant with `text`
|
/// Looks for widgets that contain a [Text] descendant with `text`
|
||||||
@ -51,8 +50,7 @@ class CommonFinders {
|
|||||||
/// tester.tap(find.widgetWithText(Button, 'Update'));
|
/// tester.tap(find.widgetWithText(Button, 'Update'));
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// If the `skipOffstage` argument is true (the default), then this skips
|
/// The `skipOffstage` argument maps to [Finder.skipOffstage] (q.v.).
|
||||||
/// nodes that are [Offstage] or that are from inactive [Route]s.
|
|
||||||
Finder widgetWithText(Type widgetType, String text, { bool skipOffstage = true }) {
|
Finder widgetWithText(Type widgetType, String text, { bool skipOffstage = true }) {
|
||||||
return find.ancestor(
|
return find.ancestor(
|
||||||
of: find.text(text, skipOffstage: skipOffstage),
|
of: find.text(text, skipOffstage: skipOffstage),
|
||||||
@ -68,8 +66,7 @@ class CommonFinders {
|
|||||||
/// expect(find.byKey(backKey), findsOneWidget);
|
/// expect(find.byKey(backKey), findsOneWidget);
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// If the `skipOffstage` argument is true (the default), then this skips
|
/// The `skipOffstage` argument maps to [Finder.skipOffstage] (q.v.).
|
||||||
/// nodes that are [Offstage] or that are from inactive [Route]s.
|
|
||||||
Finder byKey(Key key, { bool skipOffstage = true }) => _KeyFinder(key, skipOffstage: skipOffstage);
|
Finder byKey(Key key, { bool skipOffstage = true }) => _KeyFinder(key, skipOffstage: skipOffstage);
|
||||||
|
|
||||||
/// Finds widgets by searching for widgets with a particular type.
|
/// Finds widgets by searching for widgets with a particular type.
|
||||||
@ -86,8 +83,7 @@ class CommonFinders {
|
|||||||
/// expect(find.byType(IconButton), findsOneWidget);
|
/// expect(find.byType(IconButton), findsOneWidget);
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// If the `skipOffstage` argument is true (the default), then this skips
|
/// The `skipOffstage` argument maps to [Finder.skipOffstage] (q.v.).
|
||||||
/// nodes that are [Offstage] or that are from inactive [Route]s.
|
|
||||||
Finder byType(Type type, { bool skipOffstage = true }) => _WidgetTypeFinder(type, skipOffstage: skipOffstage);
|
Finder byType(Type type, { bool skipOffstage = true }) => _WidgetTypeFinder(type, skipOffstage: skipOffstage);
|
||||||
|
|
||||||
/// Finds [Icon] widgets containing icon data equal to the `icon`
|
/// Finds [Icon] widgets containing icon data equal to the `icon`
|
||||||
@ -99,8 +95,7 @@ class CommonFinders {
|
|||||||
/// expect(find.byIcon(Icons.inbox), findsOneWidget);
|
/// expect(find.byIcon(Icons.inbox), findsOneWidget);
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// If the `skipOffstage` argument is true (the default), then this skips
|
/// The `skipOffstage` argument maps to [Finder.skipOffstage] (q.v.).
|
||||||
/// nodes that are [Offstage] or that are from inactive [Route]s.
|
|
||||||
Finder byIcon(IconData icon, { bool skipOffstage = true }) => _WidgetIconFinder(icon, skipOffstage: skipOffstage);
|
Finder byIcon(IconData icon, { bool skipOffstage = true }) => _WidgetIconFinder(icon, skipOffstage: skipOffstage);
|
||||||
|
|
||||||
/// Looks for widgets that contain an [Icon] descendant displaying [IconData]
|
/// Looks for widgets that contain an [Icon] descendant displaying [IconData]
|
||||||
@ -118,8 +113,7 @@ class CommonFinders {
|
|||||||
/// tester.tap(find.widgetWithIcon(Button, Icons.arrow_forward));
|
/// tester.tap(find.widgetWithIcon(Button, Icons.arrow_forward));
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// If the `skipOffstage` argument is true (the default), then this skips
|
/// The `skipOffstage` argument maps to [Finder.skipOffstage] (q.v.).
|
||||||
/// nodes that are [Offstage] or that are from inactive [Route]s.
|
|
||||||
Finder widgetWithIcon(Type widgetType, IconData icon, { bool skipOffstage = true }) {
|
Finder widgetWithIcon(Type widgetType, IconData icon, { bool skipOffstage = true }) {
|
||||||
return find.ancestor(
|
return find.ancestor(
|
||||||
of: find.byIcon(icon),
|
of: find.byIcon(icon),
|
||||||
@ -141,8 +135,7 @@ class CommonFinders {
|
|||||||
/// expect(find.byElementType(SingleChildRenderObjectElement), findsOneWidget);
|
/// expect(find.byElementType(SingleChildRenderObjectElement), findsOneWidget);
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// If the `skipOffstage` argument is true (the default), then this skips
|
/// The `skipOffstage` argument maps to [Finder.skipOffstage] (q.v.).
|
||||||
/// nodes that are [Offstage] or that are from inactive [Route]s.
|
|
||||||
Finder byElementType(Type type, { bool skipOffstage = true }) => _ElementTypeFinder(type, skipOffstage: skipOffstage);
|
Finder byElementType(Type type, { bool skipOffstage = true }) => _ElementTypeFinder(type, skipOffstage: skipOffstage);
|
||||||
|
|
||||||
/// Finds widgets whose current widget is the instance given by the
|
/// Finds widgets whose current widget is the instance given by the
|
||||||
@ -160,8 +153,7 @@ class CommonFinders {
|
|||||||
/// tester.tap(find.byWidget(myButton));
|
/// tester.tap(find.byWidget(myButton));
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// If the `skipOffstage` argument is true (the default), then this skips
|
/// The `skipOffstage` argument maps to [Finder.skipOffstage] (q.v.).
|
||||||
/// nodes that are [Offstage] or that are from inactive [Route]s.
|
|
||||||
Finder byWidget(Widget widget, { bool skipOffstage = true }) => _WidgetFinder(widget, skipOffstage: skipOffstage);
|
Finder byWidget(Widget widget, { bool skipOffstage = true }) => _WidgetFinder(widget, skipOffstage: skipOffstage);
|
||||||
|
|
||||||
/// Finds widgets using a widget [predicate].
|
/// Finds widgets using a widget [predicate].
|
||||||
@ -180,8 +172,7 @@ class CommonFinders {
|
|||||||
/// fails to locate the desired widget. Otherwise, the description prints the
|
/// fails to locate the desired widget. Otherwise, the description prints the
|
||||||
/// signature of the predicate function.
|
/// signature of the predicate function.
|
||||||
///
|
///
|
||||||
/// If the `skipOffstage` argument is true (the default), then this skips
|
/// The `skipOffstage` argument maps to [Finder.skipOffstage] (q.v.).
|
||||||
/// nodes that are [Offstage] or that are from inactive [Route]s.
|
|
||||||
Finder byWidgetPredicate(WidgetPredicate predicate, { String description, bool skipOffstage = true }) {
|
Finder byWidgetPredicate(WidgetPredicate predicate, { String description, bool skipOffstage = true }) {
|
||||||
return _WidgetPredicateFinder(predicate, description: description, skipOffstage: skipOffstage);
|
return _WidgetPredicateFinder(predicate, description: description, skipOffstage: skipOffstage);
|
||||||
}
|
}
|
||||||
@ -194,8 +185,7 @@ class CommonFinders {
|
|||||||
/// expect(find.byTooltip('Back'), findsOneWidget);
|
/// expect(find.byTooltip('Back'), findsOneWidget);
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// If the `skipOffstage` argument is true (the default), then this skips
|
/// The `skipOffstage` argument maps to [Finder.skipOffstage] (q.v.).
|
||||||
/// nodes that are [Offstage] or that are from inactive [Route]s.
|
|
||||||
Finder byTooltip(String message, { bool skipOffstage = true }) {
|
Finder byTooltip(String message, { bool skipOffstage = true }) {
|
||||||
return byWidgetPredicate(
|
return byWidgetPredicate(
|
||||||
(Widget widget) => widget is Tooltip && widget.message == message,
|
(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
|
/// fails to locate the desired widget. Otherwise, the description prints the
|
||||||
/// signature of the predicate function.
|
/// signature of the predicate function.
|
||||||
///
|
///
|
||||||
/// If the `skipOffstage` argument is true (the default), then this skips
|
/// The `skipOffstage` argument maps to [Finder.skipOffstage] (q.v.).
|
||||||
/// nodes that are [Offstage] or that are from inactive [Route]s.
|
|
||||||
Finder byElementPredicate(ElementPredicate predicate, { String description, bool skipOffstage = true }) {
|
Finder byElementPredicate(ElementPredicate predicate, { String description, bool skipOffstage = true }) {
|
||||||
return _ElementPredicateFinder(predicate, description: description, skipOffstage: skipOffstage);
|
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]
|
/// If the [matchRoot] argument is true then the widget(s) specified by [of]
|
||||||
/// will be matched along with the descendants.
|
/// will be matched along with the descendants.
|
||||||
///
|
///
|
||||||
/// If the [skipOffstage] argument is true (the default), then nodes that are
|
/// The `skipOffstage` argument maps to [Finder.skipOffstage] (q.v.).
|
||||||
/// [Offstage] or that are from inactive [Route]s are skipped.
|
Finder descendant({
|
||||||
Finder descendant({ Finder of, Finder matching, bool matchRoot = false, bool skipOffstage = true }) {
|
@required Finder of,
|
||||||
|
@required Finder matching,
|
||||||
|
bool matchRoot = false,
|
||||||
|
bool skipOffstage = true,
|
||||||
|
}) {
|
||||||
return _DescendantFinder(of, matching, matchRoot: matchRoot, skipOffstage: skipOffstage);
|
return _DescendantFinder(of, matching, matchRoot: matchRoot, skipOffstage: skipOffstage);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -296,9 +289,25 @@ abstract class Finder {
|
|||||||
|
|
||||||
/// Whether this finder skips nodes that are offstage.
|
/// Whether this finder skips nodes that are offstage.
|
||||||
///
|
///
|
||||||
/// If this is true, then the elements are walked using
|
/// By default, finders skip nodes that are considered "offstage". The term is
|
||||||
/// [Element.debugVisitOnstageChildren]. This skips offstage children of
|
/// very loosely defined and is only meaningful in a debug environment; it is
|
||||||
/// [Offstage] widgets, as well as children of inactive [Route]s.
|
/// 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;
|
final bool skipOffstage;
|
||||||
|
|
||||||
/// Returns all the [Element]s that will be considered by this finder.
|
/// Returns all the [Element]s that will be considered by this finder.
|
||||||
|
Loading…
Reference in New Issue
Block a user