Unverified Commit d522179b authored by chunhtai's avatar chunhtai Committed by GitHub

Unify Text selection API (#98073)

* Unify Text selection API

* fix test

* further simplify

* fix more tests

* styling change
parent ec588352
...@@ -67,13 +67,13 @@ class _CupertinoDesktopTextSelectionControls extends TextSelectionControls { ...@@ -67,13 +67,13 @@ class _CupertinoDesktopTextSelectionControls extends TextSelectionControls {
/// Builds the text selection handles, but desktop has none. /// Builds the text selection handles, but desktop has none.
@override @override
Widget buildHandle(BuildContext context, TextSelectionHandleType type, double textLineHeight, [VoidCallback? onTap, double? startGlyphHeight, double? endGlyphHeight]) { Widget buildHandle(BuildContext context, TextSelectionHandleType type, double textLineHeight, [VoidCallback? onTap]) {
return const SizedBox.shrink(); return const SizedBox.shrink();
} }
/// Gets the position for the text selection handles, but desktop has none. /// Gets the position for the text selection handles, but desktop has none.
@override @override
Offset getHandleAnchor(TextSelectionHandleType type, double textLineHeight, [double? startGlyphHeight, double? endGlyphHeight]) { Offset getHandleAnchor(TextSelectionHandleType type, double textLineHeight) {
return Offset.zero; return Offset.zero;
} }
} }
......
...@@ -247,14 +247,8 @@ class CupertinoTextSelectionControls extends TextSelectionControls { ...@@ -247,14 +247,8 @@ class CupertinoTextSelectionControls extends TextSelectionControls {
/// Builder for iOS text selection edges. /// Builder for iOS text selection edges.
@override @override
Widget buildHandle(BuildContext context, TextSelectionHandleType type, double textLineHeight, [VoidCallback? onTap, double? startGlyphHeight, double? endGlyphHeight]) { Widget buildHandle(BuildContext context, TextSelectionHandleType type, double textLineHeight, [VoidCallback? onTap]) {
// iOS selection handles do not respond to taps. // iOS selection handles do not respond to taps.
// We want a size that's a vertical line the height of the text plus a 18.0
// padding in every direction that will constitute the selection drag area.
startGlyphHeight = startGlyphHeight ?? textLineHeight;
endGlyphHeight = endGlyphHeight ?? textLineHeight;
final Size desiredSize; final Size desiredSize;
final Widget handle; final Widget handle;
...@@ -267,14 +261,14 @@ class CupertinoTextSelectionControls extends TextSelectionControls { ...@@ -267,14 +261,14 @@ class CupertinoTextSelectionControls extends TextSelectionControls {
// on top of the text selection endpoints. // on top of the text selection endpoints.
switch (type) { switch (type) {
case TextSelectionHandleType.left: case TextSelectionHandleType.left:
desiredSize = getHandleSize(startGlyphHeight); desiredSize = getHandleSize(textLineHeight);
handle = SizedBox.fromSize( handle = SizedBox.fromSize(
size: desiredSize, size: desiredSize,
child: customPaint, child: customPaint,
); );
return handle; return handle;
case TextSelectionHandleType.right: case TextSelectionHandleType.right:
desiredSize = getHandleSize(endGlyphHeight); desiredSize = getHandleSize(textLineHeight);
handle = SizedBox.fromSize( handle = SizedBox.fromSize(
size: desiredSize, size: desiredSize,
child: customPaint, child: customPaint,
...@@ -296,17 +290,14 @@ class CupertinoTextSelectionControls extends TextSelectionControls { ...@@ -296,17 +290,14 @@ class CupertinoTextSelectionControls extends TextSelectionControls {
/// ///
/// See [TextSelectionControls.getHandleAnchor]. /// See [TextSelectionControls.getHandleAnchor].
@override @override
Offset getHandleAnchor(TextSelectionHandleType type, double textLineHeight, [double? startGlyphHeight, double? endGlyphHeight]) { Offset getHandleAnchor(TextSelectionHandleType type, double textLineHeight) {
startGlyphHeight = startGlyphHeight ?? textLineHeight;
endGlyphHeight = endGlyphHeight ?? textLineHeight;
final Size handleSize; final Size handleSize;
switch (type) { switch (type) {
// The circle is at the top for the left handle, and the anchor point is // The circle is at the top for the left handle, and the anchor point is
// all the way at the bottom of the line. // all the way at the bottom of the line.
case TextSelectionHandleType.left: case TextSelectionHandleType.left:
handleSize = getHandleSize(startGlyphHeight); handleSize = getHandleSize(textLineHeight);
return Offset( return Offset(
handleSize.width / 2, handleSize.width / 2,
handleSize.height, handleSize.height,
...@@ -314,7 +305,7 @@ class CupertinoTextSelectionControls extends TextSelectionControls { ...@@ -314,7 +305,7 @@ class CupertinoTextSelectionControls extends TextSelectionControls {
// The right handle is vertically flipped, and the anchor point is near // The right handle is vertically flipped, and the anchor point is near
// the top of the circle to give slight overlap. // the top of the circle to give slight overlap.
case TextSelectionHandleType.right: case TextSelectionHandleType.right:
handleSize = getHandleSize(endGlyphHeight); handleSize = getHandleSize(textLineHeight);
return Offset( return Offset(
handleSize.width / 2, handleSize.width / 2,
handleSize.height - 2 * _kSelectionHandleRadius + _kSelectionHandleOverlap, handleSize.height - 2 * _kSelectionHandleRadius + _kSelectionHandleOverlap,
......
...@@ -53,13 +53,13 @@ class _DesktopTextSelectionControls extends TextSelectionControls { ...@@ -53,13 +53,13 @@ class _DesktopTextSelectionControls extends TextSelectionControls {
/// Builds the text selection handles, but desktop has none. /// Builds the text selection handles, but desktop has none.
@override @override
Widget buildHandle(BuildContext context, TextSelectionHandleType type, double textLineHeight, [VoidCallback? onTap, double? startGlyphHeight, double? endGlyphHeight]) { Widget buildHandle(BuildContext context, TextSelectionHandleType type, double textLineHeight, [VoidCallback? onTap]) {
return const SizedBox.shrink(); return const SizedBox.shrink();
} }
/// Gets the position for the text selection handles, but desktop has none. /// Gets the position for the text selection handles, but desktop has none.
@override @override
Offset getHandleAnchor(TextSelectionHandleType type, double textLineHeight, [double? startGlyphHeight, double? endGlyphHeight]) { Offset getHandleAnchor(TextSelectionHandleType type, double textLineHeight) {
return Offset.zero; return Offset.zero;
} }
......
...@@ -54,7 +54,7 @@ class MaterialTextSelectionControls extends TextSelectionControls { ...@@ -54,7 +54,7 @@ class MaterialTextSelectionControls extends TextSelectionControls {
/// Builder for material-style text selection handles. /// Builder for material-style text selection handles.
@override @override
Widget buildHandle(BuildContext context, TextSelectionHandleType type, double textHeight, [VoidCallback? onTap, double? startGlyphHeight, double? endGlyphHeight]) { Widget buildHandle(BuildContext context, TextSelectionHandleType type, double textHeight, [VoidCallback? onTap]) {
final ThemeData theme = Theme.of(context); final ThemeData theme = Theme.of(context);
final Color handleColor = TextSelectionTheme.of(context).selectionHandleColor ?? theme.colorScheme.primary; final Color handleColor = TextSelectionTheme.of(context).selectionHandleColor ?? theme.colorScheme.primary;
final Widget handle = SizedBox( final Widget handle = SizedBox(
...@@ -94,7 +94,7 @@ class MaterialTextSelectionControls extends TextSelectionControls { ...@@ -94,7 +94,7 @@ class MaterialTextSelectionControls extends TextSelectionControls {
/// ///
/// See [TextSelectionControls.getHandleAnchor]. /// See [TextSelectionControls.getHandleAnchor].
@override @override
Offset getHandleAnchor(TextSelectionHandleType type, double textLineHeight, [double? startGlyphHeight, double? endGlyphHeight]) { Offset getHandleAnchor(TextSelectionHandleType type, double textLineHeight) {
switch (type) { switch (type) {
case TextSelectionHandleType.left: case TextSelectionHandleType.left:
return const Offset(_kHandleSize, 0); return const Offset(_kHandleSize, 0);
......
...@@ -22,7 +22,6 @@ import 'gesture_detector.dart'; ...@@ -22,7 +22,6 @@ import 'gesture_detector.dart';
import 'overlay.dart'; import 'overlay.dart';
import 'ticker_provider.dart'; import 'ticker_provider.dart';
import 'transitions.dart'; import 'transitions.dart';
import 'visibility.dart';
export 'package:flutter/services.dart' show TextSelectionDelegate; export 'package:flutter/services.dart' show TextSelectionDelegate;
...@@ -116,12 +115,12 @@ abstract class TextSelectionControls { ...@@ -116,12 +115,12 @@ abstract class TextSelectionControls {
/// interaction is allowed. As a counterexample, the default selection handle /// interaction is allowed. As a counterexample, the default selection handle
/// on iOS [cupertinoTextSelectionControls] does not call [onTap] at all, /// on iOS [cupertinoTextSelectionControls] does not call [onTap] at all,
/// since its handles are not meant to be tapped. /// since its handles are not meant to be tapped.
Widget buildHandle(BuildContext context, TextSelectionHandleType type, double textLineHeight, [VoidCallback? onTap, double? startGlyphHeight, double? endGlyphHeight]); Widget buildHandle(BuildContext context, TextSelectionHandleType type, double textLineHeight, [VoidCallback? onTap]);
/// Get the anchor point of the handle relative to itself. The anchor point is /// Get the anchor point of the handle relative to itself. The anchor point is
/// the point that is aligned with a specific point in the text. A handle /// the point that is aligned with a specific point in the text. A handle
/// often visually "points to" that location. /// often visually "points to" that location.
Offset getHandleAnchor(TextSelectionHandleType type, double textLineHeight, [double? startGlyphHeight, double? endGlyphHeight]); Offset getHandleAnchor(TextSelectionHandleType type, double textLineHeight);
/// Builds a toolbar near a text selection. /// Builds a toolbar near a text selection.
/// ///
...@@ -274,6 +273,9 @@ class TextSelectionOverlay { ...@@ -274,6 +273,9 @@ class TextSelectionOverlay {
'Usually the Navigator created by WidgetsApp provides the overlay. Perhaps your ' 'Usually the Navigator created by WidgetsApp provides the overlay. Perhaps your '
'app content was created above the Navigator with the WidgetsApp builder parameter.', 'app content was created above the Navigator with the WidgetsApp builder parameter.',
); );
renderObject.selectionStartInViewport.addListener(_updateHandleVisibilities);
renderObject.selectionEndInViewport.addListener(_updateHandleVisibilities);
_updateHandleVisibilities();
_toolbarController = AnimationController(duration: fadeDuration, vsync: overlay!); _toolbarController = AnimationController(duration: fadeDuration, vsync: overlay!);
} }
...@@ -372,6 +374,13 @@ class TextSelectionOverlay { ...@@ -372,6 +374,13 @@ class TextSelectionOverlay {
TextSelection get _selection => _value.selection; TextSelection get _selection => _value.selection;
final ValueNotifier<bool> _effectiveStartHandleVisibility = ValueNotifier<bool>(false);
final ValueNotifier<bool> _effectiveEndHandleVisibility = ValueNotifier<bool>(false);
void _updateHandleVisibilities() {
_effectiveStartHandleVisibility.value = _handlesVisible && renderObject.selectionStartInViewport.value;
_effectiveEndHandleVisibility.value = _handlesVisible && renderObject.selectionEndInViewport.value;
}
/// Whether selection handles are visible. /// Whether selection handles are visible.
/// ///
/// Set to false if you want to hide the handles. Use this property to show or /// Set to false if you want to hide the handles. Use this property to show or
...@@ -393,13 +402,7 @@ class TextSelectionOverlay { ...@@ -393,13 +402,7 @@ class TextSelectionOverlay {
if (_handlesVisible == visible) if (_handlesVisible == visible)
return; return;
_handlesVisible = visible; _handlesVisible = visible;
// If we are in build state, it will be too late to update visibility. _updateHandleVisibilities();
// We will need to schedule the build in next frame.
if (SchedulerBinding.instance.schedulerPhase == SchedulerPhase.persistentCallbacks) {
SchedulerBinding.instance.addPostFrameCallback(_markNeedsBuild);
} else {
_markNeedsBuild();
}
} }
/// Builds the handles by inserting them into the [context]'s overlay. /// Builds the handles by inserting them into the [context]'s overlay.
...@@ -501,6 +504,8 @@ class TextSelectionOverlay { ...@@ -501,6 +504,8 @@ class TextSelectionOverlay {
void dispose() { void dispose() {
hide(); hide();
_toolbarController.dispose(); _toolbarController.dispose();
renderObject.selectionStartInViewport.removeListener(_updateHandleVisibilities);
renderObject.selectionEndInViewport.removeListener(_updateHandleVisibilities);
} }
Widget _buildStartHandle(BuildContext context) { Widget _buildStartHandle(BuildContext context) {
...@@ -509,9 +514,7 @@ class TextSelectionOverlay { ...@@ -509,9 +514,7 @@ class TextSelectionOverlay {
if (selectionControls == null) if (selectionControls == null)
handle = Container(); handle = Container();
else { else {
handle = Visibility( handle = _SelectionHandleOverlay(
visible: handlesVisible,
child: _SelectionHandleOverlay(
type: _chooseType( type: _chooseType(
renderObject.textDirection, renderObject.textDirection,
TextSelectionHandleType.left, TextSelectionHandleType.left,
...@@ -522,11 +525,9 @@ class TextSelectionOverlay { ...@@ -522,11 +525,9 @@ class TextSelectionOverlay {
onSelectionHandleDragStart: _handleSelectionStartHandleDragStart, onSelectionHandleDragStart: _handleSelectionStartHandleDragStart,
onSelectionHandleDragUpdate: _handleSelectionStartHandleDragUpdate, onSelectionHandleDragUpdate: _handleSelectionStartHandleDragUpdate,
selectionControls: selectionControls, selectionControls: selectionControls,
visibility: renderObject.selectionStartInViewport, visibility: _effectiveStartHandleVisibility,
preferredLineHeight: renderObject.preferredLineHeight, preferredLineHeight: _getStartGlyphHeight(),
glyphHeight: _getStartGlyphHeight(),
dragStartBehavior: dragStartBehavior, dragStartBehavior: dragStartBehavior,
)
); );
} }
return ExcludeSemantics( return ExcludeSemantics(
...@@ -540,9 +541,7 @@ class TextSelectionOverlay { ...@@ -540,9 +541,7 @@ class TextSelectionOverlay {
if (_selection.isCollapsed || selectionControls == null) if (_selection.isCollapsed || selectionControls == null)
handle = Container(); // hide the second handle when collapsed handle = Container(); // hide the second handle when collapsed
else { else {
handle = Visibility( handle = _SelectionHandleOverlay(
visible: handlesVisible,
child: _SelectionHandleOverlay(
type: _chooseType( type: _chooseType(
renderObject.textDirection, renderObject.textDirection,
TextSelectionHandleType.right, TextSelectionHandleType.right,
...@@ -553,11 +552,9 @@ class TextSelectionOverlay { ...@@ -553,11 +552,9 @@ class TextSelectionOverlay {
onSelectionHandleDragStart: _handleSelectionEndHandleDragStart, onSelectionHandleDragStart: _handleSelectionEndHandleDragStart,
onSelectionHandleDragUpdate: _handleSelectionEndHandleDragUpdate, onSelectionHandleDragUpdate: _handleSelectionEndHandleDragUpdate,
selectionControls: selectionControls, selectionControls: selectionControls,
visibility: renderObject.selectionEndInViewport, visibility: _effectiveEndHandleVisibility,
preferredLineHeight: renderObject.preferredLineHeight, preferredLineHeight: _getEndGlyphHeight(),
glyphHeight: _getEndGlyphHeight(),
dragStartBehavior: dragStartBehavior, dragStartBehavior: dragStartBehavior,
)
); );
} }
return ExcludeSemantics( return ExcludeSemantics(
...@@ -565,7 +562,7 @@ class TextSelectionOverlay { ...@@ -565,7 +562,7 @@ class TextSelectionOverlay {
); );
} }
double? _getStartGlyphHeight() { double _getStartGlyphHeight() {
final InlineSpan span = renderObject.text!; final InlineSpan span = renderObject.text!;
final String prevText = span.toPlainText(); final String prevText = span.toPlainText();
final String currText = selectionDelegate.textEditingValue.text; final String currText = selectionDelegate.textEditingValue.text;
...@@ -583,10 +580,10 @@ class TextSelectionOverlay { ...@@ -583,10 +580,10 @@ class TextSelectionOverlay {
firstSelectedGraphemeExtent = selectedGraphemes.characters.first.length; firstSelectedGraphemeExtent = selectedGraphemes.characters.first.length;
startHandleRect = renderObject.getRectForComposingRange(TextRange(start: _selection.start, end: _selection.start + firstSelectedGraphemeExtent)); startHandleRect = renderObject.getRectForComposingRange(TextRange(start: _selection.start, end: _selection.start + firstSelectedGraphemeExtent));
} }
return startHandleRect?.height; return startHandleRect?.height ?? renderObject.preferredLineHeight;
} }
double? _getEndGlyphHeight() { double _getEndGlyphHeight() {
final InlineSpan span = renderObject.text!; final InlineSpan span = renderObject.text!;
final String prevText = span.toPlainText(); final String prevText = span.toPlainText();
final String currText = selectionDelegate.textEditingValue.text; final String currText = selectionDelegate.textEditingValue.text;
...@@ -598,7 +595,7 @@ class TextSelectionOverlay { ...@@ -598,7 +595,7 @@ class TextSelectionOverlay {
lastSelectedGraphemeExtent = selectedGraphemes.characters.last.length; lastSelectedGraphemeExtent = selectedGraphemes.characters.last.length;
endHandleRect = renderObject.getRectForComposingRange(TextRange(start: _selection.end - lastSelectedGraphemeExtent, end: _selection.end)); endHandleRect = renderObject.getRectForComposingRange(TextRange(start: _selection.end - lastSelectedGraphemeExtent, end: _selection.end));
} }
return endHandleRect?.height; return endHandleRect?.height ?? renderObject.preferredLineHeight;
} }
late Offset _dragEndPosition; late Offset _dragEndPosition;
...@@ -754,7 +751,6 @@ class _SelectionHandleOverlay extends StatefulWidget { ...@@ -754,7 +751,6 @@ class _SelectionHandleOverlay extends StatefulWidget {
required this.selectionControls, required this.selectionControls,
required this.visibility, required this.visibility,
required this.preferredLineHeight, required this.preferredLineHeight,
this.glyphHeight,
this.dragStartBehavior = DragStartBehavior.start, this.dragStartBehavior = DragStartBehavior.start,
}) : super(key: key); }) : super(key: key);
...@@ -765,7 +761,6 @@ class _SelectionHandleOverlay extends StatefulWidget { ...@@ -765,7 +761,6 @@ class _SelectionHandleOverlay extends StatefulWidget {
final TextSelectionControls selectionControls; final TextSelectionControls selectionControls;
final ValueListenable<bool> visibility; final ValueListenable<bool> visibility;
final double preferredLineHeight; final double preferredLineHeight;
final double? glyphHeight;
final TextSelectionHandleType type; final TextSelectionHandleType type;
final DragStartBehavior dragStartBehavior; final DragStartBehavior dragStartBehavior;
...@@ -817,8 +812,6 @@ class _SelectionHandleOverlayState extends State<_SelectionHandleOverlay> with S ...@@ -817,8 +812,6 @@ class _SelectionHandleOverlayState extends State<_SelectionHandleOverlay> with S
final Offset handleAnchor = widget.selectionControls.getHandleAnchor( final Offset handleAnchor = widget.selectionControls.getHandleAnchor(
widget.type, widget.type,
widget.preferredLineHeight, widget.preferredLineHeight,
widget.glyphHeight,
widget.glyphHeight,
); );
final Size handleSize = widget.selectionControls.getHandleSize( final Size handleSize = widget.selectionControls.getHandleSize(
widget.preferredLineHeight, widget.preferredLineHeight,
...@@ -869,8 +862,6 @@ class _SelectionHandleOverlayState extends State<_SelectionHandleOverlay> with S ...@@ -869,8 +862,6 @@ class _SelectionHandleOverlayState extends State<_SelectionHandleOverlay> with S
widget.type, widget.type,
widget.preferredLineHeight, widget.preferredLineHeight,
widget.onSelectionHandleTapped, widget.onSelectionHandleTapped,
widget.glyphHeight,
widget.glyphHeight,
), ),
), ),
), ),
......
...@@ -31,7 +31,7 @@ const bool isContextMenuProvidedByPlatform = isBrowser; ...@@ -31,7 +31,7 @@ const bool isContextMenuProvidedByPlatform = isBrowser;
class MockTextSelectionControls extends TextSelectionControls { class MockTextSelectionControls extends TextSelectionControls {
@override @override
Widget buildHandle(BuildContext context, TextSelectionHandleType type, double textLineHeight, [VoidCallback? onTap, double? startGlyphHeight, double? endGlyphHeight]) { Widget buildHandle(BuildContext context, TextSelectionHandleType type, double textLineHeight, [VoidCallback? onTap]) {
throw UnimplementedError(); throw UnimplementedError();
} }
...@@ -50,7 +50,7 @@ class MockTextSelectionControls extends TextSelectionControls { ...@@ -50,7 +50,7 @@ class MockTextSelectionControls extends TextSelectionControls {
} }
@override @override
Offset getHandleAnchor(TextSelectionHandleType type, double textLineHeight, [double? startGlyphHeight, double? endGlyphHeight]) { Offset getHandleAnchor(TextSelectionHandleType type, double textLineHeight) {
throw UnimplementedError(); throw UnimplementedError();
} }
......
...@@ -1370,14 +1370,15 @@ void main() { ...@@ -1370,14 +1370,15 @@ void main() {
// Handle not shown. // Handle not shown.
expect(controller.selection.isCollapsed, true); expect(controller.selection.isCollapsed, true);
final Finder fadeFinder = find.byType(FadeTransition); final Finder fadeFinder = find.byType(FadeTransition);
expect(fadeFinder, findsNothing); FadeTransition handle = tester.widget(fadeFinder.at(0));
expect(handle.opacity.value, equals(0.0));
// Tap on the text field to show the handle. // Tap on the text field to show the handle.
await tester.tap(find.byType(TextField)); await tester.tap(find.byType(TextField));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect(controller.selection.isCollapsed, true); expect(controller.selection.isCollapsed, true);
expect(fadeFinder, findsNWidgets(1)); expect(fadeFinder, findsNWidgets(1));
final FadeTransition handle = tester.widget(fadeFinder.at(0)); handle = tester.widget(fadeFinder.at(0));
expect(handle.opacity.value, equals(1.0)); expect(handle.opacity.value, equals(1.0));
// Enter more text. // Enter more text.
...@@ -1388,7 +1389,8 @@ void main() { ...@@ -1388,7 +1389,8 @@ void main() {
// Handle not shown. // Handle not shown.
expect(controller.selection.isCollapsed, true); expect(controller.selection.isCollapsed, true);
expect(fadeFinder, findsNothing); handle = tester.widget(fadeFinder.at(0));
expect(handle.opacity.value, equals(0.0));
}); });
testWidgets('selection handles are excluded from the semantics', (WidgetTester tester) async { testWidgets('selection handles are excluded from the semantics', (WidgetTester tester) async {
......
...@@ -10463,7 +10463,7 @@ class MockTextSelectionControls extends Fake implements TextSelectionControls { ...@@ -10463,7 +10463,7 @@ class MockTextSelectionControls extends Fake implements TextSelectionControls {
} }
@override @override
Widget buildHandle(BuildContext context, TextSelectionHandleType type, double textLineHeight, [VoidCallback? onTap, double? startGlyphHeight, double? endGlyphHeight]) { Widget buildHandle(BuildContext context, TextSelectionHandleType type, double textLineHeight, [VoidCallback? onTap]) {
return Container(); return Container();
} }
...@@ -10473,7 +10473,7 @@ class MockTextSelectionControls extends Fake implements TextSelectionControls { ...@@ -10473,7 +10473,7 @@ class MockTextSelectionControls extends Fake implements TextSelectionControls {
} }
@override @override
Offset getHandleAnchor(TextSelectionHandleType type, double textLineHeight, [double? startGlyphHeight, double? endGlyphHeight]) { Offset getHandleAnchor(TextSelectionHandleType type, double textLineHeight) {
return Offset.zero; return Offset.zero;
} }
......
...@@ -707,7 +707,7 @@ void main() { ...@@ -707,7 +707,7 @@ void main() {
await tester.pumpAndSettle(); await tester.pumpAndSettle();
final Finder gestureDetector = find.descendant( final Finder gestureDetector = find.descendant(
of: find.byType(Visibility), of: find.byType(CompositedTransformFollower),
matching: find.descendant( matching: find.descendant(
of: find.byType(FadeTransition), of: find.byType(FadeTransition),
matching: find.byType(GestureDetector), matching: find.byType(GestureDetector),
...@@ -910,7 +910,7 @@ class FakeRenderEditable extends RenderEditable { ...@@ -910,7 +910,7 @@ class FakeRenderEditable extends RenderEditable {
class CustomTextSelectionControls extends TextSelectionControls { class CustomTextSelectionControls extends TextSelectionControls {
@override @override
Widget buildHandle(BuildContext context, TextSelectionHandleType type, double textLineHeight, [VoidCallback? onTap, double? startGlyphHeight, double? endGlyphHeight]) { Widget buildHandle(BuildContext context, TextSelectionHandleType type, double textLineHeight, [VoidCallback? onTap]) {
throw UnimplementedError(); throw UnimplementedError();
} }
...@@ -929,7 +929,7 @@ class CustomTextSelectionControls extends TextSelectionControls { ...@@ -929,7 +929,7 @@ class CustomTextSelectionControls extends TextSelectionControls {
} }
@override @override
Offset getHandleAnchor(TextSelectionHandleType type, double textLineHeight, [double? startGlyphHeight, double? endGlyphHeight]) { Offset getHandleAnchor(TextSelectionHandleType type, double textLineHeight) {
throw UnimplementedError(); throw UnimplementedError();
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment