Added example for Magnifier and TextMagnifier (#110218)

This commit is contained in:
Anthony Oleinik 2022-09-23 15:29:32 -05:00 committed by GitHub
parent dc2618bb90
commit 4ceeca0833
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 494 additions and 139 deletions

View file

@ -0,0 +1,62 @@
// Copyright 2014 The Flutter 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';
void main() => runApp(const MyApp());
class MyApp extends StatefulWidget {
const MyApp({super.key});
static const Size loupeSize = Size(200, 200);
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
Offset dragGesturePositon = Offset.zero;
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text('Drag on the logo!'),
RepaintBoundary(
child: Stack(
children: <Widget>[
GestureDetector(
onPanUpdate: (DragUpdateDetails details) => setState(
() {
dragGesturePositon = details.localPosition;
},
),
child: const FlutterLogo(size: 200),
),
Positioned(
left: dragGesturePositon.dx,
top: dragGesturePositon.dy,
child: const RawMagnifier(
decoration: MagnifierDecoration(
shape: CircleBorder(
side: BorderSide(color: Colors.pink, width: 3),
),
),
size: Size(100, 100),
magnificationScale: 2,
),
)
],
),
),
],
),
),
),
);
}
}

View file

@ -0,0 +1,112 @@
// Copyright 2014 The Flutter 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/foundation.dart';
import 'package:flutter/material.dart';
void main() => runApp(const MyApp(text: 'Hello world!'));
class MyApp extends StatelessWidget {
const MyApp({
super.key,
this.textDirection = TextDirection.ltr,
required this.text,
});
final TextDirection textDirection;
final String text;
static const Size loupeSize = Size(200, 200);
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Padding(
padding: const EdgeInsets.symmetric(horizontal: 48.0),
child: Center(
child: TextField(
textDirection: textDirection,
// Create a custom magnifier configuration that
// this `TextField` will use to build a magnifier with.
magnifierConfiguration: TextMagnifierConfiguration(
magnifierBuilder: (_, __, ValueNotifier<MagnifierInfo> magnifierInfo) => CustomMagnifier(
magnifierInfo: magnifierInfo,
),
),
controller: TextEditingController(text: text),
),
),
),
),
);
}
}
class CustomMagnifier extends StatelessWidget {
const CustomMagnifier({super.key, required this.magnifierInfo});
static const Size magnifierSize = Size(200, 200);
// This magnifier will consume some text data and position itself
// based on the info in the magnifier.
final ValueNotifier<MagnifierInfo> magnifierInfo;
@override
Widget build(BuildContext context) {
// Use a value listenable builder because we want to rebuild
// every time the text selection info changes.
// `CustomMagnifier` could also be a `StatefulWidget` and call `setState`
// when `magnifierInfo` updates. This would be useful for more complex
// positioning cases.
return ValueListenableBuilder<MagnifierInfo>(
valueListenable: magnifierInfo,
builder: (BuildContext context,
MagnifierInfo currentMagnifierInfo, _) {
// We want to position the magnifier at the global position of the gesture.
Offset magnifierPosition = currentMagnifierInfo.globalGesturePosition;
// You may use the `MagnifierInfo` however you'd like:
// In this case, we make sure the magnifier never goes out of the current line bounds.
magnifierPosition = Offset(
clampDouble(
magnifierPosition.dx,
currentMagnifierInfo.currentLineBoundaries.left,
currentMagnifierInfo.currentLineBoundaries.right,
),
clampDouble(
magnifierPosition.dy,
currentMagnifierInfo.currentLineBoundaries.top,
currentMagnifierInfo.currentLineBoundaries.bottom,
),
);
// Finally, align the magnifier to the bottom center. The inital anchor is
// the top left, so subtract bottom center alignment.
magnifierPosition -= Alignment.bottomCenter.alongSize(magnifierSize);
return Positioned(
left: magnifierPosition.dx,
top: magnifierPosition.dy,
child: RawMagnifier(
magnificationScale: 2,
// The focal point starts at the center of the magnifier.
// We probably want to point below the magnifier, so
// offset the focal point by half the magnifier height.
focalPointOffset: Offset(0, magnifierSize.height / 2),
// Decorate it however we'd like!
decoration: const MagnifierDecoration(
shape: StarBorder(
side: BorderSide(
color: Colors.green,
width: 2,
),
),
),
size: magnifierSize,
),
);
});
}
}

View file

@ -0,0 +1,56 @@
// Copyright 2014 The Flutter 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_api_samples/widgets/magnifier/magnifier.0.dart'
as example;
import 'package:flutter_test/flutter_test.dart';
void main() {
testWidgets('should update magnifier position on drag', (WidgetTester tester) async {
await tester.pumpWidget(const example.MyApp());
Matcher isPositionedAt(Offset at) {
return isA<Positioned>().having(
(Positioned positioned) => Offset(positioned.left!, positioned.top!),
'magnifier position',
at,
);
}
expect(
tester.widget(find.byType(Positioned)),
isPositionedAt(Offset.zero),
);
final Offset centerOfFlutterLogo = tester.getCenter(find.byType(Positioned));
final Offset topLeftOfFlutterLogo = tester.getTopLeft(find.byType(FlutterLogo));
const Offset dragDistance = Offset(10, 10);
await tester.dragFrom(centerOfFlutterLogo, dragDistance);
await tester.pump();
expect(
tester.widget(find.byType(Positioned)),
// Need to adjust by the topleft since the position is local.
isPositionedAt((centerOfFlutterLogo - topLeftOfFlutterLogo) + dragDistance),
);
});
testWidgets('should match golden', (WidgetTester tester) async {
await tester.pumpWidget(const example.MyApp());
final Offset centerOfFlutterLogo = tester.getCenter(find.byType(Positioned));
const Offset dragDistance = Offset(10, 10);
await tester.dragFrom(centerOfFlutterLogo, dragDistance);
await tester.pump();
await expectLater(
find.byType(RepaintBoundary).last,
matchesGoldenFile('magnifier.0_test.png'),
);
});
}

View file

