Add enableInteractiveSelection to CupertinoTextField and test it (#32823)
Adds a field that already exists in Material's TextField.
This commit is contained in:
parent
4aaeb4e11f
commit
95eed87640
@ -186,6 +186,7 @@ class CupertinoTextField extends StatefulWidget {
|
||||
this.keyboardAppearance,
|
||||
this.scrollPadding = const EdgeInsets.all(20.0),
|
||||
this.dragStartBehavior = DragStartBehavior.start,
|
||||
this.enableInteractiveSelection,
|
||||
this.scrollPhysics,
|
||||
}) : assert(textAlign != null),
|
||||
assert(autofocus != null),
|
||||
@ -423,12 +424,20 @@ class CupertinoTextField extends StatefulWidget {
|
||||
/// {@macro flutter.widgets.editableText.scrollPadding}
|
||||
final EdgeInsets scrollPadding;
|
||||
|
||||
/// {@macro flutter.widgets.editableText.enableInteractiveSelection}
|
||||
final bool enableInteractiveSelection;
|
||||
|
||||
/// {@macro flutter.widgets.scrollable.dragStartBehavior}
|
||||
final DragStartBehavior dragStartBehavior;
|
||||
|
||||
/// {@macro flutter.widgets.edtiableText.scrollPhysics}
|
||||
final ScrollPhysics scrollPhysics;
|
||||
|
||||
/// {@macro flutter.rendering.editable.selectionEnabled}
|
||||
bool get selectionEnabled {
|
||||
return enableInteractiveSelection ?? !obscureText;
|
||||
}
|
||||
|
||||
@override
|
||||
_CupertinoTextFieldState createState() => _CupertinoTextFieldState();
|
||||
|
||||
@ -456,6 +465,7 @@ class CupertinoTextField extends StatefulWidget {
|
||||
properties.add(IntProperty('maxLength', maxLength, defaultValue: null));
|
||||
properties.add(FlagProperty('maxLengthEnforced', value: maxLengthEnforced, ifTrue: 'max length enforced'));
|
||||
properties.add(DiagnosticsProperty<Color>('cursorColor', cursorColor, defaultValue: null));
|
||||
properties.add(FlagProperty('selectionEnabled', value: selectionEnabled, defaultValue: true, ifFalse: 'selection disabled'));
|
||||
properties.add(DiagnosticsProperty<ScrollPhysics>('scrollPhysics', scrollPhysics, defaultValue: null));
|
||||
}
|
||||
}
|
||||
@ -530,10 +540,12 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with AutomaticK
|
||||
}
|
||||
|
||||
void _handleForcePressStarted(ForcePressDetails details) {
|
||||
_renderEditable.selectWordsInRange(
|
||||
from: details.globalPosition,
|
||||
cause: SelectionChangedCause.forcePress,
|
||||
);
|
||||
if (widget.selectionEnabled) {
|
||||
_renderEditable.selectWordsInRange(
|
||||
from: details.globalPosition,
|
||||
cause: SelectionChangedCause.forcePress,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void _handleForcePressEnded(ForcePressDetails details) {
|
||||
@ -546,22 +558,28 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with AutomaticK
|
||||
}
|
||||
|
||||
void _handleSingleTapUp(TapUpDetails details) {
|
||||
_renderEditable.selectWordEdge(cause: SelectionChangedCause.tap);
|
||||
if (widget.selectionEnabled) {
|
||||
_renderEditable.selectWordEdge(cause: SelectionChangedCause.tap);
|
||||
}
|
||||
_requestKeyboard();
|
||||
}
|
||||
|
||||
void _handleSingleLongTapStart(LongPressStartDetails details) {
|
||||
_renderEditable.selectPositionAt(
|
||||
from: details.globalPosition,
|
||||
cause: SelectionChangedCause.longPress,
|
||||
);
|
||||
if (widget.selectionEnabled) {
|
||||
_renderEditable.selectPositionAt(
|
||||
from: details.globalPosition,
|
||||
cause: SelectionChangedCause.longPress,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void _handleSingleLongTapMoveUpdate(LongPressMoveUpdateDetails details) {
|
||||
_renderEditable.selectPositionAt(
|
||||
from: details.globalPosition,
|
||||
cause: SelectionChangedCause.longPress,
|
||||
);
|
||||
if (widget.selectionEnabled) {
|
||||
_renderEditable.selectPositionAt(
|
||||
from: details.globalPosition,
|
||||
cause: SelectionChangedCause.longPress,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void _handleSingleLongTapEnd(LongPressEndDetails details) {
|
||||
@ -570,9 +588,11 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with AutomaticK
|
||||
}
|
||||
|
||||
void _handleDoubleTapDown(TapDownDetails details) {
|
||||
_renderEditable.selectWord(cause: SelectionChangedCause.tap);
|
||||
if (_shouldShowSelectionToolbar)
|
||||
_editableText.showToolbar();
|
||||
if (widget.selectionEnabled) {
|
||||
_renderEditable.selectWord(cause: SelectionChangedCause.tap);
|
||||
if (_shouldShowSelectionToolbar)
|
||||
_editableText.showToolbar();
|
||||
}
|
||||
}
|
||||
|
||||
bool _shouldShowSelectionHandles(SelectionChangedCause cause) {
|
||||
@ -782,7 +802,8 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with AutomaticK
|
||||
minLines: widget.minLines,
|
||||
expands: widget.expands,
|
||||
selectionColor: _kSelectionHighlightColor,
|
||||
selectionControls: cupertinoTextSelectionControls,
|
||||
selectionControls: widget.selectionEnabled
|
||||
? cupertinoTextSelectionControls : null,
|
||||
onChanged: widget.onChanged,
|
||||
onSelectionChanged: _handleSelectionChanged,
|
||||
onEditingComplete: widget.onEditingComplete,
|
||||
@ -800,6 +821,7 @@ class _CupertinoTextFieldState extends State<CupertinoTextField> with AutomaticK
|
||||
keyboardAppearance: keyboardAppearance,
|
||||
dragStartBehavior: widget.dragStartBehavior,
|
||||
scrollPhysics: widget.scrollPhysics,
|
||||
enableInteractiveSelection: widget.enableInteractiveSelection,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@ -1399,6 +1399,102 @@ void main() {
|
||||
},
|
||||
);
|
||||
|
||||
testWidgets(
|
||||
'An obscured CupertinoTextField is not selectable by default',
|
||||
(WidgetTester tester) async {
|
||||
final TextEditingController controller = TextEditingController(
|
||||
text: 'Atwater Peel Sherbrooke Bonaventure',
|
||||
);
|
||||
await tester.pumpWidget(
|
||||
CupertinoApp(
|
||||
home: Center(
|
||||
child: CupertinoTextField(
|
||||
controller: controller,
|
||||
obscureText: true,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
final Offset textfieldStart = tester.getTopLeft(find.byType(CupertinoTextField));
|
||||
|
||||
await tester.tapAt(textfieldStart + const Offset(150.0, 5.0));
|
||||
await tester.pump(const Duration(milliseconds: 50));
|
||||
final TestGesture gesture =
|
||||
await tester.startGesture(textfieldStart + const Offset(150.0, 5.0));
|
||||
// Hold the press.
|
||||
await tester.pump(const Duration(milliseconds: 500));
|
||||
|
||||
// Nothing is selected despite the double tap long press gesture.
|
||||
expect(
|
||||
controller.selection,
|
||||
const TextSelection(baseOffset: 35, extentOffset: 35),
|
||||
);
|
||||
|
||||
// The selection menu is not present.
|
||||
expect(find.byType(CupertinoButton), findsNWidgets(0));
|
||||
|
||||
await gesture.up();
|
||||
await tester.pump();
|
||||
|
||||
// Still nothing selected and no selection menu.
|
||||
expect(
|
||||
controller.selection,
|
||||
const TextSelection(baseOffset: 35, extentOffset: 35),
|
||||
);
|
||||
expect(find.byType(CupertinoButton), findsNWidgets(0));
|
||||
},
|
||||
);
|
||||
|
||||
testWidgets(
|
||||
'An obscured CupertinoTextField is selectable when enabled',
|
||||
(WidgetTester tester) async {
|
||||
final TextEditingController controller = TextEditingController(
|
||||
text: 'Atwater Peel Sherbrooke Bonaventure',
|
||||
);
|
||||
await tester.pumpWidget(
|
||||
CupertinoApp(
|
||||
home: Center(
|
||||
child: CupertinoTextField(
|
||||
controller: controller,
|
||||
obscureText: true,
|
||||
enableInteractiveSelection: true,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
final Offset textfieldStart = tester.getTopLeft(find.byType(CupertinoTextField));
|
||||
|
||||
await tester.tapAt(textfieldStart + const Offset(150.0, 5.0));
|
||||
await tester.pump(const Duration(milliseconds: 50));
|
||||
final TestGesture gesture =
|
||||
await tester.startGesture(textfieldStart + const Offset(150.0, 5.0));
|
||||
// Hold the press.
|
||||
await tester.pump(const Duration(milliseconds: 500));
|
||||
|
||||
// The obscured text is not broken into words, so only one letter is
|
||||
// selected at a time.
|
||||
expect(
|
||||
controller.selection,
|
||||
const TextSelection(baseOffset: 9, extentOffset: 10),
|
||||
);
|
||||
|
||||
// Selected text shows 3 toolbar buttons.
|
||||
expect(find.byType(CupertinoButton), findsNWidgets(3));
|
||||
|
||||
await gesture.up();
|
||||
await tester.pump();
|
||||
|
||||
// Still selected.
|
||||
expect(
|
||||
controller.selection,
|
||||
const TextSelection(baseOffset: 9, extentOffset: 10),
|
||||
);
|
||||
expect(find.byType(CupertinoButton), findsNWidgets(3));
|
||||
},
|
||||
);
|
||||
|
||||
testWidgets(
|
||||
'long press moves cursor to the exact long press position and shows toolbar',
|
||||
(WidgetTester tester) async {
|
||||
|
Loading…
x
Reference in New Issue
Block a user