mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
SelectableText handles after Select All (#62072)
This commit is contained in:
parent
f707f6f6ea
commit
a4d570f0dd
@ -477,27 +477,44 @@ class _SelectableTextState extends State<SelectableText> with AutomaticKeepAlive
|
||||
_controller = _TextSpanEditingController(
|
||||
textSpan: widget.textSpan ?? TextSpan(text: widget.data)
|
||||
);
|
||||
_controller.addListener(_onControllerChanged);
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(SelectableText oldWidget) {
|
||||
super.didUpdateWidget(oldWidget);
|
||||
if (widget.data != oldWidget.data || widget.textSpan != oldWidget.textSpan) {
|
||||
_controller.removeListener(_onControllerChanged);
|
||||
_controller = _TextSpanEditingController(
|
||||
textSpan: widget.textSpan ?? TextSpan(text: widget.data)
|
||||
);
|
||||
_controller.addListener(_onControllerChanged);
|
||||
}
|
||||
if (_effectiveFocusNode.hasFocus && _controller.selection.isCollapsed) {
|
||||
_showSelectionHandles = false;
|
||||
} else {
|
||||
_showSelectionHandles = true;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_focusNode?.dispose();
|
||||
_controller.removeListener(_onControllerChanged);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _onControllerChanged() {
|
||||
final bool showSelectionHandles = !_effectiveFocusNode.hasFocus
|
||||
|| !_controller.selection.isCollapsed;
|
||||
if (showSelectionHandles == _showSelectionHandles) {
|
||||
return;
|
||||
}
|
||||
setState(() {
|
||||
_showSelectionHandles = showSelectionHandles;
|
||||
});
|
||||
}
|
||||
|
||||
void _handleSelectionChanged(TextSelection selection, SelectionChangedCause cause) {
|
||||
final bool willShowSelectionHandles = _shouldShowSelectionHandles(cause);
|
||||
if (willShowSelectionHandles != _showSelectionHandles) {
|
||||
|
||||
@ -440,8 +440,6 @@ class TextSelectionOverlay {
|
||||
OverlayEntry(builder: (BuildContext context) => _buildHandle(context, _TextSelectionHandlePosition.end)),
|
||||
];
|
||||
|
||||
|
||||
|
||||
Overlay.of(context, rootOverlay: true, debugRequiredFor: debugRequiredFor).insertAll(_handles);
|
||||
}
|
||||
|
||||
|
||||
@ -3894,4 +3894,77 @@ void main() {
|
||||
|
||||
expect(RendererBinding.instance.mouseTracker.debugDeviceActiveCursor(1), SystemMouseCursors.text);
|
||||
});
|
||||
|
||||
testWidgets('The handles show after pressing Select All', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
const MaterialApp(
|
||||
home: Material(
|
||||
child: SelectableText('abc def ghi'),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// Long press at 'e' in 'def'.
|
||||
final Offset ePos = textOffsetToPosition(tester, 5);
|
||||
await tester.longPressAt(ePos);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.text('Select all'), findsOneWidget);
|
||||
expect(find.text('Copy'), findsOneWidget);
|
||||
expect(find.text('Paste'), findsNothing);
|
||||
expect(find.text('Cut'), findsNothing);
|
||||
EditableTextState editableText = tester.state(find.byType(EditableText));
|
||||
expect(editableText.selectionOverlay.handlesAreVisible, isTrue);
|
||||
expect(editableText.selectionOverlay.toolbarIsVisible, isTrue);
|
||||
|
||||
await tester.tap(find.text('Select all'));
|
||||
await tester.pump();
|
||||
expect(find.text('Copy'), findsOneWidget);
|
||||
expect(find.text('Select all'), findsNothing);
|
||||
expect(find.text('Paste'), findsNothing);
|
||||
expect(find.text('Cut'), findsNothing);
|
||||
editableText = tester.state(find.byType(EditableText));
|
||||
expect(editableText.selectionOverlay.handlesAreVisible, isTrue);
|
||||
},
|
||||
variant: const TargetPlatformVariant(<TargetPlatform>{
|
||||
TargetPlatform.android,
|
||||
TargetPlatform.fuchsia,
|
||||
TargetPlatform.linux,
|
||||
TargetPlatform.windows,
|
||||
}),
|
||||
);
|
||||
|
||||
testWidgets('The handles show after pressing Select All (iOS and Mac)', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
const MaterialApp(
|
||||
home: Material(
|
||||
child: SelectableText('abc def ghi'),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// Long press at 'e' in 'def'.
|
||||
final Offset ePos = textOffsetToPosition(tester, 5);
|
||||
await tester.longPressAt(ePos);
|
||||
await tester.pumpAndSettle();
|
||||
|
||||
expect(find.text('Select All'), findsOneWidget);
|
||||
expect(find.text('Copy'), findsNothing);
|
||||
expect(find.text('Paste'), findsNothing);
|
||||
expect(find.text('Cut'), findsNothing);
|
||||
EditableTextState editableText = tester.state(find.byType(EditableText));
|
||||
expect(editableText.selectionOverlay.handlesAreVisible, isFalse);
|
||||
expect(editableText.selectionOverlay.toolbarIsVisible, isTrue);
|
||||
|
||||
await tester.tap(find.text('Select All'));
|
||||
await tester.pumpAndSettle();
|
||||
expect(find.text('Copy'), findsOneWidget);
|
||||
expect(find.text('Select All'), findsNothing);
|
||||
expect(find.text('Paste'), findsNothing);
|
||||
expect(find.text('Cut'), findsNothing);
|
||||
editableText = tester.state(find.byType(EditableText));
|
||||
expect(editableText.selectionOverlay.handlesAreVisible, isTrue);
|
||||
},
|
||||
variant: const TargetPlatformVariant(<TargetPlatform>{ TargetPlatform.iOS, TargetPlatform.macOS }),
|
||||
);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user