@ -0,0 +1,111 @@
// Copyright 2014 The Flutter 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/rendering.dart';
import 'package:flutter_api_samples/widgets/text_magnifier/text_magnifier.0.dart'
as example;
import 'package:flutter_test/flutter_test.dart';
List<TextSelectionPoint> _globalize(
Iterable<TextSelectionPoint> points, RenderBox box) {
return points.map<TextSelectionPoint>((TextSelectionPoint point) {
return TextSelectionPoint(
box.localToGlobal(point.point),
point.direction,
);
}).toList();
}
RenderEditable _findRenderEditable<T extends State<StatefulWidget>>(WidgetTester tester) {
return (tester.state(find.byType(TextField))
as TextSelectionGestureDetectorBuilderDelegate)
.editableTextKey
.currentState!
.renderEditable;
}
Offset _textOffsetToPosition<T extends State<StatefulWidget>>(WidgetTester tester, int offset) {
final RenderEditable renderEditable = _findRenderEditable(tester);
final List<TextSelectionPoint> endpoints = renderEditable
.getEndpointsForSelection(
TextSelection.collapsed(offset: offset),
)
.map<TextSelectionPoint>((TextSelectionPoint point) => TextSelectionPoint(
renderEditable.localToGlobal(point.point),
point.direction,
))
.toList();
return endpoints[0].point + const Offset(0.0, -2.0);
}
void main() {
const Duration durationBetweenActons = Duration(milliseconds: 20);
const String defaultText = 'I am a magnifier, fear me!';
Future<void> showMagnifier(WidgetTester tester, String characterToTapOn) async {
final Offset tapOffset = _textOffsetToPosition(tester, defaultText.indexOf(characterToTapOn));
// Double tap 'Magnifier' word to show the selection handles.
final TestGesture testGesture = await tester.startGesture(tapOffset);
await tester.pump(durationBetweenActons);
await testGesture.up();
await tester.pump(durationBetweenActons);
await testGesture.down(tapOffset);
await tester.pump(durationBetweenActons);
await testGesture.up();
await tester.pumpAndSettle();
final TextSelection selection = tester
.firstWidget<TextField>(find.byType(TextField))
.controller!
.selection;
final RenderEditable renderEditable = _findRenderEditable(tester);
final List<TextSelectionPoint> endpoints = _globalize(
renderEditable.getEndpointsForSelection(selection),
renderEditable,
);
final Offset handlePos = endpoints.last.point + const Offset(10.0, 10.0);
final TestGesture gesture = await tester.startGesture(handlePos);
await gesture.moveTo(
_textOffsetToPosition(
tester,
defaultText.length - 2,
),
);
await tester.pump();
}
testWidgets('should show custom magnifier on drag', (WidgetTester tester) async {
await tester.pumpWidget(const example.MyApp(text: defaultText));
await showMagnifier(tester, 'e');
expect(find.byType(example.CustomMagnifier), findsOneWidget);
await expectLater(
find.byType(example.MyApp),
matchesGoldenFile('text_magnifier.0_test.png'),
);
}, variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.android }));
for (final TextDirection textDirection in TextDirection.values) {
testWidgets('should show custom magnifier in $textDirection', (WidgetTester tester) async {
final String text = textDirection == TextDirection.rtl ? 'أثارت زر' : defaultText;
final String textToTapOn = textDirection == TextDirection.rtl ? 'ت' : 'e';
await tester.pumpWidget(example.MyApp(textDirection: textDirection, text: text));
await showMagnifier(tester, textToTapOn);
expect(find.byType(example.CustomMagnifier), findsOneWidget);
});
}
}

View file

