diff --git a/examples/api/lib/widgets/editable_text/text_editing_controller.1.dart b/examples/api/lib/widgets/editable_text/text_editing_controller.1.dart new file mode 100644 index 00000000000..46672976e1f --- /dev/null +++ b/examples/api/lib/widgets/editable_text/text_editing_controller.1.dart @@ -0,0 +1,61 @@ +// 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'; + +/// Flutter code sample for [TextEditingController]. + +void main() { + runApp(const TextEditingControllerExampleApp()); +} + +class TextEditingControllerExampleApp extends StatelessWidget { + const TextEditingControllerExampleApp({super.key}); + + @override + Widget build(BuildContext context) { + return const MaterialApp( + home: TextEditingControllerExample(), + ); + } +} + +class TextEditingControllerExample extends StatefulWidget { + const TextEditingControllerExample({super.key}); + + @override + State createState() => _TextEditingControllerExampleState(); +} + +class _TextEditingControllerExampleState extends State { + // Create a controller whose initial selection is empty (collapsed) and positioned + // before the text (offset is 0). + final TextEditingController _controller = TextEditingController.fromValue( + const TextEditingValue( + text: 'Flutter', + selection: TextSelection.collapsed(offset: 0), + ), + ); + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Container( + alignment: Alignment.center, + padding: const EdgeInsets.all(16.0), + child: TextField( + controller: _controller, + autofocus: true, + decoration: const InputDecoration(filled: true), + ), + ), + ); + } +} diff --git a/examples/api/test/widgets/editable_text/text_editing_controller.1_test.dart b/examples/api/test/widgets/editable_text/text_editing_controller.1_test.dart new file mode 100644 index 00000000000..b60106e29e1 --- /dev/null +++ b/examples/api/test/widgets/editable_text/text_editing_controller.1_test.dart @@ -0,0 +1,21 @@ +// 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/editable_text/text_editing_controller.1.dart' as example; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + testWidgets('Initial selection is collasped at offset 0', (WidgetTester tester) async { + await tester.pumpWidget( + const example.TextEditingControllerExampleApp(), + ); + + final EditableText editableText = tester.widget(find.byType(EditableText)); + final TextEditingController controller = editableText.controller; + + expect(controller.text, 'Flutter'); + expect(controller.selection, const TextSelection.collapsed(offset: 0)); + }); +} diff --git a/packages/flutter/lib/src/widgets/editable_text.dart b/packages/flutter/lib/src/widgets/editable_text.dart index 940357b20cc..ba7f39ecb3c 100644 --- a/packages/flutter/lib/src/widgets/editable_text.dart +++ b/packages/flutter/lib/src/widgets/editable_text.dart @@ -178,6 +178,7 @@ class _RenderCompositionCallback extends RenderProxyBox { /// /// Remember to [dispose] of the [TextEditingController] when it is no longer /// needed. This will ensure we discard any resources used by the object. +/// /// {@tool dartpad} /// This example creates a [TextField] with a [TextEditingController] whose /// change listener forces the entered text to be lower case and keeps the @@ -198,6 +199,24 @@ class TextEditingController extends ValueNotifier { /// /// This constructor treats a null [text] argument as if it were the empty /// string. + /// + /// The initial selection is `TextSelection.collapsed(offset: -1)`. + /// This indicates that there is no selection at all ([TextSelection.isValid] + /// is false in this case). When a text field is built with a controller whose + /// selection is not valid, the text field will update the selection when it + /// is focused (the selection will be an empty selection positioned at the + /// end of the text). + // + /// Consider using [TextEditingController.fromValue] to initialize both the + /// text and the selection. + /// + /// {@tool dartpad} + /// This example creates a [TextField] with a [TextEditingController] whose + /// initial selection is empty (collapsed) and positioned at the beginning + /// of the text (offset is 0). + /// + /// ** See code in examples/api/lib/widgets/editable_text/text_editing_controller.1.dart ** + /// {@end-tool} TextEditingController({ String? text }) : super(text == null ? TextEditingValue.empty : TextEditingValue(text: text));