mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
Add Overlay.maybeOf
, make Overlay.of
return a non-nullable instance (#110811)
This commit is contained in:
parent
a7ba717b2f
commit
2051f09c68
@ -132,7 +132,7 @@ class _OverlayExampleState extends State<OverlayExample> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Add the OverlayEntry to the Overlay.
|
// Add the OverlayEntry to the Overlay.
|
||||||
Overlay.of(context, debugRequiredFor: widget)!.insert(overlayEntry!);
|
Overlay.of(context, debugRequiredFor: widget).insert(overlayEntry!);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove the OverlayEntry.
|
// Remove the OverlayEntry.
|
||||||
|
@ -363,7 +363,7 @@ class _CupertinoContextMenuState extends State<CupertinoContextMenu> with Ticker
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
Overlay.of(context, rootOverlay: true, debugRequiredFor: widget)!.insert(_lastOverlayEntry!);
|
Overlay.of(context, rootOverlay: true, debugRequiredFor: widget).insert(_lastOverlayEntry!);
|
||||||
_openController.forward();
|
_openController.forward();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -655,7 +655,7 @@ class _RangeSliderState extends State<RangeSlider> with TickerProviderStateMixin
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
Overlay.of(context, debugRequiredFor: widget)!.insert(overlayEntry!);
|
Overlay.of(context, debugRequiredFor: widget).insert(overlayEntry!);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -887,7 +887,7 @@ class _SliderState extends State<Slider> with TickerProviderStateMixin {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
Overlay.of(context, debugRequiredFor: widget)!.insert(overlayEntry!);
|
Overlay.of(context, debugRequiredFor: widget).insert(overlayEntry!);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -517,7 +517,7 @@ class TooltipState extends State<Tooltip> with SingleTickerProviderStateMixin {
|
|||||||
final OverlayState overlayState = Overlay.of(
|
final OverlayState overlayState = Overlay.of(
|
||||||
context,
|
context,
|
||||||
debugRequiredFor: widget,
|
debugRequiredFor: widget,
|
||||||
)!;
|
);
|
||||||
overlayState.insert(_entry!);
|
overlayState.insert(_entry!);
|
||||||
}
|
}
|
||||||
SemanticsService.tooltip(_tooltipMessage);
|
SemanticsService.tooltip(_tooltipMessage);
|
||||||
@ -573,7 +573,7 @@ class TooltipState extends State<Tooltip> with SingleTickerProviderStateMixin {
|
|||||||
final OverlayState overlayState = Overlay.of(
|
final OverlayState overlayState = Overlay.of(
|
||||||
context,
|
context,
|
||||||
debugRequiredFor: widget,
|
debugRequiredFor: widget,
|
||||||
)!;
|
);
|
||||||
|
|
||||||
final RenderBox box = context.findRenderObject()! as RenderBox;
|
final RenderBox box = context.findRenderObject()! as RenderBox;
|
||||||
final Offset target = box.localToGlobal(
|
final Offset target = box.localToGlobal(
|
||||||
|
@ -438,7 +438,7 @@ class _RawAutocompleteState<T extends Object> extends State<RawAutocomplete<T>>
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
Overlay.of(context, rootOverlay: true, debugRequiredFor: widget)!.insert(newFloatingOptions);
|
Overlay.of(context, rootOverlay: true, debugRequiredFor: widget).insert(newFloatingOptions);
|
||||||
_floatingOptions = newFloatingOptions;
|
_floatingOptions = newFloatingOptions;
|
||||||
} else {
|
} else {
|
||||||
_floatingOptions = null;
|
_floatingOptions = null;
|
||||||
|
@ -555,7 +555,7 @@ class _DraggableState<T extends Object> extends State<Draggable<T>> {
|
|||||||
_activeCount += 1;
|
_activeCount += 1;
|
||||||
});
|
});
|
||||||
final _DragAvatar<T> avatar = _DragAvatar<T>(
|
final _DragAvatar<T> avatar = _DragAvatar<T>(
|
||||||
overlayState: Overlay.of(context, debugRequiredFor: widget, rootOverlay: widget.rootOverlay)!,
|
overlayState: Overlay.of(context, debugRequiredFor: widget, rootOverlay: widget.rootOverlay),
|
||||||
data: widget.data,
|
data: widget.data,
|
||||||
axis: widget.axis,
|
axis: widget.axis,
|
||||||
initialPosition: position,
|
initialPosition: position,
|
||||||
|
@ -168,7 +168,7 @@ class MagnifierController {
|
|||||||
/// final MagnifierController myMagnifierController = MagnifierController();
|
/// final MagnifierController myMagnifierController = MagnifierController();
|
||||||
///
|
///
|
||||||
/// // Placed below the magnifier, so it will show.
|
/// // Placed below the magnifier, so it will show.
|
||||||
/// Overlay.of(context)!.insert(OverlayEntry(
|
/// Overlay.of(context).insert(OverlayEntry(
|
||||||
/// builder: (BuildContext context) => const Text('I WILL display in the magnifier')));
|
/// builder: (BuildContext context) => const Text('I WILL display in the magnifier')));
|
||||||
///
|
///
|
||||||
/// // Will display in the magnifier, since this entry was passed to show.
|
/// // Will display in the magnifier, since this entry was passed to show.
|
||||||
@ -176,7 +176,7 @@ class MagnifierController {
|
|||||||
/// builder: (BuildContext context) =>
|
/// builder: (BuildContext context) =>
|
||||||
/// const Text('I WILL display in the magnifier'));
|
/// const Text('I WILL display in the magnifier'));
|
||||||
///
|
///
|
||||||
/// Overlay.of(context)!
|
/// Overlay.of(context)
|
||||||
/// .insert(displayInMagnifier);
|
/// .insert(displayInMagnifier);
|
||||||
/// myMagnifierController.show(
|
/// myMagnifierController.show(
|
||||||
/// context: context,
|
/// context: context,
|
||||||
@ -186,10 +186,10 @@ class MagnifierController {
|
|||||||
/// ));
|
/// ));
|
||||||
///
|
///
|
||||||
/// // By default, new entries will be placed over the top entry.
|
/// // By default, new entries will be placed over the top entry.
|
||||||
/// Overlay.of(context)!.insert(OverlayEntry(
|
/// Overlay.of(context).insert(OverlayEntry(
|
||||||
/// builder: (BuildContext context) => const Text('I WILL NOT display in the magnifier')));
|
/// builder: (BuildContext context) => const Text('I WILL NOT display in the magnifier')));
|
||||||
///
|
///
|
||||||
/// Overlay.of(context)!.insert(
|
/// Overlay.of(context).insert(
|
||||||
/// below:
|
/// below:
|
||||||
/// myMagnifierController.overlayEntry, // Explicitly placed below the magnifier.
|
/// myMagnifierController.overlayEntry, // Explicitly placed below the magnifier.
|
||||||
/// OverlayEntry(
|
/// OverlayEntry(
|
||||||
@ -246,7 +246,7 @@ class MagnifierController {
|
|||||||
overlayEntry!.remove();
|
overlayEntry!.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
final OverlayState? overlayState = Overlay.of(
|
final OverlayState overlayState = Overlay.of(
|
||||||
context,
|
context,
|
||||||
rootOverlay: true,
|
rootOverlay: true,
|
||||||
debugRequiredFor: debugRequiredFor,
|
debugRequiredFor: debugRequiredFor,
|
||||||
@ -260,7 +260,7 @@ class MagnifierController {
|
|||||||
_overlayEntry = OverlayEntry(
|
_overlayEntry = OverlayEntry(
|
||||||
builder: (BuildContext context) => capturedThemes.wrap(builder(context)),
|
builder: (BuildContext context) => capturedThemes.wrap(builder(context)),
|
||||||
);
|
);
|
||||||
overlayState!.insert(overlayEntry!, below: below);
|
overlayState.insert(overlayEntry!, below: below);
|
||||||
|
|
||||||
if (animationController != null) {
|
if (animationController != null) {
|
||||||
await animationController?.forward();
|
await animationController?.forward();
|
||||||
@ -389,7 +389,7 @@ class MagnifierDecoration extends ShapeDecoration {
|
|||||||
/// gesture, on an image or text.
|
/// gesture, on an image or text.
|
||||||
/// {@endtemplate}
|
/// {@endtemplate}
|
||||||
///
|
///
|
||||||
/// A magnifier can be convienently managed by [MagnifierController], which handles
|
/// A magnifier can be conveniently managed by [MagnifierController], which handles
|
||||||
/// showing and hiding the magnifier, with an optional entry / exit animation.
|
/// showing and hiding the magnifier, with an optional entry / exit animation.
|
||||||
///
|
///
|
||||||
/// See:
|
/// See:
|
||||||
@ -402,7 +402,7 @@ class RawMagnifier extends StatelessWidget {
|
|||||||
/// the focal point is directly under the magnifier, and there is no magnification:
|
/// the focal point is directly under the magnifier, and there is no magnification:
|
||||||
/// This means that a default magnifier will be entirely invisible to the naked eye,
|
/// This means that a default magnifier will be entirely invisible to the naked eye,
|
||||||
/// since it is painting exactly what is under it, exactly where it was painted
|
/// since it is painting exactly what is under it, exactly where it was painted
|
||||||
/// orignally.
|
/// originally.
|
||||||
/// {@endtemplate}
|
/// {@endtemplate}
|
||||||
const RawMagnifier({
|
const RawMagnifier({
|
||||||
super.key,
|
super.key,
|
||||||
@ -414,7 +414,7 @@ class RawMagnifier extends StatelessWidget {
|
|||||||
}) : assert(magnificationScale != 0,
|
}) : assert(magnificationScale != 0,
|
||||||
'Magnification scale of 0 results in undefined behavior.');
|
'Magnification scale of 0 results in undefined behavior.');
|
||||||
|
|
||||||
/// An optional widget to posiiton inside the len of the [RawMagnifier].
|
/// An optional widget to position inside the len of the [RawMagnifier].
|
||||||
///
|
///
|
||||||
/// This is positioned over the [RawMagnifier] - it may be useful for tinting the
|
/// This is positioned over the [RawMagnifier] - it may be useful for tinting the
|
||||||
/// [RawMagnifier], or drawing a crosshair like UI.
|
/// [RawMagnifier], or drawing a crosshair like UI.
|
||||||
|
@ -273,8 +273,9 @@ class _OverlayEntryWidgetState extends State<_OverlayEntryWidget> {
|
|||||||
/// [OverlayEntry] objects.
|
/// [OverlayEntry] objects.
|
||||||
///
|
///
|
||||||
/// Although you can create an [Overlay] directly, it's most common to use the
|
/// Although you can create an [Overlay] directly, it's most common to use the
|
||||||
/// overlay created by the [Navigator] in a [WidgetsApp] or a [MaterialApp]. The
|
/// overlay created by the [Navigator] in a [WidgetsApp], [CupertinoApp] or a
|
||||||
/// navigator uses its overlay to manage the visual appearance of its routes.
|
/// [MaterialApp]. The navigator uses its overlay to manage the visual
|
||||||
|
/// appearance of its routes.
|
||||||
///
|
///
|
||||||
/// The [Overlay] widget uses a custom stack implementation, which is very
|
/// The [Overlay] widget uses a custom stack implementation, which is very
|
||||||
/// similar to the [Stack] widget. The main use case of [Overlay] is related to
|
/// similar to the [Stack] widget. The main use case of [Overlay] is related to
|
||||||
@ -298,6 +299,7 @@ class _OverlayEntryWidgetState extends State<_OverlayEntryWidget> {
|
|||||||
/// * [OverlayState], which is used to insert the entries into the overlay.
|
/// * [OverlayState], which is used to insert the entries into the overlay.
|
||||||
/// * [WidgetsApp], which inserts an [Overlay] widget indirectly via its [Navigator].
|
/// * [WidgetsApp], which inserts an [Overlay] widget indirectly via its [Navigator].
|
||||||
/// * [MaterialApp], which inserts an [Overlay] widget indirectly via its [Navigator].
|
/// * [MaterialApp], which inserts an [Overlay] widget indirectly via its [Navigator].
|
||||||
|
/// * [CupertinoApp], which inserts an [Overlay] widget indirectly via its [Navigator].
|
||||||
/// * [Stack], which allows directly displaying a stack of widgets.
|
/// * [Stack], which allows directly displaying a stack of widgets.
|
||||||
class Overlay extends StatefulWidget {
|
class Overlay extends StatefulWidget {
|
||||||
/// Creates an overlay.
|
/// Creates an overlay.
|
||||||
@ -306,7 +308,8 @@ class Overlay extends StatefulWidget {
|
|||||||
/// [OverlayState] is initialized.
|
/// [OverlayState] is initialized.
|
||||||
///
|
///
|
||||||
/// Rather than creating an overlay, consider using the overlay that is
|
/// Rather than creating an overlay, consider using the overlay that is
|
||||||
/// created by the [Navigator] in a [WidgetsApp] or a [MaterialApp] for the application.
|
/// created by the [Navigator] in a [WidgetsApp], [CupertinoApp], or a
|
||||||
|
/// [MaterialApp] for the application.
|
||||||
const Overlay({
|
const Overlay({
|
||||||
super.key,
|
super.key,
|
||||||
this.initialEntries = const <OverlayEntry>[],
|
this.initialEntries = const <OverlayEntry>[],
|
||||||
@ -334,40 +337,46 @@ class Overlay extends StatefulWidget {
|
|||||||
/// Defaults to [Clip.hardEdge], and must not be null.
|
/// Defaults to [Clip.hardEdge], and must not be null.
|
||||||
final Clip clipBehavior;
|
final Clip clipBehavior;
|
||||||
|
|
||||||
/// The state from the closest instance of this class that encloses the given context.
|
/// The [OverlayState] from the closest instance of [Overlay] that encloses
|
||||||
|
/// the given context, and, in debug mode, will throw if one is not found.
|
||||||
///
|
///
|
||||||
/// In debug mode, if the `debugRequiredFor` argument is provided then this
|
/// In debug mode, if the `debugRequiredFor` argument is provided and an
|
||||||
/// function will assert that an overlay was found and will throw an exception
|
/// overlay isn't found, then this function will throw an exception containing
|
||||||
/// if not. The exception attempts to explain that the calling [Widget] (the
|
/// the runtime type of the given widget in the error message. The exception
|
||||||
/// one given by the `debugRequiredFor` argument) needs an [Overlay] to be
|
/// attempts to explain that the calling [Widget] (the one given by the
|
||||||
/// present to function.
|
/// `debugRequiredFor` argument) needs an [Overlay] to be present to function.
|
||||||
|
/// If `debugRequiredFor` is not supplied, then the error message is more
|
||||||
|
/// generic.
|
||||||
///
|
///
|
||||||
/// Typical usage is as follows:
|
/// Typical usage is as follows:
|
||||||
///
|
///
|
||||||
/// ```dart
|
/// ```dart
|
||||||
/// OverlayState overlay = Overlay.of(context)!;
|
/// OverlayState overlay = Overlay.of(context);
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// If `rootOverlay` is set to true, the state from the furthest instance of
|
/// If `rootOverlay` is set to true, the state from the furthest instance of
|
||||||
/// this class is given instead. Useful for installing overlay entries
|
/// this class is given instead. Useful for installing overlay entries above
|
||||||
/// above all subsequent instances of [Overlay].
|
/// all subsequent instances of [Overlay].
|
||||||
///
|
///
|
||||||
/// This method can be expensive (it walks the element tree).
|
/// This method can be expensive (it walks the element tree).
|
||||||
static OverlayState? of(
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [Overlay.maybeOf] for a similar function that returns null if an
|
||||||
|
/// [Overlay] is not found.
|
||||||
|
static OverlayState of(
|
||||||
BuildContext context, {
|
BuildContext context, {
|
||||||
bool rootOverlay = false,
|
bool rootOverlay = false,
|
||||||
Widget? debugRequiredFor,
|
Widget? debugRequiredFor,
|
||||||
}) {
|
}) {
|
||||||
final OverlayState? result = rootOverlay
|
final OverlayState? result = maybeOf(context, rootOverlay: rootOverlay);
|
||||||
? context.findRootAncestorStateOfType<OverlayState>()
|
|
||||||
: context.findAncestorStateOfType<OverlayState>();
|
|
||||||
assert(() {
|
assert(() {
|
||||||
if (debugRequiredFor != null && result == null) {
|
if (result == null) {
|
||||||
final List<DiagnosticsNode> information = <DiagnosticsNode>[
|
final List<DiagnosticsNode> information = <DiagnosticsNode>[
|
||||||
ErrorSummary('No Overlay widget found.'),
|
ErrorSummary('No Overlay widget found.'),
|
||||||
ErrorDescription('${debugRequiredFor.runtimeType} widgets require an Overlay widget ancestor for correct operation.'),
|
ErrorDescription('${debugRequiredFor?.runtimeType ?? 'Some'} widgets require an Overlay widget ancestor for correct operation.'),
|
||||||
ErrorHint('The most common way to add an Overlay to an application is to include a MaterialApp or Navigator widget in the runApp() call.'),
|
ErrorHint('The most common way to add an Overlay to an application is to include a MaterialApp, CupertinoApp or Navigator widget in the runApp() call.'),
|
||||||
DiagnosticsProperty<Widget>('The specific widget that failed to find an overlay was', debugRequiredFor, style: DiagnosticsTreeStyle.errorProperty),
|
if (debugRequiredFor != null) DiagnosticsProperty<Widget>('The specific widget that failed to find an overlay was', debugRequiredFor, style: DiagnosticsTreeStyle.errorProperty),
|
||||||
if (context.widget != debugRequiredFor)
|
if (context.widget != debugRequiredFor)
|
||||||
context.describeElement('The context from which that widget was searching for an overlay was'),
|
context.describeElement('The context from which that widget was searching for an overlay was'),
|
||||||
];
|
];
|
||||||
@ -376,7 +385,36 @@ class Overlay extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}());
|
}());
|
||||||
return result;
|
return result!;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The [OverlayState] from the closest instance of [Overlay] that encloses
|
||||||
|
/// the given context, if any.
|
||||||
|
///
|
||||||
|
/// Typical usage is as follows:
|
||||||
|
///
|
||||||
|
/// ```dart
|
||||||
|
/// OverlayState? overlay = Overlay.maybeOf(context);
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// If `rootOverlay` is set to true, the state from the furthest instance of
|
||||||
|
/// this class is given instead. Useful for installing overlay entries above
|
||||||
|
/// all subsequent instances of [Overlay].
|
||||||
|
///
|
||||||
|
/// This method can be expensive (it walks the element tree).
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [Overlay.of] for a similar function that returns a non-nullable result
|
||||||
|
/// and throws if an [Overlay] is not found.
|
||||||
|
|
||||||
|
static OverlayState? maybeOf(
|
||||||
|
BuildContext context, {
|
||||||
|
bool rootOverlay = false,
|
||||||
|
}) {
|
||||||
|
return rootOverlay
|
||||||
|
? context.findRootAncestorStateOfType<OverlayState>()
|
||||||
|
: context.findAncestorStateOfType<OverlayState>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -728,7 +728,7 @@ class SliverReorderableListState extends State<SliverReorderableList> with Ticke
|
|||||||
);
|
);
|
||||||
_dragInfo!.startDrag();
|
_dragInfo!.startDrag();
|
||||||
|
|
||||||
final OverlayState overlay = Overlay.of(context, debugRequiredFor: widget)!;
|
final OverlayState overlay = Overlay.of(context, debugRequiredFor: widget);
|
||||||
assert(_overlayEntry == null);
|
assert(_overlayEntry == null);
|
||||||
_overlayEntry = OverlayEntry(builder: _dragInfo!.createProxy);
|
_overlayEntry = OverlayEntry(builder: _dragInfo!.createProxy);
|
||||||
overlay.insert(_overlayEntry!);
|
overlay.insert(_overlayEntry!);
|
||||||
@ -923,7 +923,7 @@ class SliverReorderableListState extends State<SliverReorderableList> with Ticke
|
|||||||
}
|
}
|
||||||
final Widget child = widget.itemBuilder(context, index);
|
final Widget child = widget.itemBuilder(context, index);
|
||||||
assert(child.key != null, 'All list items must have a key');
|
assert(child.key != null, 'All list items must have a key');
|
||||||
final OverlayState overlay = Overlay.of(context, debugRequiredFor: widget)!;
|
final OverlayState overlay = Overlay.of(context, debugRequiredFor: widget);
|
||||||
return _ReorderableItem(
|
return _ReorderableItem(
|
||||||
key: _ReorderableItemGlobalKey(child.key!, index, this),
|
key: _ReorderableItemGlobalKey(child.key!, index, this),
|
||||||
index: index,
|
index: index,
|
||||||
@ -1310,7 +1310,7 @@ class _DragInfo extends Drag {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Offset _overlayOrigin(BuildContext context) {
|
Offset _overlayOrigin(BuildContext context) {
|
||||||
final OverlayState overlay = Overlay.of(context, debugRequiredFor: context.widget)!;
|
final OverlayState overlay = Overlay.of(context, debugRequiredFor: context.widget);
|
||||||
final RenderBox overlayBox = overlay.context.findRenderObject()! as RenderBox;
|
final RenderBox overlayBox = overlay.context.findRenderObject()! as RenderBox;
|
||||||
return overlayBox.localToGlobal(Offset.zero);
|
return overlayBox.localToGlobal(Offset.zero);
|
||||||
}
|
}
|
||||||
|
@ -120,7 +120,7 @@ abstract class TextSelectionControls {
|
|||||||
List<TextSelectionPoint> endpoints,
|
List<TextSelectionPoint> endpoints,
|
||||||
TextSelectionDelegate delegate,
|
TextSelectionDelegate delegate,
|
||||||
// TODO(chunhtai): Change to ValueListenable<ClipboardStatus>? once
|
// TODO(chunhtai): Change to ValueListenable<ClipboardStatus>? once
|
||||||
// mirgration is done. https://github.com/flutter/flutter/issues/99360
|
// migration is done. https://github.com/flutter/flutter/issues/99360
|
||||||
ClipboardStatusNotifier? clipboardStatus,
|
ClipboardStatusNotifier? clipboardStatus,
|
||||||
Offset? lastSecondaryTapDownPosition,
|
Offset? lastSecondaryTapDownPosition,
|
||||||
);
|
);
|
||||||
@ -793,16 +793,16 @@ class SelectionOverlay {
|
|||||||
/// a magnifierBuilder will not be provided, or the magnifierBuilder will return null
|
/// a magnifierBuilder will not be provided, or the magnifierBuilder will return null
|
||||||
/// on platforms not mobile.
|
/// on platforms not mobile.
|
||||||
///
|
///
|
||||||
/// This is NOT the souce of truth for if the magnifier is up or not,
|
/// This is NOT the source of truth for if the magnifier is up or not,
|
||||||
/// since magnifiers may hide themselves. If this info is needed, check
|
/// since magnifiers may hide themselves. If this info is needed, check
|
||||||
/// [MagnifierController.shown].
|
/// [MagnifierController.shown].
|
||||||
void showMagnifier(MagnifierOverlayInfoBearer initalInfoBearer) {
|
void showMagnifier(MagnifierOverlayInfoBearer initialInfoBearer) {
|
||||||
if (_toolbar != null) {
|
if (_toolbar != null) {
|
||||||
hideToolbar();
|
hideToolbar();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start from empty, so we don't utilize any rememnant values.
|
// Start from empty, so we don't utilize any remnant values.
|
||||||
_magnifierOverlayInfoBearer.value = initalInfoBearer;
|
_magnifierOverlayInfoBearer.value = initialInfoBearer;
|
||||||
|
|
||||||
// Pre-build the magnifiers so we can tell if we've built something
|
// Pre-build the magnifiers so we can tell if we've built something
|
||||||
// or not. If we don't build a magnifiers, then we should not
|
// or not. If we don't build a magnifiers, then we should not
|
||||||
@ -1062,8 +1062,7 @@ class SelectionOverlay {
|
|||||||
OverlayEntry(builder: _buildEndHandle),
|
OverlayEntry(builder: _buildEndHandle),
|
||||||
];
|
];
|
||||||
|
|
||||||
Overlay.of(context, rootOverlay: true, debugRequiredFor: debugRequiredFor)!
|
Overlay.of(context, rootOverlay: true, debugRequiredFor: debugRequiredFor).insertAll(_handles!);
|
||||||
.insertAll(_handles!);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// {@template flutter.widgets.SelectionOverlay.hideHandles}
|
/// {@template flutter.widgets.SelectionOverlay.hideHandles}
|
||||||
@ -1085,7 +1084,7 @@ class SelectionOverlay {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_toolbar = OverlayEntry(builder: _buildToolbar);
|
_toolbar = OverlayEntry(builder: _buildToolbar);
|
||||||
Overlay.of(context, rootOverlay: true, debugRequiredFor: debugRequiredFor)!.insert(_toolbar!);
|
Overlay.of(context, rootOverlay: true, debugRequiredFor: debugRequiredFor).insert(_toolbar!);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _buildScheduled = false;
|
bool _buildScheduled = false;
|
||||||
|
@ -226,7 +226,7 @@ void main() {
|
|||||||
final OverlayEntry fakeBeforeOverlayEntry =
|
final OverlayEntry fakeBeforeOverlayEntry =
|
||||||
OverlayEntry(builder: (_) => fakeBefore);
|
OverlayEntry(builder: (_) => fakeBefore);
|
||||||
|
|
||||||
Overlay.of(context)!.insert(fakeBeforeOverlayEntry);
|
Overlay.of(context).insert(fakeBeforeOverlayEntry);
|
||||||
magnifierController.show(
|
magnifierController.show(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (_) => fakeMagnifier,
|
builder: (_) => fakeMagnifier,
|
||||||
|
@ -694,7 +694,7 @@ void main() {
|
|||||||
await tester.pump();
|
await tester.pump();
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets('OverlayState.of() called without Overlay being exist', (WidgetTester tester) async {
|
testWidgets('OverlayState.of() throws when called if an Overlay does not exist', (WidgetTester tester) async {
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
Directionality(
|
Directionality(
|
||||||
textDirection: TextDirection.ltr,
|
textDirection: TextDirection.ltr,
|
||||||
@ -712,7 +712,8 @@ void main() {
|
|||||||
expect(error.diagnostics[2].level, DiagnosticLevel.hint);
|
expect(error.diagnostics[2].level, DiagnosticLevel.hint);
|
||||||
expect(error.diagnostics[2].toStringDeep(), equalsIgnoringHashCodes(
|
expect(error.diagnostics[2].toStringDeep(), equalsIgnoringHashCodes(
|
||||||
'The most common way to add an Overlay to an application is to\n'
|
'The most common way to add an Overlay to an application is to\n'
|
||||||
'include a MaterialApp or Navigator widget in the runApp() call.\n',
|
'include a MaterialApp, CupertinoApp or Navigator widget in the\n'
|
||||||
|
'runApp() call.\n'
|
||||||
));
|
));
|
||||||
expect(error.diagnostics[3], isA<DiagnosticsProperty<Widget>>());
|
expect(error.diagnostics[3], isA<DiagnosticsProperty<Widget>>());
|
||||||
expect(error.diagnostics[3].value, debugRequiredFor);
|
expect(error.diagnostics[3].value, debugRequiredFor);
|
||||||
@ -723,12 +724,13 @@ void main() {
|
|||||||
' Container widgets require an Overlay widget ancestor for correct\n'
|
' Container widgets require an Overlay widget ancestor for correct\n'
|
||||||
' operation.\n'
|
' operation.\n'
|
||||||
' The most common way to add an Overlay to an application is to\n'
|
' The most common way to add an Overlay to an application is to\n'
|
||||||
' include a MaterialApp or Navigator widget in the runApp() call.\n'
|
' include a MaterialApp, CupertinoApp or Navigator widget in the\n'
|
||||||
|
' runApp() call.\n'
|
||||||
' The specific widget that failed to find an overlay was:\n'
|
' The specific widget that failed to find an overlay was:\n'
|
||||||
' Container\n'
|
' Container\n'
|
||||||
' The context from which that widget was searching for an overlay\n'
|
' The context from which that widget was searching for an overlay\n'
|
||||||
' was:\n'
|
' was:\n'
|
||||||
' Builder\n',
|
' Builder\n'
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
return Container();
|
return Container();
|
||||||
@ -738,6 +740,47 @@ void main() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWidgets("OverlayState.maybeOf() works when an Overlay does and doesn't exist", (WidgetTester tester) async {
|
||||||
|
final GlobalKey overlayKey = GlobalKey();
|
||||||
|
OverlayState? foundState;
|
||||||
|
|
||||||
|
await tester.pumpWidget(
|
||||||
|
Directionality(
|
||||||
|
textDirection: TextDirection.ltr,
|
||||||
|
child: Overlay(
|
||||||
|
key: overlayKey,
|
||||||
|
initialEntries: <OverlayEntry>[
|
||||||
|
OverlayEntry(
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
foundState = Overlay.maybeOf(context);
|
||||||
|
return Container();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(tester.takeException(), isNull);
|
||||||
|
expect(foundState, isNotNull);
|
||||||
|
foundState = null;
|
||||||
|
|
||||||
|
await tester.pumpWidget(
|
||||||
|
Directionality(
|
||||||
|
textDirection: TextDirection.ltr,
|
||||||
|
child: Builder(
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
foundState = Overlay.maybeOf(context);
|
||||||
|
return const SizedBox();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(tester.takeException(), isNull);
|
||||||
|
expect(foundState, isNull);
|
||||||
|
});
|
||||||
|
|
||||||
testWidgets('OverlayEntry.opaque can be changed when OverlayEntry is not part of an Overlay (yet)', (WidgetTester tester) async {
|
testWidgets('OverlayEntry.opaque can be changed when OverlayEntry is not part of an Overlay (yet)', (WidgetTester tester) async {
|
||||||
final GlobalKey<OverlayState> overlayKey = GlobalKey<OverlayState>();
|
final GlobalKey<OverlayState> overlayKey = GlobalKey<OverlayState>();
|
||||||
final Key root = UniqueKey();
|
final Key root = UniqueKey();
|
||||||
|
Loading…
Reference in New Issue
Block a user