@ -9,7 +9,7 @@ import 'package:flutter/widgets.dart';
/// finger may be blocking the point of interest, like a selection handle.
///
/// Delegates styling to [CupertinoMagnifier] with its position depending on
/// [magnifierOverlayInfoBearer].
/// [magnifierInfo].
///
/// Specifically, the [CupertinoTextMagnifier] follows the following rules.
/// [CupertinoTextMagnifier]:
@ -21,7 +21,7 @@ import 'package:flutter/widgets.dart';
/// then has vertical offset [dragResistance] * k.
class CupertinoTextMagnifier extends StatefulWidget {
/// Constructs a [RawMagnifier] in the Cupertino style, positioning with respect to
/// [magnifierOverlayInfoBearer].
/// [magnifierInfo].
///
/// The default constructor parameters and constants were eyeballed on
/// an iPhone XR iOS v15.5.
@ -32,7 +32,7 @@ class CupertinoTextMagnifier extends StatefulWidget {
this.dragResistance = 10.0,
this.hideBelowThreshold = 48.0,
this.horizontalScreenEdgePadding = 10.0,
required this.magnifierOverlayInfoBearer,
required this.magnifierInfo,
});
/// The curve used for the in / out animations.
@ -63,9 +63,9 @@ class CupertinoTextMagnifier extends StatefulWidget {
final double horizontalScreenEdgePadding;
/// [CupertinoTextMagnifier] will determine its own positioning
/// based on the [MagnifierOverlayInfoBearer] of this notifier.
final ValueNotifier<MagnifierOverlayInfoBearer>
magnifierOverlayInfoBearer;
/// based on the [MagnifierInfo] of this notifier.
final ValueNotifier<MagnifierInfo>
magnifierInfo;
/// The duration that the magnifier drags behind its final position.
static const Duration _kDragAnimationDuration = Duration(milliseconds: 45);
@ -95,7 +95,7 @@ class _CupertinoTextMagnifierState extends State<CupertinoTextMagnifier>
)..addListener(() => setState(() {}));
widget.controller.animationController = _ioAnimationController;
widget.magnifierOverlayInfoBearer
widget.magnifierInfo
.addListener(_determineMagnifierPositionAndFocalPoint);
_ioAnimation = Tween<double>(
@ -111,16 +111,16 @@ class _CupertinoTextMagnifierState extends State<CupertinoTextMagnifier>
void dispose() {
widget.controller.animationController = null;
_ioAnimationController.dispose();
widget.magnifierOverlayInfoBearer
widget.magnifierInfo
.removeListener(_determineMagnifierPositionAndFocalPoint);
super.dispose();
}
@override
void didUpdateWidget(CupertinoTextMagnifier oldWidget) {
if (oldWidget.magnifierOverlayInfoBearer != widget.magnifierOverlayInfoBearer) {
oldWidget.magnifierOverlayInfoBearer.removeListener(_determineMagnifierPositionAndFocalPoint);
widget.magnifierOverlayInfoBearer.addListener(_determineMagnifierPositionAndFocalPoint);
if (oldWidget.magnifierInfo != widget.magnifierInfo) {
oldWidget.magnifierInfo.removeListener(_determineMagnifierPositionAndFocalPoint);
widget.magnifierInfo.addListener(_determineMagnifierPositionAndFocalPoint);
}
super.didUpdateWidget(oldWidget);
}
@ -132,8 +132,8 @@ class _CupertinoTextMagnifierState extends State<CupertinoTextMagnifier>
}
void _determineMagnifierPositionAndFocalPoint() {
final MagnifierOverlayInfoBearer textEditingContext =
widget.magnifierOverlayInfoBearer.value;
final MagnifierInfo textEditingContext =
widget.magnifierInfo.value;
// The exact Y of the center of the current line.
final double verticalCenterOfCurrentLine =
@ -228,7 +228,7 @@ class _CupertinoTextMagnifierState extends State<CupertinoTextMagnifier>
///
/// * [RawMagnifier], the backing implementation.
/// * [CupertinoTextMagnifier], a widget that positions [CupertinoMagnifier] based on
/// [MagnifierOverlayInfoBearer].
/// [MagnifierInfo].
/// * [MagnifierController], the controller for this magnifier.
class CupertinoMagnifier extends StatelessWidget {
/// Creates a [RawMagnifier] in the Cupertino style.

View file

@ -798,9 +798,11 @@ class CupertinoTextField extends StatefulWidget {
/// platforms. If it is desired to suppress the magnifier, consider passing
/// [TextMagnifierConfiguration.disabled].
///
// TODO(antholeole): https://github.com/flutter/flutter/issues/108041
// once the magnifier PR lands, I should enrich this area of the
// docs with images of what a magnifier is.
/// {@tool dartpad}
/// This sample demonstrates how to customize the magnifier that this text field uses.
///
/// ** See code in examples/api/lib/widgets/text_magnifier/text_magnifier.0.dart **
/// {@end-tool}
final TextMagnifierConfiguration? magnifierConfiguration;
/// {@macro flutter.widgets.EditableText.spellCheckConfiguration}
@ -873,14 +875,14 @@ class CupertinoTextField extends StatefulWidget {
magnifierBuilder: (
BuildContext context,
MagnifierController controller,
ValueNotifier<MagnifierOverlayInfoBearer> magnifierOverlayInfoBearer
ValueNotifier<MagnifierInfo> magnifierInfo
) {
switch (defaultTargetPlatform) {
case TargetPlatform.android:
case TargetPlatform.iOS:
return CupertinoTextMagnifier(
controller: controller,
magnifierOverlayInfoBearer: magnifierOverlayInfoBearer,
magnifierInfo: magnifierInfo,
);
case TargetPlatform.fuchsia:
case TargetPlatform.linux:

View file

@ -45,17 +45,17 @@ class TextMagnifier extends StatefulWidget {
magnifierBuilder: (
BuildContext context,
MagnifierController controller,
ValueNotifier<MagnifierOverlayInfoBearer> magnifierOverlayInfoBearer,
ValueNotifier<MagnifierInfo> magnifierInfo,
) {
switch (defaultTargetPlatform) {
case TargetPlatform.iOS:
return CupertinoTextMagnifier(
controller: controller,
magnifierOverlayInfoBearer: magnifierOverlayInfoBearer,
magnifierInfo: magnifierInfo,
);
case TargetPlatform.android:
return TextMagnifier(
magnifierInfo: magnifierOverlayInfoBearer,
magnifierInfo: magnifierInfo,
);
case TargetPlatform.fuchsia:
case TargetPlatform.linux:
@ -75,7 +75,7 @@ class TextMagnifier extends StatefulWidget {
/// [TextMagnifier] positions itself based on [magnifierInfo].
///
/// {@macro widgets.material.magnifier.positionRules}
final ValueNotifier<MagnifierOverlayInfoBearer>
final ValueNotifier<MagnifierInfo>
magnifierInfo;
@override
@ -132,7 +132,7 @@ class _TextMagnifierState extends State<TextMagnifier> {
/// {@macro widgets.material.magnifier.positionRules}
void _determineMagnifierPositionAndFocalPoint() {
final MagnifierOverlayInfoBearer selectionInfo =
final MagnifierInfo selectionInfo =
widget.magnifierInfo.value;
final Rect screenRect = Offset.zero & MediaQuery.of(context).size;

View file

@ -436,6 +436,12 @@ class TextField extends StatefulWidget {
/// By default, builds a [CupertinoTextMagnifier] on iOS and [TextMagnifier]
/// on Android, and builds nothing on all other platforms. If it is desired to
/// suppress the magnifier, consider passing [TextMagnifierConfiguration.disabled].
///
/// {@tool dartpad}
/// This sample demonstrates how to customize the magnifier that this text field uses.
///
/// ** See code in examples/api/lib/widgets/text_magnifier/text_magnifier.0.dart **
/// {@end-tool}
final TextMagnifierConfiguration? magnifierConfiguration;
/// Controls the text being edited.

View file

@ -18,7 +18,7 @@ import 'overlay.dart';
/// {@template flutter.widgets.magnifier.MagnifierBuilder}
/// Signature for a builder that builds a [Widget] with a [MagnifierController].
///
/// Consuming [MagnifierController] or [ValueNotifier]<[MagnifierOverlayInfoBearer]> is not
/// Consuming [MagnifierController] or [ValueNotifier]<[MagnifierInfo]> is not
/// required, although if a Widget intends to have entry or exit animations, it should take
/// [MagnifierController] and provide it an [AnimationController], so that [MagnifierController]
/// can wait before removing it from the overlay.
@ -26,28 +26,28 @@ import 'overlay.dart';
///
/// See also:
///
/// - [MagnifierOverlayInfoBearer], the data class that updates the
/// - [MagnifierInfo], the data class that updates the
/// magnifier.
typedef MagnifierBuilder = Widget? Function(
BuildContext context,
MagnifierController controller,
ValueNotifier<MagnifierOverlayInfoBearer> magnifierOverlayInfoBearer,
ValueNotifier<MagnifierInfo> magnifierInfo,
);
/// A data class that contains the geometry information of text layouts
/// and selection gestures, used to position magnifiers.
@immutable
class MagnifierOverlayInfoBearer {
/// Constructs a [MagnifierOverlayInfoBearer] from provided geometry values.
const MagnifierOverlayInfoBearer({
class MagnifierInfo {
/// Constructs a [MagnifierInfo] from provided geometry values.
const MagnifierInfo({
required this.globalGesturePosition,
required this.caretRect,
required this.fieldBounds,
required this.currentLineBoundaries,
});
/// Const [MagnifierOverlayInfoBearer] with all values set to 0.
static const MagnifierOverlayInfoBearer empty = MagnifierOverlayInfoBearer(
/// Const [MagnifierInfo] with all values set to 0.
static const MagnifierInfo empty = MagnifierInfo(
globalGesturePosition: Offset.zero,
caretRect: Rect.zero,
currentLineBoundaries: Rect.zero,
@ -73,7 +73,7 @@ class MagnifierOverlayInfoBearer {
if (identical(this, other)) {
return true;
}
return other is MagnifierOverlayInfoBearer
return other is MagnifierInfo
&& other.globalGesturePosition == globalGesturePosition
&& other.caretRect == caretRect
&& other.currentLineBoundaries == currentLineBoundaries
@ -388,6 +388,12 @@ class MagnifierDecoration extends ShapeDecoration {
/// A common base class for magnifiers.
///
/// {@tool dartpad}
/// This sample demonstrates what a magnifier is, and how it can be used.
///
/// ** See code in examples/api/lib/widgets/magnifier/magnifier.0.dart **
/// {@end-tool}
///
/// {@template flutter.widgets.magnifier.intro}
/// This magnifying glass is useful for scenarios on mobile devices where
/// the user's finger may be covering part of the screen where a granular

View file

@ -569,7 +569,7 @@ class _SelectableRegionState extends State<SelectableRegion> with TextSelectionD
));
}
MagnifierOverlayInfoBearer _buildInfoForMagnifier(Offset globalGesturePosition, SelectionPoint selectionPoint) {
MagnifierInfo _buildInfoForMagnifier(Offset globalGesturePosition, SelectionPoint selectionPoint) {
final Vector3 globalTransform = _selectable!.getTransformTo(null).getTranslation();
final Offset globalTransformAsOffset = Offset(globalTransform.x, globalTransform.y);
final Offset globalSelectionPointPosition = selectionPoint.localPosition + globalTransformAsOffset;
@ -580,7 +580,7 @@ class _SelectableRegionState extends State<SelectableRegion> with TextSelectionD
selectionPoint.lineHeight
);
return MagnifierOverlayInfoBearer(
return MagnifierInfo(
globalGesturePosition: globalGesturePosition,
caretRect: caretRect,
fieldBounds: globalTransformAsOffset & _selectable!.size,

View file

@ -543,7 +543,7 @@ class TextSelectionOverlay {
return endHandleRect?.height ?? renderObject.preferredLineHeight;
}
MagnifierOverlayInfoBearer _buildMagnifier({
MagnifierInfo _buildMagnifier({
required RenderEditable renderEditable,
required Offset globalGesturePosition,
required TextPosition currentTextPosition,
@ -567,7 +567,7 @@ class TextSelectionOverlay {
renderEditable.getLocalRectForCaret(positionAtEndOfLine).bottomCenter,
);
return MagnifierOverlayInfoBearer(
return MagnifierInfo(
fieldBounds: globalRenderEditableTopLeft & renderEditable.size,
globalGesturePosition: globalGesturePosition,
caretRect: localCaretRect.shift(globalRenderEditableTopLeft),
@ -808,8 +808,8 @@ class SelectionOverlay {
final BuildContext context;
final ValueNotifier<MagnifierOverlayInfoBearer> _magnifierOverlayInfoBearer =
ValueNotifier<MagnifierOverlayInfoBearer>(MagnifierOverlayInfoBearer.empty);
final ValueNotifier<MagnifierInfo> _magnifierInfo =
ValueNotifier<MagnifierInfo>(MagnifierInfo.empty);
/// [MagnifierController.show] and [MagnifierController.hide] should not be called directly, except
/// from inside [showMagnifier] and [hideMagnifier]. If it is desired to show or hide the magnifier,
@ -836,13 +836,13 @@ class SelectionOverlay {
/// since magnifiers may hide themselves. If this info is needed, check
/// [MagnifierController.shown].
/// {@endtemplate}
void showMagnifier(MagnifierOverlayInfoBearer initialInfoBearer) {
void showMagnifier(MagnifierInfo initalMagnifierInfo) {
if (_toolbar != null) {
hideToolbar();
}
// Start from empty, so we don't utilize any remnant values.
_magnifierOverlayInfoBearer.value = initialInfoBearer;
// Start from empty, so we don't utilize any rememnant values.
_magnifierInfo.value = initalMagnifierInfo;
// 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
@ -850,7 +850,7 @@ class SelectionOverlay {
final Widget? builtMagnifier = magnifierConfiguration.magnifierBuilder(
context,
_magnifierController,
_magnifierOverlayInfoBearer,
_magnifierInfo,
);
if (builtMagnifier == null) {
@ -1300,14 +1300,14 @@ class SelectionOverlay {
/// because the magnifier may have hidden itself and is looking for a cue to reshow
/// itself.
///
/// If there is no magnifier in the overlay, this does nothing,
/// If there is no magnifier in the overlay, this does nothing.
/// {@endtemplate}
void updateMagnifier(MagnifierOverlayInfoBearer magnifierOverlayInfoBearer) {
void updateMagnifier(MagnifierInfo magnifierInfo) {
if (_magnifierController.overlayEntry == null) {
return;
}
_magnifierOverlayInfoBearer.value = magnifierOverlayInfoBearer;
_magnifierInfo.value = magnifierInfo;
}
}

View file

@ -14,18 +14,18 @@ void main() {
const Rect reasonableTextField = Rect.fromLTRB(0, 100, 200, 200);
final MagnifierController magnifierController = MagnifierController();
// Make sure that your gesture in infoBearer is within the line in infoBearer,
// Make sure that your gesture in magnifierInfo is within the line in magnifierInfo,
// or else the magnifier status will stay hidden and this will not complete.
Future<void> showCupertinoMagnifier(
BuildContext context,
WidgetTester tester,
ValueNotifier<MagnifierOverlayInfoBearer> infoBearer,
ValueNotifier<MagnifierInfo> magnifierInfo,
) async {
final Future<void> magnifierShown = magnifierController.show(
context: context,
builder: (_) => CupertinoTextMagnifier(
controller: magnifierController,
magnifierOverlayInfoBearer: infoBearer,
magnifierInfo: magnifierInfo,
));
WidgetsBinding.instance.scheduleFrame();
@ -76,9 +76,9 @@ void main() {
final Rect fakeTextFieldRect =
tapPointRenderBox.localToGlobal(Offset.zero) & tapPointRenderBox.size;
final ValueNotifier<MagnifierOverlayInfoBearer> magnifier =
ValueNotifier<MagnifierOverlayInfoBearer>(
MagnifierOverlayInfoBearer(
final ValueNotifier<MagnifierInfo> magnifier =
ValueNotifier<MagnifierInfo>(
MagnifierInfo(
currentLineBoundaries: fakeTextFieldRect,
fieldBounds: fakeTextFieldRect,
caretRect: fakeTextFieldRect,
@ -110,8 +110,8 @@ void main() {
await showCupertinoMagnifier(
context,
tester,
ValueNotifier<MagnifierOverlayInfoBearer>(
MagnifierOverlayInfoBearer(
ValueNotifier<MagnifierInfo>(
MagnifierInfo(
currentLineBoundaries: reasonableTextField,
fieldBounds: reasonableTextField,
caretRect: reasonableTextField,
@ -143,8 +143,8 @@ void main() {
await showCupertinoMagnifier(
context,
tester,
ValueNotifier<MagnifierOverlayInfoBearer>(
MagnifierOverlayInfoBearer(
ValueNotifier<MagnifierInfo>(
MagnifierInfo(
currentLineBoundaries: reasonableTextField,
fieldBounds: reasonableTextField,
caretRect: reasonableTextField,
@ -176,9 +176,9 @@ void main() {
final BuildContext context =
tester.firstElement(find.byType(Placeholder));
final ValueNotifier<MagnifierOverlayInfoBearer> magnifierinfo =
ValueNotifier<MagnifierOverlayInfoBearer>(
MagnifierOverlayInfoBearer(
final ValueNotifier<MagnifierInfo> magnifierinfo =
ValueNotifier<MagnifierInfo>(
MagnifierInfo(
currentLineBoundaries: reasonableTextField,
fieldBounds: reasonableTextField,
caretRect: reasonableTextField,
@ -192,7 +192,7 @@ void main() {
await showCupertinoMagnifier(context, tester, magnifierinfo);
// Move the gesture to one that should hide it.
magnifierinfo.value = MagnifierOverlayInfoBearer(
magnifierinfo.value = MagnifierInfo(
currentLineBoundaries: reasonableTextField,
fieldBounds: reasonableTextField,
caretRect: reasonableTextField,
@ -216,9 +216,9 @@ void main() {
final BuildContext context =
tester.firstElement(find.byType(Placeholder));
final ValueNotifier<MagnifierOverlayInfoBearer> magnifierInfo =
ValueNotifier<MagnifierOverlayInfoBearer>(
MagnifierOverlayInfoBearer(
final ValueNotifier<MagnifierInfo> magnifierInfo =
ValueNotifier<MagnifierInfo>(
MagnifierInfo(
currentLineBoundaries: reasonableTextField,
fieldBounds: reasonableTextField,
caretRect: reasonableTextField,
@ -231,7 +231,7 @@ void main() {
await showCupertinoMagnifier(context, tester, magnifierInfo);
// Move the gesture to one that should hide it.
magnifierInfo.value = MagnifierOverlayInfoBearer(
magnifierInfo.value = MagnifierInfo(
currentLineBoundaries: reasonableTextField,
fieldBounds: reasonableTextField,
caretRect: reasonableTextField,
@ -243,7 +243,7 @@ void main() {
expect(magnifierController.overlayEntry, isNotNull);
// Return the gesture to one that shows it.
magnifierInfo.value = MagnifierOverlayInfoBearer(
magnifierInfo.value = MagnifierInfo(
currentLineBoundaries: reasonableTextField,
fieldBounds: reasonableTextField,
caretRect: reasonableTextField,

View file

@ -5964,7 +5964,7 @@ void main() {
});
group('magnifier', () {
late ValueNotifier<MagnifierOverlayInfoBearer> infoBearer;
late ValueNotifier<MagnifierInfo> magnifierInfo;
final Widget fakeMagnifier = Container(key: UniqueKey());
group('magnifier builder', () {
@ -5987,7 +5987,7 @@ void main() {
defaultCupertinoTextField.magnifierConfiguration!.magnifierBuilder(
context,
MagnifierController(),
ValueNotifier<MagnifierOverlayInfoBearer>(MagnifierOverlayInfoBearer.empty),
ValueNotifier<MagnifierInfo>(MagnifierInfo.empty),
),
isA<Widget>().having((Widget widget) => widget.key, 'key', equals(customMagnifier.key)));
});
@ -6005,7 +6005,7 @@ void main() {
editableText.magnifierConfiguration.magnifierBuilder(
context,
MagnifierController(),
ValueNotifier<MagnifierOverlayInfoBearer>(MagnifierOverlayInfoBearer.empty),
ValueNotifier<MagnifierInfo>(MagnifierInfo.empty),
),
isA<CupertinoTextMagnifier>());
},
@ -6025,7 +6025,7 @@ void main() {
editableText.magnifierConfiguration.magnifierBuilder(
context,
MagnifierController(),
ValueNotifier<MagnifierOverlayInfoBearer>(MagnifierOverlayInfoBearer.empty),
ValueNotifier<MagnifierInfo>(MagnifierInfo.empty),
),
isNull);
},
@ -6046,9 +6046,9 @@ void main() {
magnifierConfiguration: TextMagnifierConfiguration(
magnifierBuilder: (_,
MagnifierController controller,
ValueNotifier<MagnifierOverlayInfoBearer>
localInfoBearer) {
infoBearer = localInfoBearer;
ValueNotifier<MagnifierInfo>
localMagnifierInfo) {
magnifierInfo = localMagnifierInfo;
return fakeMagnifier;
}),
),
@ -6086,14 +6086,14 @@ void main() {
await tester.pump();
expect(find.byKey(fakeMagnifier.key!), findsOneWidget);
firstDragGesturePosition = infoBearer.value.globalGesturePosition;
firstDragGesturePosition = magnifierInfo.value.globalGesturePosition;
await gesture.moveTo(textOffsetToPosition(tester, testValue.length));
await tester.pump();
// Expect the position the magnifier gets to have moved.
expect(firstDragGesturePosition,
isNot(infoBearer.value.globalGesturePosition));
isNot(magnifierInfo.value.globalGesturePosition));
await gesture.up();
await tester.pump();
@ -6114,9 +6114,9 @@ void main() {
magnifierBuilder: (
_,
MagnifierController controller,
ValueNotifier<MagnifierOverlayInfoBearer> localInfoBearer
ValueNotifier<MagnifierInfo> localMagnifierInfo
) {
infoBearer = localInfoBearer;
magnifierInfo = localMagnifierInfo;
return fakeMagnifier;
},
),
@ -6144,7 +6144,7 @@ void main() {
expect(controller.selection.extentOffset, 5);
expect(find.byKey(fakeMagnifier.key!), findsOneWidget);
final Offset firstLongPressGesturePosition = infoBearer.value.globalGesturePosition;
final Offset firstLongPressGesturePosition = magnifierInfo.value.globalGesturePosition;
// Move the gesture to 'h' to update the magnifier and move the cursor to 'h'.
await gesture.moveTo(textOffsetToPosition(tester, testValue.indexOf('h')));
@ -6153,7 +6153,7 @@ void main() {
expect(controller.selection.extentOffset, 9);
expect(find.byKey(fakeMagnifier.key!), findsOneWidget);
// Expect the position the magnifier gets to have moved.
expect(firstLongPressGesturePosition, isNot(infoBearer.value.globalGesturePosition));
expect(firstLongPressGesturePosition, isNot(magnifierInfo.value.globalGesturePosition));
// End the long press to hide the magnifier.
await gesture.up();

View file

@ -28,12 +28,12 @@ void main() {
Future<void> showMagnifier(
BuildContext context,
WidgetTester tester,
ValueNotifier<MagnifierOverlayInfoBearer> infoBearer,
ValueNotifier<MagnifierInfo> magnifierInfo,
) async {
final Future<void> magnifierShown = magnifierController.show(
context: context,
builder: (_) => TextMagnifier(
magnifierInfo: infoBearer,
magnifierInfo: magnifierInfo,
));
WidgetsBinding.instance.scheduleFrame();
@ -60,7 +60,7 @@ void main() {
final Widget? builtWidget = TextMagnifier.adaptiveMagnifierConfiguration.magnifierBuilder(
context,
MagnifierController(),
ValueNotifier<MagnifierOverlayInfoBearer>(MagnifierOverlayInfoBearer.empty),
ValueNotifier<MagnifierInfo>(MagnifierInfo.empty),
);
expect(builtWidget, isA<TextMagnifier>());
@ -77,7 +77,7 @@ void main() {
final Widget? builtWidget = TextMagnifier.adaptiveMagnifierConfiguration.magnifierBuilder(
context,
MagnifierController(),
ValueNotifier<MagnifierOverlayInfoBearer>(MagnifierOverlayInfoBearer.empty),
ValueNotifier<MagnifierInfo>(MagnifierInfo.empty),
);
expect(builtWidget, isA<CupertinoTextMagnifier>());
@ -94,7 +94,7 @@ void main() {
final Widget? builtWidget = TextMagnifier.adaptiveMagnifierConfiguration.magnifierBuilder(
context,
MagnifierController(),
ValueNotifier<MagnifierOverlayInfoBearer>(MagnifierOverlayInfoBearer.empty),
ValueNotifier<MagnifierInfo>(MagnifierInfo.empty),
);
expect(builtWidget, isNull);
@ -144,9 +144,9 @@ void main() {
tapPointRenderBox.localToGlobal(Offset.zero) &
tapPointRenderBox.size;
final ValueNotifier<MagnifierOverlayInfoBearer> magnifierInfo =
ValueNotifier<MagnifierOverlayInfoBearer>(
MagnifierOverlayInfoBearer(
final ValueNotifier<MagnifierInfo> magnifierInfo =
ValueNotifier<MagnifierInfo>(
MagnifierInfo(
currentLineBoundaries: fakeTextFieldRect,
fieldBounds: fakeTextFieldRect,
caretRect: fakeTextFieldRect,
@ -179,8 +179,8 @@ void main() {
await showMagnifier(
context,
tester,
ValueNotifier<MagnifierOverlayInfoBearer>(
MagnifierOverlayInfoBearer(
ValueNotifier<MagnifierInfo>(
MagnifierInfo(
currentLineBoundaries: reasonableTextField,
// Inflate these two to make sure we're bounding on the
// current line boundaries, not anything else.
@ -212,8 +212,8 @@ void main() {
await showMagnifier(
context,
tester,
ValueNotifier<MagnifierOverlayInfoBearer>(
MagnifierOverlayInfoBearer(
ValueNotifier<MagnifierInfo>(
MagnifierInfo(
currentLineBoundaries: reasonableTextField,
// Inflate these two to make sure we're bounding on the
// current line boundaries, not anything else.
@ -240,8 +240,8 @@ void main() {
await showMagnifier(
context,
tester,
ValueNotifier<MagnifierOverlayInfoBearer>(
MagnifierOverlayInfoBearer(
ValueNotifier<MagnifierInfo>(
MagnifierInfo(
currentLineBoundaries: reasonableTextField,
fieldBounds: reasonableTextField,
caretRect: reasonableTextField,
@ -267,8 +267,8 @@ void main() {
await showMagnifier(
context,
tester,
ValueNotifier<MagnifierOverlayInfoBearer>(
MagnifierOverlayInfoBearer(
ValueNotifier<MagnifierInfo>(
MagnifierInfo(
currentLineBoundaries: topOfScreenTextFieldRect,
fieldBounds: topOfScreenTextFieldRect,
caretRect: topOfScreenTextFieldRect,
@ -300,8 +300,8 @@ void main() {
await showMagnifier(
context,
tester,
ValueNotifier<MagnifierOverlayInfoBearer>(
MagnifierOverlayInfoBearer(
ValueNotifier<MagnifierInfo>(
MagnifierInfo(
currentLineBoundaries: reasonableTextField,
fieldBounds: reasonableTextField,
caretRect: reasonableTextField,
@ -331,8 +331,8 @@ void main() {
await showMagnifier(
context,
tester,
ValueNotifier<MagnifierOverlayInfoBearer>(
MagnifierOverlayInfoBearer(
ValueNotifier<MagnifierInfo>(
MagnifierInfo(
currentLineBoundaries: topOfScreenTextFieldRect,
fieldBounds: topOfScreenTextFieldRect,
caretRect: topOfScreenTextFieldRect,
@ -364,8 +364,8 @@ void main() {
await showMagnifier(
context,
tester,
ValueNotifier<MagnifierOverlayInfoBearer>(
MagnifierOverlayInfoBearer(
ValueNotifier<MagnifierInfo>(
MagnifierInfo(
currentLineBoundaries: reasonableTextField,
fieldBounds: reasonableTextField,
caretRect: reasonableTextField,
@ -386,9 +386,9 @@ void main() {
final BuildContext context =
tester.firstElement(find.byType(Placeholder));
final ValueNotifier<MagnifierOverlayInfoBearer> magnifierPositioner =
ValueNotifier<MagnifierOverlayInfoBearer>(
MagnifierOverlayInfoBearer(
final ValueNotifier<MagnifierInfo> magnifierPositioner =
ValueNotifier<MagnifierInfo>(
MagnifierInfo(
currentLineBoundaries: reasonableTextField,
fieldBounds: reasonableTextField,
caretRect: reasonableTextField,
@ -399,7 +399,7 @@ void main() {
await showMagnifier(context, tester, magnifierPositioner);
// New position has a horizontal shift.
magnifierPositioner.value = MagnifierOverlayInfoBearer(
magnifierPositioner.value = MagnifierInfo(
currentLineBoundaries: reasonableTextField,
fieldBounds: reasonableTextField,
caretRect: reasonableTextField,
@ -422,9 +422,9 @@ void main() {
final BuildContext context =
tester.firstElement(find.byType(Placeholder));
final ValueNotifier<MagnifierOverlayInfoBearer> magnifierPositioner =
ValueNotifier<MagnifierOverlayInfoBearer>(
MagnifierOverlayInfoBearer(
final ValueNotifier<MagnifierInfo> magnifierPositioner =
ValueNotifier<MagnifierInfo>(
MagnifierInfo(
currentLineBoundaries: reasonableTextField,
fieldBounds: reasonableTextField,
caretRect: reasonableTextField,
@ -435,7 +435,7 @@ void main() {
await showMagnifier(context, tester, magnifierPositioner);
// New position has a vertical shift.
magnifierPositioner.value = MagnifierOverlayInfoBearer(
magnifierPositioner.value = MagnifierInfo(
currentLineBoundaries: reasonableTextField.shift(verticalShift),
fieldBounds: Rect.fromPoints(reasonableTextField.topLeft,
reasonableTextField.bottomRight + verticalShift),
@ -458,9 +458,9 @@ void main() {
final BuildContext context =
tester.firstElement(find.byType(Placeholder));
final ValueNotifier<MagnifierOverlayInfoBearer> magnifierPositioner =
ValueNotifier<MagnifierOverlayInfoBearer>(
MagnifierOverlayInfoBearer(
final ValueNotifier<MagnifierInfo> magnifierPositioner =
ValueNotifier<MagnifierInfo>(
MagnifierInfo(
currentLineBoundaries: reasonableTextField,
fieldBounds: reasonableTextField,
caretRect: reasonableTextField,
@ -471,7 +471,7 @@ void main() {
await showMagnifier(context, tester, magnifierPositioner);
// New position has a vertical shift.
magnifierPositioner.value = MagnifierOverlayInfoBearer(
magnifierPositioner.value = MagnifierInfo(
currentLineBoundaries: reasonableTextField.shift(verticalShift),
fieldBounds: Rect.fromPoints(reasonableTextField.topLeft,
reasonableTextField.bottomRight + verticalShift),

View file

@ -12032,7 +12032,7 @@ void main() {
textField.magnifierConfiguration!.magnifierBuilder(
context,
MagnifierController(),
ValueNotifier<MagnifierOverlayInfoBearer>(MagnifierOverlayInfoBearer.empty),
ValueNotifier<MagnifierInfo>(MagnifierInfo.empty),
),
isA<Widget>().having(
(Widget widget) => widget.key,
@ -12053,7 +12053,7 @@ void main() {
editableText.magnifierConfiguration.magnifierBuilder(
context,
MagnifierController(),
ValueNotifier<MagnifierOverlayInfoBearer>(MagnifierOverlayInfoBearer.empty),
ValueNotifier<MagnifierInfo>(MagnifierInfo.empty),
),
isA<TextMagnifier>());
}, variant: TargetPlatformVariant.only(TargetPlatform.android));
@ -12071,7 +12071,7 @@ void main() {
editableText.magnifierConfiguration.magnifierBuilder(
context,
MagnifierController(),
ValueNotifier<MagnifierOverlayInfoBearer>(MagnifierOverlayInfoBearer.empty),
ValueNotifier<MagnifierInfo>(MagnifierInfo.empty),
),
isA<CupertinoTextMagnifier>());
}, variant: TargetPlatformVariant.only(TargetPlatform.iOS));
@ -12089,7 +12089,7 @@ void main() {
editableText.magnifierConfiguration.magnifierBuilder(
context,
MagnifierController(),
ValueNotifier<MagnifierOverlayInfoBearer>(MagnifierOverlayInfoBearer.empty),
ValueNotifier<MagnifierInfo>(MagnifierInfo.empty),
),
isNull);
},
@ -12101,7 +12101,7 @@ void main() {
});
group('magnifier', () {
late ValueNotifier<MagnifierOverlayInfoBearer> infoBearer;
late ValueNotifier<MagnifierInfo> magnifierInfo;
final Widget fakeMagnifier = Container(key: UniqueKey());
testWidgets(
@ -12117,9 +12117,9 @@ void main() {
magnifierBuilder: (
_,
MagnifierController controller,
ValueNotifier<MagnifierOverlayInfoBearer> localInfoBearer
ValueNotifier<MagnifierInfo> localMagnifierInfo
) {
infoBearer = localInfoBearer;
magnifierInfo = localMagnifierInfo;
return fakeMagnifier;
},
),
@ -12153,14 +12153,14 @@ void main() {
await tester.pump();
expect(find.byKey(fakeMagnifier.key!), findsOneWidget);
final Offset firstDragGesturePosition = infoBearer.value.globalGesturePosition;
final Offset firstDragGesturePosition = magnifierInfo.value.globalGesturePosition;
await gesture.moveTo(textOffsetToPosition(tester, testValue.length));
await tester.pump();
// Expect the position the magnifier gets to have moved.
expect(firstDragGesturePosition,
isNot(infoBearer.value.globalGesturePosition));
isNot(magnifierInfo.value.globalGesturePosition));
await gesture.up();
await tester.pump();
@ -12182,9 +12182,9 @@ void main() {
magnifierBuilder: (
_,
MagnifierController controller,
ValueNotifier<MagnifierOverlayInfoBearer> localInfoBearer
ValueNotifier<MagnifierInfo> localMagnifierInfo
) {
infoBearer = localInfoBearer;
magnifierInfo = localMagnifierInfo;
return fakeMagnifier;
},
),
@ -12214,7 +12214,7 @@ void main() {
expect(controller.selection.extentOffset, isTargetPlatformAndroid ? 7 : 5);
expect(find.byKey(fakeMagnifier.key!), findsOneWidget);
final Offset firstLongPressGesturePosition = infoBearer.value.globalGesturePosition;
final Offset firstLongPressGesturePosition = magnifierInfo.value.globalGesturePosition;
// Move the gesture to 'h' on Android to update the magnifier and select 'ghi'.
// Move the gesture to 'h' on iOS to update the magnifier and move the cursor to 'h'.
@ -12224,7 +12224,7 @@ void main() {
expect(controller.selection.extentOffset, isTargetPlatformAndroid ? 11 : 9);
expect(find.byKey(fakeMagnifier.key!), findsOneWidget);
// Expect the position the magnifier gets to have moved.
expect(firstLongPressGesturePosition, isNot(infoBearer.value.globalGesturePosition));
expect(firstLongPressGesturePosition, isNot(magnifierInfo.value.globalGesturePosition));
// End the long press to hide the magnifier.
await gesture.up();

View file

@ -12919,7 +12919,7 @@ void main() {
editableText.magnifierConfiguration.magnifierBuilder(
context,
MagnifierController(),
ValueNotifier<MagnifierOverlayInfoBearer>(MagnifierOverlayInfoBearer.empty)
ValueNotifier<MagnifierInfo>(MagnifierInfo.empty)
),
isNull,
);

View file

@ -1101,7 +1101,7 @@ void main() {
}, skip: kIsWeb); // [intended] Web uses its native context menu.
group('magnifier', () {
late ValueNotifier<MagnifierOverlayInfoBearer> infoBearer;
late ValueNotifier<MagnifierInfo> magnifierInfo;
final Widget fakeMagnifier = Container(key: UniqueKey());
testWidgets('Can drag handles to show, unshow, and update magnifier',
@ -1114,9 +1114,9 @@ void main() {
magnifierConfiguration: TextMagnifierConfiguration(
magnifierBuilder: (_,
MagnifierController controller,
ValueNotifier<MagnifierOverlayInfoBearer>
localInfoBearer) {
infoBearer = localInfoBearer;
ValueNotifier<MagnifierInfo>
localMagnifierInfo) {
magnifierInfo = localMagnifierInfo;
return fakeMagnifier;
},
),
@ -1151,14 +1151,14 @@ void main() {
// Expect the magnifier to show and then store it's position.
expect(find.byKey(fakeMagnifier.key!), findsOneWidget);
final Offset firstDragGesturePosition =
infoBearer.value.globalGesturePosition;
magnifierInfo.value.globalGesturePosition;
await gesture.moveTo(textOffsetToPosition(paragraph, text.length));
await tester.pump();
// Expect the position the magnifier gets to have moved.
expect(firstDragGesturePosition,
isNot(infoBearer.value.globalGesturePosition));
isNot(magnifierInfo.value.globalGesturePosition));
// Lift the pointer and expect the magnifier to disappear.
await gesture.up();

View file

@ -5153,7 +5153,7 @@ void main() {
});
group('magnifier', () {
late ValueNotifier<MagnifierOverlayInfoBearer> infoBearer;
late ValueNotifier<MagnifierInfo> magnifierInfo;
final Widget fakeMagnifier = Container(key: UniqueKey());
testWidgets(
@ -5166,9 +5166,9 @@ void main() {
magnifierBuilder: (
_,
MagnifierController controller,
ValueNotifier<MagnifierOverlayInfoBearer> localInfoBearer
ValueNotifier<MagnifierInfo> localMagnifierInfo
) {
infoBearer = localInfoBearer;
magnifierInfo = localMagnifierInfo;
return fakeMagnifier;
},
)
@ -5209,14 +5209,14 @@ void main() {
await tester.pump();
expect(find.byKey(fakeMagnifier.key!), findsOneWidget);
firstDragGesturePosition = infoBearer.value.globalGesturePosition;
firstDragGesturePosition = magnifierInfo.value.globalGesturePosition;
await gesture.moveTo(textOffsetToPosition(tester, testValue.length));
await tester.pump();
// Expect the position the magnifier gets to have moved.
expect(firstDragGesturePosition,
isNot(infoBearer.value.globalGesturePosition));
isNot(magnifierInfo.value.globalGesturePosition));
await gesture.up();
await tester.pump();

View file

@ -1256,7 +1256,7 @@ void main() {
tester,
magnifierConfiguration: TextMagnifierConfiguration(
shouldDisplayHandlesInMagnifier: false,
magnifierBuilder: (BuildContext context, MagnifierController controller, ValueNotifier<MagnifierOverlayInfoBearer>? notifier) {
magnifierBuilder: (BuildContext context, MagnifierController controller, ValueNotifier<MagnifierInfo>? notifier) {
return SizedBox.shrink(
key: magnifierKey,
);
@ -1266,7 +1266,7 @@ void main() {
expect(find.byKey(magnifierKey), findsNothing);
final MagnifierOverlayInfoBearer info = MagnifierOverlayInfoBearer(
final MagnifierInfo info = MagnifierInfo(
globalGesturePosition: Offset.zero,
caretRect: Offset.zero & const Size(5.0, 20.0),
fieldBounds: Offset.zero & const Size(200.0, 50.0),