@@ -221,6 +221,54 @@ class TextEditingController extends ValueNotifier<TextEditingValue> {
221221 }
222222}
223223
224+ /// Toolbar configuration for [EditableText] .
225+ ///
226+ /// Toolbar is a context menu that will show up when user right click or long
227+ /// press the [EditableText] . It includes several options: cut, copy, paste,
228+ /// and select all.
229+ ///
230+ /// [EditableText] and its derived widgets have their own default [ToolbarOptions] .
231+ /// Create a custom [ToolbarOptions] if you want explicit control over the toolbar
232+ /// option.
233+ class ToolbarOptions {
234+ /// Create a toolbar configuration with given options.
235+ ///
236+ /// All options default to false if they are not explicitly set.
237+ const ToolbarOptions ({
238+ this .copy = false ,
239+ this .cut = false ,
240+ this .paste = false ,
241+ this .selectAll = false ,
242+ }) : assert (copy != null ),
243+ assert (cut != null ),
244+ assert (paste != null ),
245+ assert (selectAll != null );
246+
247+ /// Whether to show copy option in toolbar.
248+ ///
249+ /// Defaults to false. Must not be null.
250+ final bool copy;
251+
252+ /// Whether to show cut option in toolbar.
253+ ///
254+ /// If [EditableText.readOnly] is set to true, cut will be disabled regardless.
255+ ///
256+ /// Defaults to false. Must not be null.
257+ final bool cut;
258+
259+ /// Whether to show paste option in toolbar.
260+ ///
261+ /// If [EditableText.readOnly] is set to true, paste will be disabled regardless.
262+ ///
263+ /// Defaults to false. Must not be null.
264+ final bool paste;
265+
266+ /// Whether to show select all option in toolbar.
267+ ///
268+ /// Defaults to false. Must not be null.
269+ final bool selectAll;
270+ }
271+
224272/// A basic text input field.
225273///
226274/// This widget interacts with the [TextInput] service to let the user edit the
@@ -336,14 +384,21 @@ class EditableText extends StatefulWidget {
336384 this .scrollPadding = const EdgeInsets .all (20.0 ),
337385 this .keyboardAppearance = Brightness .light,
338386 this .dragStartBehavior = DragStartBehavior .start,
339- this .enableInteractiveSelection,
387+ this .enableInteractiveSelection = true ,
340388 this .scrollController,
341389 this .scrollPhysics,
390+ this .toolbarOptions = const ToolbarOptions (
391+ copy: true ,
392+ cut: true ,
393+ paste: true ,
394+ selectAll: true
395+ )
342396 }) : assert (controller != null ),
343397 assert (focusNode != null ),
344398 assert (obscureText != null ),
345399 assert (autocorrect != null ),
346400 assert (showSelectionHandles != null ),
401+ assert (enableInteractiveSelection != null ),
347402 assert (readOnly != null ),
348403 assert (forceLine != null ),
349404 assert (style != null ),
@@ -367,6 +422,7 @@ class EditableText extends StatefulWidget {
367422 assert (rendererIgnoresPointer != null ),
368423 assert (scrollPadding != null ),
369424 assert (dragStartBehavior != null ),
425+ assert (toolbarOptions != null ),
370426 _strutStyle = strutStyle,
371427 keyboardType = keyboardType ?? (maxLines == 1 ? TextInputType .text : TextInputType .multiline),
372428 inputFormatters = maxLines == 1
@@ -419,6 +475,12 @@ class EditableText extends StatefulWidget {
419475 /// * [textWidthBasis] , which controls the calculation of text width.
420476 final bool forceLine;
421477
478+ /// Configuration of toolbar options.
479+ ///
480+ /// By default, all options are enabled. If [readOnly] is true,
481+ /// paste and cut will be disabled regardless.
482+ final ToolbarOptions toolbarOptions;
483+
422484 /// Whether to show selection handles.
423485 ///
424486 /// When a selection is active, there will be two handles at each side of
@@ -903,9 +965,7 @@ class EditableText extends StatefulWidget {
903965 final ScrollPhysics scrollPhysics;
904966
905967 /// {@macro flutter.rendering.editable.selectionEnabled}
906- bool get selectionEnabled {
907- return enableInteractiveSelection ?? ! obscureText;
908- }
968+ bool get selectionEnabled => enableInteractiveSelection;
909969
910970 @override
911971 EditableTextState createState () => EditableTextState ();
@@ -969,16 +1029,16 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
9691029 Color get _cursorColor => widget.cursorColor.withOpacity (_cursorBlinkOpacityController.value);
9701030
9711031 @override
972- bool get cutEnabled => ! widget.readOnly;
1032+ bool get cutEnabled => widget.toolbarOptions.cut && ! widget.readOnly;
9731033
9741034 @override
975- bool get copyEnabled => true ;
1035+ bool get copyEnabled => widget.toolbarOptions.copy ;
9761036
9771037 @override
978- bool get pasteEnabled => ! widget.readOnly;
1038+ bool get pasteEnabled => widget.toolbarOptions.paste && ! widget.readOnly;
9791039
9801040 @override
981- bool get selectAllEnabled => true ;
1041+ bool get selectAllEnabled => widget.toolbarOptions.selectAll ;
9821042
9831043 // State lifecycle:
9841044
0 commit comments