Skip to content

Commit fe6c969

Browse files
Renzo-OlivaresRenzo Olivares
andauthored
Update default selectionHeightStyle and selectionWidthStyle for EditableText (#167762)
This change updates the default `selectionHeightStyle` and `selectionWidthStyle` for `EditableText` to more closely match the behavior on native platforms. ```dart /// The default value for [selectionHeightStyle]. /// /// On web platforms, this defaults to [ui.BoxHeightStyle.max]. /// /// On native platforms, this defaults to [ui.BoxHeightStyle.includeLineSpacingMiddle] for all /// platforms. static ui.BoxHeightStyle get defaultSelectionHeightStyle { if (kIsWeb) { return ui.BoxHeightStyle.max; } switch (defaultTargetPlatform) { case TargetPlatform.android: case TargetPlatform.fuchsia: case TargetPlatform.iOS: case TargetPlatform.linux: case TargetPlatform.macOS: case TargetPlatform.windows: return ui.BoxHeightStyle.includeLineSpacingMiddle; } } /// The default value for [selectionWidthStyle]. /// /// On web platforms, this defaults to [ui.BoxWidthStyle.max] for Apple platforms and /// [ui.BoxWidthStyle.tight] for all others. /// /// On non-web platforms, this defaults to [ui.BoxWidthStyle.max] for all /// platforms. static ui.BoxWidthStyle get defaultSelectionWidthStyle { if (kIsWeb) { if (defaultTargetPlatform == TargetPlatform.iOS || WebBrowserDetection.browserIsSafari) { return ui.BoxWidthStyle.max; } return ui.BoxWidthStyle.tight; } switch (defaultTargetPlatform) { case TargetPlatform.android: case TargetPlatform.fuchsia: case TargetPlatform.iOS: case TargetPlatform.linux: case TargetPlatform.macOS: case TargetPlatform.windows: return ui.BoxWidthStyle.max; } } ``` ## Native Selection Style Behavior ### Android Native Behavior | Component Type | UI Framework / Component | Image | |---|---|---| | **Static Text** | Android TextView | <img height="400" alt="native_android_static_textview" src="https://github.com/user-attachments/assets/34da885c-c3d8-4ecc-baf5-65cd32850aa7" /> | | **Static Text** | Jetpack Compose Text | <img height="400" alt="native_android_static_compose" src="https://github.com/user-attachments/assets/ef916e8d-3627-4394-b5a1-aa59989ba826" /> | | **Static Text** | Chrome (Web) "p element" | <img height="400" alt="android_chrome_web" src="https://github.com/user-attachments/assets/b6537871-5d07-470b-bdee-ae0d222b2404" /> | | **Text Field** | Android EditText | <img height="400" alt="native_android_textfield_edittext" src="https://github.com/user-attachments/assets/ef91c6c3-eed0-4cf5-8b6f-182ecf8ce60b" /> | | **Text Field** | Jetpack Compose TextField | <img height="400" alt="native_android_textfield_compose" src="https://github.com/user-attachments/assets/891c28ba-66f7-4923-a1d3-839cad3b039c" /> | ### iOS Native Behavior | Component Type | UI Framework / Component | Image | |---|---|---| | **Text Field** | Native SwiftUI TextEditor | <img height="400" alt="native_ios_texteditor" src="https://github.com/user-attachments/assets/b99adb30-8cb3-454e-aa56-41f3cfadeeed" /> | | **Text Field** | Native SwiftUI TextField | <img height="400" alt="native_ios_textfield" src="https://github.com/user-attachments/assets/0544419b-b9a7-4641-930b-9a123f9a7720" /> | | **Static Text** | Safari (Web) "p element" | <img height="400" alt="mobile_safari_web" src="https://github.com/user-attachments/assets/6934ed80-4712-4000-bff0-4d5d2833abbe" /> | ### macOS Native Behavior | Component Type | UI Framework / Component | Image | |---|---|---| | **Static Text** | Native SwiftUI Text | <img height="400" alt="native_macos_static_text" src="https://github.com/user-attachments/assets/becf7690-878e-4cf1-b9d7-49725d58fd42" /> | | **Static Text** | Chrome (Web) "p element" | <img height="400" alt="chrome_web" src="https://github.com/user-attachments/assets/bf38e1c0-7bd6-42b7-8230-71b8365ac1d7" /> | | **Static Text** | Firefox (Web) "p element" | <img height="400" alt="firefox_web" src="https://github.com/user-attachments/assets/54817628-690b-4243-8bb0-0d94afaf5013" /> | | **Static Text** | Safari (Web) "p element" | <img height="400" alt="safari_web" src="https://github.com/user-attachments/assets/08ae8a6e-8ea5-4cc5-84f8-49c5f759e910" /> | | **Text Field** | Native SwiftUI TextEditor | <img height="400" alt="native_macos_texteditor" src="https://github.com/user-attachments/assets/43995c72-acf5-4ef0-99d7-faa3940b16e7" /> | | **Text Field** | Native SwiftUI TextField | <img alt="native_macos_textfield" src="https://github.com/user-attachments/assets/d5606b23-dff0-47da-a1e8-b1c71047c426" /> | ## Flutter Selection Style Behavior ### Flutter Before Behavior This was the behavior on all platforms before this change. | Component Type | Behavior | Image | |---|---|---| | **Text Field** | Flutter TextField | <img height="400" alt="flutter_before_text_field" src="https://github.com/user-attachments/assets/014bfc9d-0bbe-49ee-9230-9da80addc675" /> | | **Static Text** | Flutter SelectableText | <img height="400" alt="flutter_before_selectabletext" src="https://github.com/user-attachments/assets/251956c6-4d7d-4d3e-802a-33718f30cbf3" /> | ### Flutter Chrome After Behavior This is the behavior on all chrome web after this change. | Component Type | Behavior | Image | |---|---|---| | **Static Text** | Flutter SelectableText in Chrome | <img height="400" alt="flutter_after_chrome_selectabletext" src="https://github.com/user-attachments/assets/167ee998-c9c4-4367-ab77-149514fb2b15" /> | | **Text Field** | Flutter TextField in Chrome | <img height="400" alt="flutter_after_chrome_textfield" src="https://github.com/user-attachments/assets/76b123df-c818-4304-afb8-7034506e2031" /> | ### Flutter Safari After Behavior This is the behavior on Safari after this change. (all iOS browsers, and Safari on macOS). | Component Type | Behavior | Image | |---|---|---| | **Text Field** | Flutter TextField in Safari | <img height="400" alt="flutter_after_safari_textfield" src="https://github.com/user-attachments/assets/c37e80cf-d89a-43aa-baff-f32e94f39b56" /> | | **Static Text** | Flutter SelectableText in Safari | <img height="400" alt="flutter_after_safari_selectabletext" src="https://github.com/user-attachments/assets/c1a11d76-afb9-4265-af54-e20e183839e1" /> | ### Flutter Native After Behavior This is the behavior on native platforms after this change. | Component Type | Behavior | Image | |---|---|---| | **Static Text** | Flutter SelectableText on Native platforms | <img height="400" alt="flutter_after_native_selectabletext" src="https://github.com/user-attachments/assets/5506eb4c-13ed-4c04-b680-9d097f20b159" /> | | **Text Field** | Flutter TextField on Native platforms | <img height="400" alt="flutter_after_native_textfield" src="https://github.com/user-attachments/assets/e65bba53-34d3-480c-9293-d597b587fe70" /> | Fixes #68675 ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. --------- Co-authored-by: Renzo Olivares <[email protected]>
1 parent b5dbfc3 commit fe6c969

14 files changed

Lines changed: 253 additions & 47 deletions

‎packages/flutter/lib/src/cupertino/text_field.dart‎

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,8 @@ class CupertinoTextField extends StatefulWidget {
208208
///
209209
/// The [selectionHeightStyle] and [selectionWidthStyle] properties allow
210210
/// changing the shape of the selection highlighting. These properties default
211-
/// to [ui.BoxHeightStyle.tight] and [ui.BoxWidthStyle.tight], respectively.
211+
/// to [EditableText.defaultSelectionHeightStyle] and
212+
/// [EditableText.defaultSelectionWidthStyle], respectively.
212213
///
213214
/// The [autocorrect], [autofocus], [clearButtonMode], [dragStartBehavior],
214215
/// [expands], [obscureText], [prefixMode], [readOnly], [scrollPadding],
@@ -284,8 +285,8 @@ class CupertinoTextField extends StatefulWidget {
284285
this.cursorRadius = const Radius.circular(2.0),
285286
this.cursorOpacityAnimates = true,
286287
this.cursorColor,
287-
this.selectionHeightStyle = ui.BoxHeightStyle.tight,
288-
this.selectionWidthStyle = ui.BoxWidthStyle.tight,
288+
this.selectionHeightStyle,
289+
this.selectionWidthStyle,
289290
this.keyboardAppearance,
290291
this.scrollPadding = const EdgeInsets.all(20.0),
291292
this.dragStartBehavior = DragStartBehavior.start,
@@ -423,8 +424,8 @@ class CupertinoTextField extends StatefulWidget {
423424
this.cursorRadius = const Radius.circular(2.0),
424425
this.cursorOpacityAnimates = true,
425426
this.cursorColor,
426-
this.selectionHeightStyle = ui.BoxHeightStyle.tight,
427-
this.selectionWidthStyle = ui.BoxWidthStyle.tight,
427+
this.selectionHeightStyle,
428+
this.selectionWidthStyle,
428429
this.keyboardAppearance,
429430
this.scrollPadding = const EdgeInsets.all(20.0),
430431
this.dragStartBehavior = DragStartBehavior.start,
@@ -732,12 +733,12 @@ class CupertinoTextField extends StatefulWidget {
732733
/// Controls how tall the selection highlight boxes are computed to be.
733734
///
734735
/// See [ui.BoxHeightStyle] for details on available styles.
735-
final ui.BoxHeightStyle selectionHeightStyle;
736+
final ui.BoxHeightStyle? selectionHeightStyle;
736737

737738
/// Controls how wide the selection highlight boxes are computed to be.
738739
///
739740
/// See [ui.BoxWidthStyle] for details on available styles.
740-
final ui.BoxWidthStyle selectionWidthStyle;
741+
final ui.BoxWidthStyle? selectionWidthStyle;
741742

742743
/// The appearance of the keyboard.
743744
///

‎packages/flutter/lib/src/cupertino/text_form_field_row.dart‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// Use of this source code is governed by a BSD-style license that can be
33
// found in the LICENSE file.
44

5+
import 'dart:ui' as ui show BoxHeightStyle, BoxWidthStyle;
6+
57
import 'package:flutter/foundation.dart';
68
import 'package:flutter/services.dart';
79
import 'package:flutter/widgets.dart';
@@ -159,6 +161,8 @@ class CupertinoTextFormFieldRow extends FormField<String> {
159161
),
160162
EditableTextContextMenuBuilder? contextMenuBuilder = _defaultContextMenuBuilder,
161163
SpellCheckConfiguration? spellCheckConfiguration,
164+
ui.BoxHeightStyle? selectionHeightStyle,
165+
ui.BoxWidthStyle? selectionWidthStyle,
162166
super.restorationId,
163167
}) : assert(initialValue == null || controller == null),
164168
assert(obscuringCharacter.length == 1),
@@ -236,6 +240,10 @@ class CupertinoTextFormFieldRow extends FormField<String> {
236240
placeholderStyle: placeholderStyle,
237241
contextMenuBuilder: contextMenuBuilder,
238242
spellCheckConfiguration: spellCheckConfiguration,
243+
selectionHeightStyle:
244+
selectionHeightStyle ?? EditableText.defaultSelectionHeightStyle,
245+
selectionWidthStyle:
246+
selectionWidthStyle ?? EditableText.defaultSelectionWidthStyle,
239247
),
240248
),
241249
);

‎packages/flutter/lib/src/material/selectable_text.dart‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -184,8 +184,8 @@ class SelectableText extends StatefulWidget {
184184
this.cursorRadius,
185185
this.cursorColor,
186186
this.selectionColor,
187-
this.selectionHeightStyle = ui.BoxHeightStyle.tight,
188-
this.selectionWidthStyle = ui.BoxWidthStyle.tight,
187+
this.selectionHeightStyle,
188+
this.selectionWidthStyle,
189189
this.dragStartBehavior = DragStartBehavior.start,
190190
this.enableInteractiveSelection = true,
191191
this.selectionControls,
@@ -243,8 +243,8 @@ class SelectableText extends StatefulWidget {
243243
this.cursorRadius,
244244
this.cursorColor,
245245
this.selectionColor,
246-
this.selectionHeightStyle = ui.BoxHeightStyle.tight,
247-
this.selectionWidthStyle = ui.BoxWidthStyle.tight,
246+
this.selectionHeightStyle,
247+
this.selectionWidthStyle,
248248
this.dragStartBehavior = DragStartBehavior.start,
249249
this.enableInteractiveSelection = true,
250250
this.selectionControls,
@@ -375,12 +375,12 @@ class SelectableText extends StatefulWidget {
375375
/// Controls how tall the selection highlight boxes are computed to be.
376376
///
377377
/// See [ui.BoxHeightStyle] for details on available styles.
378-
final ui.BoxHeightStyle selectionHeightStyle;
378+
final ui.BoxHeightStyle? selectionHeightStyle;
379379

380380
/// Controls how wide the selection highlight boxes are computed to be.
381381
///
382382
/// See [ui.BoxWidthStyle] for details on available styles.
383-
final ui.BoxWidthStyle selectionWidthStyle;
383+
final ui.BoxWidthStyle? selectionWidthStyle;
384384

385385
/// {@macro flutter.widgets.editableText.enableInteractiveSelection}
386386
final bool enableInteractiveSelection;

‎packages/flutter/lib/src/material/text_field.dart‎

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,8 @@ class TextField extends StatefulWidget {
232232
///
233233
/// The [selectionHeightStyle] and [selectionWidthStyle] properties allow
234234
/// changing the shape of the selection highlighting. These properties default
235-
/// to [ui.BoxHeightStyle.tight] and [ui.BoxWidthStyle.tight], respectively.
235+
/// to [EditableText.defaultSelectionHeightStyle] and
236+
/// [EditableText.defaultSelectionHeightStyle], respectively.
236237
///
237238
/// See also:
238239
///
@@ -286,8 +287,8 @@ class TextField extends StatefulWidget {
286287
this.cursorOpacityAnimates,
287288
this.cursorColor,
288289
this.cursorErrorColor,
289-
this.selectionHeightStyle = ui.BoxHeightStyle.tight,
290-
this.selectionWidthStyle = ui.BoxWidthStyle.tight,
290+
this.selectionHeightStyle,
291+
this.selectionWidthStyle,
291292
this.keyboardAppearance,
292293
this.scrollPadding = const EdgeInsets.all(20.0),
293294
this.dragStartBehavior = DragStartBehavior.start,
@@ -665,12 +666,12 @@ class TextField extends StatefulWidget {
665666
/// Controls how tall the selection highlight boxes are computed to be.
666667
///
667668
/// See [ui.BoxHeightStyle] for details on available styles.
668-
final ui.BoxHeightStyle selectionHeightStyle;
669+
final ui.BoxHeightStyle? selectionHeightStyle;
669670

670671
/// Controls how wide the selection highlight boxes are computed to be.
671672
///
672673
/// See [ui.BoxWidthStyle] for details on available styles.
673-
final ui.BoxWidthStyle selectionWidthStyle;
674+
final ui.BoxWidthStyle? selectionWidthStyle;
674675

675676
/// The appearance of the keyboard.
676677
///

‎packages/flutter/lib/src/material/text_form_field.dart‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -179,8 +179,8 @@ class TextFormField extends FormField<String> {
179179
UndoHistoryController? undoController,
180180
AppPrivateCommandCallback? onAppPrivateCommand,
181181
bool? cursorOpacityAnimates,
182-
ui.BoxHeightStyle selectionHeightStyle = ui.BoxHeightStyle.tight,
183-
ui.BoxWidthStyle selectionWidthStyle = ui.BoxWidthStyle.tight,
182+
ui.BoxHeightStyle? selectionHeightStyle,
183+
ui.BoxWidthStyle? selectionWidthStyle,
184184
DragStartBehavior dragStartBehavior = DragStartBehavior.start,
185185
ContentInsertionConfiguration? contentInsertionConfiguration,
186186
MaterialStatesController? statesController,
@@ -297,8 +297,9 @@ class TextFormField extends FormField<String> {
297297
undoController: undoController,
298298
onAppPrivateCommand: onAppPrivateCommand,
299299
cursorOpacityAnimates: cursorOpacityAnimates,
300-
selectionHeightStyle: selectionHeightStyle,
301-
selectionWidthStyle: selectionWidthStyle,
300+
selectionHeightStyle:
301+
selectionHeightStyle ?? EditableText.defaultSelectionHeightStyle,
302+
selectionWidthStyle: selectionWidthStyle ?? EditableText.defaultSelectionWidthStyle,
302303
dragStartBehavior: dragStartBehavior,
303304
contentInsertionConfiguration: contentInsertionConfiguration,
304305
clipBehavior: clipBehavior,

‎packages/flutter/lib/src/rendering/editable.dart‎

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -324,8 +324,8 @@ class RenderEditable extends RenderBox
324324
bool paintCursorAboveText = false,
325325
Offset cursorOffset = Offset.zero,
326326
double devicePixelRatio = 1.0,
327-
ui.BoxHeightStyle selectionHeightStyle = ui.BoxHeightStyle.tight,
328-
ui.BoxWidthStyle selectionWidthStyle = ui.BoxWidthStyle.tight,
327+
ui.BoxHeightStyle selectionHeightStyle = ui.BoxHeightStyle.max,
328+
ui.BoxWidthStyle selectionWidthStyle = ui.BoxWidthStyle.max,
329329
bool? enableInteractiveSelection,
330330
this.floatingCursorAddedMargin = const EdgeInsets.fromLTRB(4, 4, 4, 5),
331331
TextRange? promptRectRange,
@@ -1318,7 +1318,11 @@ class RenderEditable extends RenderBox
13181318
List<TextBox> getBoxesForSelection(TextSelection selection) {
13191319
_computeTextMetricsIfNeeded();
13201320
return _textPainter
1321-
.getBoxesForSelection(selection)
1321+
.getBoxesForSelection(
1322+
selection,
1323+
boxHeightStyle: selectionHeightStyle,
1324+
boxWidthStyle: selectionWidthStyle,
1325+
)
13221326
.map(
13231327
(TextBox textBox) => TextBox.fromLTRBD(
13241328
textBox.left + _paintOffset.dx,
@@ -2921,11 +2925,14 @@ class _TextHighlightPainter extends RenderEditablePainter {
29212925

29222926
highlightPaint.color = color;
29232927
final TextPainter textPainter = renderEditable._textPainter;
2924-
final List<TextBox> boxes = textPainter.getBoxesForSelection(
2925-
TextSelection(baseOffset: range.start, extentOffset: range.end),
2926-
boxHeightStyle: selectionHeightStyle,
2927-
boxWidthStyle: selectionWidthStyle,
2928-
);
2928+
final Set<TextBox> boxes =
2929+
textPainter
2930+
.getBoxesForSelection(
2931+
TextSelection(baseOffset: range.start, extentOffset: range.end),
2932+
boxHeightStyle: selectionHeightStyle,
2933+
boxWidthStyle: selectionWidthStyle,
2934+
)
2935+
.toSet();
29292936

29302937
for (final TextBox box in boxes) {
29312938
canvas.drawRect(
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Copyright 2014 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
// The class in this file is an implementation for non-web platforms that will always
6+
// return false. See `_web_browser_detection.dart` for the web implementation.
7+
8+
/// A class that provides information about the current browser when on the web.
9+
class WebBrowserDetection {
10+
/// Whether the current browser is webkit (Safari). Always returns false on non-web platforms.
11+
static bool get isSafari => false;
12+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Copyright 2014 The Flutter Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
import 'dart:ui_web' as ui_web;
6+
7+
/// A class that provides information about the current browser when on the web.
8+
class WebBrowserDetection {
9+
/// Whether the current browser is webkit (Safari). Always returns false on non-web platforms.
10+
static bool get isSafari => ui_web.BrowserDetection.instance.isSafari;
11+
}

‎packages/flutter/lib/src/widgets/editable_text.dart‎

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import 'package:flutter/rendering.dart';
2525
import 'package:flutter/scheduler.dart';
2626
import 'package:flutter/services.dart';
2727

28+
import '_web_browser_detection_io.dart' if (dart.library.js_util) '_web_browser_detection_web.dart';
2829
import 'actions.dart';
2930
import 'app_lifecycle_listener.dart';
3031
import 'autofill.dart';
@@ -876,8 +877,8 @@ class EditableText extends StatefulWidget {
876877
this.cursorOpacityAnimates = false,
877878
this.cursorOffset,
878879
this.paintCursorAboveText = false,
879-
this.selectionHeightStyle = ui.BoxHeightStyle.tight,
880-
this.selectionWidthStyle = ui.BoxWidthStyle.tight,
880+
ui.BoxHeightStyle? selectionHeightStyle,
881+
ui.BoxWidthStyle? selectionWidthStyle,
881882
this.scrollPadding = const EdgeInsets.all(20.0),
882883
this.keyboardAppearance = Brightness.light,
883884
this.dragStartBehavior = DragStartBehavior.start,
@@ -964,7 +965,9 @@ class EditableText extends StatefulWidget {
964965
...inputFormatters ?? const Iterable<TextInputFormatter>.empty(),
965966
]
966967
: inputFormatters,
967-
showCursor = showCursor ?? !readOnly;
968+
showCursor = showCursor ?? !readOnly,
969+
selectionHeightStyle = selectionHeightStyle ?? defaultSelectionHeightStyle,
970+
selectionWidthStyle = selectionWidthStyle ?? defaultSelectionWidthStyle;
968971

969972
/// Controls the text being edited.
970973
final TextEditingController controller;
@@ -2049,6 +2052,37 @@ class EditableText extends StatefulWidget {
20492052
/// {@macro flutter.services.TextInputConfiguration.hintLocales}
20502053
final List<Locale>? hintLocales;
20512054

2055+
/// The default value for [selectionHeightStyle].
2056+
///
2057+
/// On web platforms, this defaults to [ui.BoxHeightStyle.max].
2058+
///
2059+
/// On native platforms, this defaults to [ui.BoxHeightStyle.includeLineSpacingMiddle] for all
2060+
/// platforms.
2061+
static ui.BoxHeightStyle get defaultSelectionHeightStyle {
2062+
if (kIsWeb) {
2063+
return ui.BoxHeightStyle.max;
2064+
}
2065+
return ui.BoxHeightStyle.includeLineSpacingMiddle;
2066+
}
2067+
2068+
/// The default value for [selectionWidthStyle].
2069+
///
2070+
/// On web platforms, this defaults to [ui.BoxWidthStyle.max] for Apple platforms running
2071+
/// Safari (webkit) based browsers and [ui.BoxWidthStyle.tight] for all others.
2072+
///
2073+
/// On non-web platforms, this defaults to [ui.BoxWidthStyle.max].
2074+
static ui.BoxWidthStyle get defaultSelectionWidthStyle {
2075+
if (kIsWeb) {
2076+
if (defaultTargetPlatform == TargetPlatform.iOS || WebBrowserDetection.isSafari) {
2077+
// On macOS web, the selection width behavior differs when running on
2078+
// Chrom(e|ium) (blink) or Safari (webkit).
2079+
return ui.BoxWidthStyle.max;
2080+
}
2081+
return ui.BoxWidthStyle.tight;
2082+
}
2083+
return ui.BoxWidthStyle.max;
2084+
}
2085+
20522086
/// The default value for [stylusHandwritingEnabled].
20532087
static const bool defaultStylusHandwritingEnabled = true;
20542088

@@ -5923,15 +5957,17 @@ class _Editable extends MultiChildRenderObjectWidget {
59235957
this.cursorRadius,
59245958
required this.cursorOffset,
59255959
required this.paintCursorAboveText,
5926-
this.selectionHeightStyle = ui.BoxHeightStyle.tight,
5927-
this.selectionWidthStyle = ui.BoxWidthStyle.tight,
5960+
ui.BoxHeightStyle? selectionHeightStyle,
5961+
ui.BoxWidthStyle? selectionWidthStyle,
59285962
this.enableInteractiveSelection = true,
59295963
required this.textSelectionDelegate,
59305964
required this.devicePixelRatio,
59315965
this.promptRectRange,
59325966
this.promptRectColor,
59335967
required this.clipBehavior,
5934-
}) : super(children: WidgetSpan.extractFromInlineSpan(inlineSpan, textScaler));
5968+
}) : selectionHeightStyle = selectionHeightStyle ?? EditableText.defaultSelectionHeightStyle,
5969+
selectionWidthStyle = selectionWidthStyle ?? EditableText.defaultSelectionWidthStyle,
5970+
super(children: WidgetSpan.extractFromInlineSpan(inlineSpan, textScaler));
59355971

59365972
final InlineSpan inlineSpan;
59375973
final TextEditingValue value;

‎packages/flutter/test/cupertino/text_field_test.dart‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7850,7 +7850,6 @@ void main() {
78507850
style: const TextStyle(height: 4, color: ui.Color.fromARGB(100, 0, 0, 0)),
78517851
toolbarOptions: const ToolbarOptions(selectAll: true),
78527852
selectionHeightStyle: ui.BoxHeightStyle.includeLineSpacingTop,
7853-
selectionWidthStyle: ui.BoxWidthStyle.max,
78547853
maxLines: 3,
78557854
),
78567855
],
@@ -7905,6 +7904,7 @@ void main() {
79057904
style: const TextStyle(height: 4, color: ui.Color.fromARGB(100, 0, 0, 0)),
79067905
toolbarOptions: const ToolbarOptions(selectAll: true),
79077906
selectionHeightStyle: ui.BoxHeightStyle.includeLineSpacingBottom,
7907+
selectionWidthStyle: ui.BoxWidthStyle.tight,
79087908
maxLines: 3,
79097909
),
79107910
],

0 commit comments

Comments
 (0)