Unverified Commit 9fccb32a authored by Ian Hickson's avatar Ian Hickson Committed by GitHub

Various improvements to text-editing-related documentation. (#142561)

parent 4becae25
...@@ -763,15 +763,14 @@ class CupertinoTextField extends StatefulWidget { ...@@ -763,15 +763,14 @@ class CupertinoTextField extends StatefulWidget {
); );
} }
/// {@macro flutter.widgets.magnifier.TextMagnifierConfiguration.intro} /// Configuration for the text field magnifier.
/// ///
/// {@macro flutter.widgets.magnifier.intro} /// By default (when this property is set to null), a [CupertinoTextMagnifier]
/// /// is used on mobile platforms, and nothing on desktop platforms. To suppress
/// {@macro flutter.widgets.magnifier.TextMagnifierConfiguration.details} /// the magnifier on all platforms, consider passing
/// [TextMagnifierConfiguration.disabled] explicitly.
/// ///
/// By default, builds a [CupertinoTextMagnifier] on iOS and Android nothing on all other /// {@macro flutter.widgets.magnifier.intro}
/// platforms. If it is desired to suppress the magnifier, consider passing
/// [TextMagnifierConfiguration.disabled].
/// ///
/// {@tool dartpad} /// {@tool dartpad}
/// This sample demonstrates how to customize the magnifier that this text field uses. /// This sample demonstrates how to customize the magnifier that this text field uses.
......
...@@ -502,15 +502,13 @@ class SelectableText extends StatefulWidget { ...@@ -502,15 +502,13 @@ class SelectableText extends StatefulWidget {
); );
} }
/// {@macro flutter.widgets.magnifier.TextMagnifierConfiguration.intro} /// The configuration for the magnifier used when the text is selected.
///
/// {@macro flutter.widgets.magnifier.intro}
///
/// {@macro flutter.widgets.magnifier.TextMagnifierConfiguration.details}
/// ///
/// By default, builds a [CupertinoTextMagnifier] on iOS and [TextMagnifier] /// By default, builds a [CupertinoTextMagnifier] on iOS and [TextMagnifier]
/// on Android, and builds nothing on all other platforms. If it is desired to /// on Android, and builds nothing on all other platforms. To suppress the
/// suppress the magnifier, consider passing [TextMagnifierConfiguration.disabled]. /// magnifier, consider passing [TextMagnifierConfiguration.disabled].
///
/// {@macro flutter.widgets.magnifier.intro}
final TextMagnifierConfiguration? magnifierConfiguration; final TextMagnifierConfiguration? magnifierConfiguration;
@override @override
......
...@@ -33,6 +33,7 @@ import 'theme.dart'; ...@@ -33,6 +33,7 @@ import 'theme.dart';
/// {@end-tool} /// {@end-tool}
/// ///
/// See also: /// See also:
///
/// * [SelectableRegion], which provides an overview of the selection system. /// * [SelectableRegion], which provides an overview of the selection system.
class SelectionArea extends StatefulWidget { class SelectionArea extends StatefulWidget {
/// Creates a [SelectionArea]. /// Creates a [SelectionArea].
...@@ -48,15 +49,13 @@ class SelectionArea extends StatefulWidget { ...@@ -48,15 +49,13 @@ class SelectionArea extends StatefulWidget {
required this.child, required this.child,
}); });
/// {@macro flutter.widgets.magnifier.TextMagnifierConfiguration.intro} /// The configuration for the magnifier in the selection region.
///
/// {@macro flutter.widgets.magnifier.intro}
///
/// {@macro flutter.widgets.magnifier.TextMagnifierConfiguration.details}
/// ///
/// By default, builds a [CupertinoTextMagnifier] on iOS and [TextMagnifier] /// By default, builds a [CupertinoTextMagnifier] on iOS and [TextMagnifier]
/// on Android, and builds nothing on all other platforms. If it is desired to /// on Android, and builds nothing on all other platforms. To suppress the
/// suppress the magnifier, consider passing [TextMagnifierConfiguration.disabled]. /// magnifier, consider passing [TextMagnifierConfiguration.disabled].
///
/// {@macro flutter.widgets.magnifier.intro}
final TextMagnifierConfiguration? magnifierConfiguration; final TextMagnifierConfiguration? magnifierConfiguration;
/// {@macro flutter.widgets.Focus.focusNode} /// {@macro flutter.widgets.Focus.focusNode}
......
...@@ -349,15 +349,13 @@ class TextField extends StatefulWidget { ...@@ -349,15 +349,13 @@ class TextField extends StatefulWidget {
keyboardType = keyboardType ?? (maxLines == 1 ? TextInputType.text : TextInputType.multiline), keyboardType = keyboardType ?? (maxLines == 1 ? TextInputType.text : TextInputType.multiline),
enableInteractiveSelection = enableInteractiveSelection ?? (!readOnly || !obscureText); enableInteractiveSelection = enableInteractiveSelection ?? (!readOnly || !obscureText);
/// {@macro flutter.widgets.magnifier.TextMagnifierConfiguration.intro} /// The configuration for the magnifier of this text field.
///
/// {@macro flutter.widgets.magnifier.intro}
///
/// {@macro flutter.widgets.magnifier.TextMagnifierConfiguration.details}
/// ///
/// By default, builds a [CupertinoTextMagnifier] on iOS and [TextMagnifier] /// By default, builds a [CupertinoTextMagnifier] on iOS and [TextMagnifier]
/// on Android, and builds nothing on all other platforms. If it is desired to /// on Android, and builds nothing on all other platforms. To suppress the
/// suppress the magnifier, consider passing [TextMagnifierConfiguration.disabled]. /// magnifier, consider passing [TextMagnifierConfiguration.disabled].
///
/// {@macro flutter.widgets.magnifier.intro}
/// ///
/// {@tool dartpad} /// {@tool dartpad}
/// This sample demonstrates how to customize the magnifier that this text field uses. /// This sample demonstrates how to customize the magnifier that this text field uses.
......
...@@ -1799,11 +1799,28 @@ class EditableText extends StatefulWidget { ...@@ -1799,11 +1799,28 @@ class EditableText extends StatefulWidget {
/// {@template flutter.widgets.EditableText.contextMenuBuilder} /// {@template flutter.widgets.EditableText.contextMenuBuilder}
/// Builds the text selection toolbar when requested by the user. /// Builds the text selection toolbar when requested by the user.
/// ///
/// `primaryAnchor` is the desired anchor position for the context menu, while /// The context menu is built when [EditableTextState.showToolbar] is called,
/// `secondaryAnchor` is the fallback location if the menu doesn't fit. /// typically by one of the callbacks installed by the widget created by
/// [TextSelectionGestureDetectorBuilder.buildGestureDetector]. The widget
/// returned by [contextMenuBuilder] is passed to a [ContextMenuController].
/// ///
/// `buttonItems` represents the buttons that would be built by default for /// If no callback is provided, no context menu will be shown.
/// this widget. ///
/// The [EditableTextContextMenuBuilder] signature used by the
/// [contextMenuBuilder] callback has two parameters, the [BuildContext] of
/// the [EditableText] and the [EditableTextState] of the [EditableText].
///
/// The [EditableTextState] has two properties that are especially useful when
/// building the widgets for the context menu:
///
/// * [EditableTextState.contextMenuAnchors] specifies the desired anchor
/// position for the context menu.
///
/// * [EditableTextState.contextMenuButtonItems] represents the buttons that
/// should typically be built for this widget (e.g. cut, copy, paste).
///
/// The [TextSelectionToolbarLayoutDelegate] class may be particularly useful
/// in honoring the preferred anchor positions.
/// ///
/// For backwards compatibility, when [selectionControls] is set to an object /// For backwards compatibility, when [selectionControls] is set to an object
/// that does not mix in [TextSelectionHandleControls], [contextMenuBuilder] /// that does not mix in [TextSelectionHandleControls], [contextMenuBuilder]
...@@ -1834,8 +1851,6 @@ class EditableText extends StatefulWidget { ...@@ -1834,8 +1851,6 @@ class EditableText extends StatefulWidget {
/// * [BrowserContextMenu], which allows the browser's context menu on web /// * [BrowserContextMenu], which allows the browser's context menu on web
/// to be disabled and Flutter-rendered context menus to appear. /// to be disabled and Flutter-rendered context menus to appear.
/// {@endtemplate} /// {@endtemplate}
///
/// If not provided, no context menu will be shown.
final EditableTextContextMenuBuilder? contextMenuBuilder; final EditableTextContextMenuBuilder? contextMenuBuilder;
/// {@template flutter.widgets.EditableText.spellCheckConfiguration} /// {@template flutter.widgets.EditableText.spellCheckConfiguration}
...@@ -1852,11 +1867,10 @@ class EditableText extends StatefulWidget { ...@@ -1852,11 +1867,10 @@ class EditableText extends StatefulWidget {
/// {@endtemplate} /// {@endtemplate}
final SpellCheckConfiguration? spellCheckConfiguration; final SpellCheckConfiguration? spellCheckConfiguration;
/// {@macro flutter.widgets.magnifier.TextMagnifierConfiguration.intro} /// The configuration for the magnifier to use with selections in this text
/// field.
/// ///
/// {@macro flutter.widgets.magnifier.intro} /// {@macro flutter.widgets.magnifier.intro}
///
/// {@macro flutter.widgets.magnifier.TextMagnifierConfiguration.details}
final TextMagnifierConfiguration magnifierConfiguration; final TextMagnifierConfiguration magnifierConfiguration;
bool get _userSelectionEnabled => enableInteractiveSelection && (!readOnly || !obscureText); bool get _userSelectionEnabled => enableInteractiveSelection && (!readOnly || !obscureText);
......
...@@ -15,19 +15,17 @@ import 'inherited_theme.dart'; ...@@ -15,19 +15,17 @@ import 'inherited_theme.dart';
import 'navigator.dart'; import 'navigator.dart';
import 'overlay.dart'; import 'overlay.dart';
/// {@template flutter.widgets.magnifier.MagnifierBuilder}
/// Signature for a builder that builds a [Widget] with a [MagnifierController]. /// Signature for a builder that builds a [Widget] with a [MagnifierController].
/// ///
/// Consuming [MagnifierController] or [ValueNotifier]<[MagnifierInfo]> is not /// The builder is called exactly once per magnifier.
/// required, although if a Widget intends to have entry or exit animations, it should take
/// [MagnifierController] and provide it an [AnimationController], so that [MagnifierController]
/// can wait before removing it from the overlay.
/// {@endtemplate}
/// ///
/// See also: /// If the `controller` parameter's [MagnifierController.animationController]
/// field is set (by the builder) to an [AnimationController], the
/// [MagnifierController] will drive the animation during entry and exit.
/// ///
/// - [MagnifierInfo], the data class that updates the /// The `magnifierInfo` parameter is updated with new [MagnifierInfo] instances
/// magnifier. /// during the lifetime of the built magnifier, e.g. as the user moves their
/// finger around the text field.
typedef MagnifierBuilder = Widget? Function( typedef MagnifierBuilder = Widget? Function(
BuildContext context, BuildContext context,
MagnifierController controller, MagnifierController controller,
...@@ -57,9 +55,9 @@ class MagnifierInfo { ...@@ -57,9 +55,9 @@ class MagnifierInfo {
/// The offset of the gesture position that the magnifier should be shown at. /// The offset of the gesture position that the magnifier should be shown at.
final Offset globalGesturePosition; final Offset globalGesturePosition;
/// The rect of the current line the magnifier should be shown at, /// The rect of the current line the magnifier should be shown at, without
/// without taking into account any padding of the field; only the position /// taking into account any padding of the field; only the position of the
/// of the first and last character. /// first and last character.
final Rect currentLineBoundaries; final Rect currentLineBoundaries;
/// The rect of the handle that the magnifier should follow. /// The rect of the handle that the magnifier should follow.
...@@ -89,48 +87,45 @@ class MagnifierInfo { ...@@ -89,48 +87,45 @@ class MagnifierInfo {
); );
} }
/// {@template flutter.widgets.magnifier.TextMagnifierConfiguration.intro} /// A configuration object for a magnifier (e.g. in a text field).
/// A configuration object for a magnifier.
/// {@endtemplate}
/// ///
/// {@macro flutter.widgets.magnifier.intro} /// In general, most features of the magnifier can be configured by controlling
/// /// the widgets built by the [magnifierBuilder].
/// {@template flutter.widgets.magnifier.TextMagnifierConfiguration.details}
/// In general, most features of the magnifier can be configured through
/// [MagnifierBuilder]. [TextMagnifierConfiguration] is used to configure
/// the magnifier's behavior through the [SelectionOverlay].
/// {@endtemplate}
class TextMagnifierConfiguration { class TextMagnifierConfiguration {
/// Constructs a [TextMagnifierConfiguration] from parts. /// Constructs a [TextMagnifierConfiguration] from parts.
/// ///
/// If [magnifierBuilder] is null, a default [MagnifierBuilder] will be used /// If [magnifierBuilder] is null, a default [MagnifierBuilder] will be used
/// that never builds a magnifier. /// that does not build a magnifier.
const TextMagnifierConfiguration({ const TextMagnifierConfiguration({
MagnifierBuilder? magnifierBuilder, MagnifierBuilder? magnifierBuilder,
this.shouldDisplayHandlesInMagnifier = true this.shouldDisplayHandlesInMagnifier = true,
}) : _magnifierBuilder = magnifierBuilder; }) : _magnifierBuilder = magnifierBuilder;
/// The passed in [MagnifierBuilder]. /// The builder callback that creates the widget that renders the magnifier.
/// MagnifierBuilder get magnifierBuilder => _magnifierBuilder ?? _none;
/// This is nullable because [disabled] needs to be static const,
/// so that it can be used as a default parameter. If left null,
/// the [magnifierBuilder] getter will be a function that always returns
/// null.
final MagnifierBuilder? _magnifierBuilder; final MagnifierBuilder? _magnifierBuilder;
/// {@macro flutter.widgets.magnifier.MagnifierBuilder} static Widget? _none(
MagnifierBuilder get magnifierBuilder => _magnifierBuilder ?? (_, __, ___) => null; BuildContext context,
MagnifierController controller,
ValueNotifier<MagnifierInfo> magnifierInfo,
) => null;
/// Determines whether a magnifier should show the text editing handles or not. /// Whether a magnifier should show the text editing handles or not.
///
/// This flag is used by [SelectionOverlay.showMagnifier] to control the order
/// of layers in the rendering; specifically, whether to place the layer
/// containing the handles above or below the layer containing the magnifier
/// in the [Overlay].
final bool shouldDisplayHandlesInMagnifier; final bool shouldDisplayHandlesInMagnifier;
/// A constant for a [TextMagnifierConfiguration] that is disabled. /// A constant for a [TextMagnifierConfiguration] that is disabled, meaning it
/// /// never builds anything, regardless of platform.
/// In particular, this [TextMagnifierConfiguration] is considered disabled
/// because it never builds anything, regardless of platform.
static const TextMagnifierConfiguration disabled = TextMagnifierConfiguration(); static const TextMagnifierConfiguration disabled = TextMagnifierConfiguration();
} }
/// A controller for a magnifier.
///
/// [MagnifierController]'s main benefit over holding a raw [OverlayEntry] is that /// [MagnifierController]'s main benefit over holding a raw [OverlayEntry] is that
/// [MagnifierController] will handle logic around waiting for a magnifier to animate in or out. /// [MagnifierController] will handle logic around waiting for a magnifier to animate in or out.
/// ///
...@@ -156,11 +151,11 @@ class MagnifierController { ...@@ -156,11 +151,11 @@ class MagnifierController {
/// The magnifier's [OverlayEntry], if currently in the overlay. /// The magnifier's [OverlayEntry], if currently in the overlay.
/// ///
/// This is public in case other overlay entries need to be positioned /// This is exposed so that other overlay entries can be positioned above or
/// above or below this [overlayEntry]. Anything in the paint order after /// below this [overlayEntry]. Anything in the paint order after the
/// the [RawMagnifier] will not be displayed in the magnifier; this means that if it /// [RawMagnifier] in this [OverlayEntry] will not be displayed in the
/// is desired for an overlay entry to be displayed in the magnifier, /// magnifier; if it is desired for an overlay entry to be displayed in the
/// it _must_ be positioned below the magnifier. /// magnifier, it _must_ be positioned below the magnifier.
/// ///
/// {@tool snippet} /// {@tool snippet}
/// ```dart /// ```dart
...@@ -198,20 +193,22 @@ class MagnifierController { ...@@ -198,20 +193,22 @@ class MagnifierController {
/// ``` /// ```
/// {@end-tool} /// {@end-tool}
/// ///
/// A null check on [overlayEntry] will not suffice to check if a magnifier is in the /// To check if a magnifier is in the overlay, use [shown]. The [overlayEntry]
/// overlay or not; instead, you should check [shown]. This is because it is possible, /// field may be non-null even when the magnifier is not visible.
/// such as in cases where [hide] was called with `removeFromOverlay` false, that the magnifier
/// is not shown, but the entry is not null.
OverlayEntry? get overlayEntry => _overlayEntry; OverlayEntry? get overlayEntry => _overlayEntry;
OverlayEntry? _overlayEntry; OverlayEntry? _overlayEntry;
/// If the magnifier is shown or not. /// Whether the magnifier is currently being shown.
///
/// This is false when nothing is in the overlay, when the
/// [animationController] is in the [AnimationStatus.dismissed] state, or when
/// the [animationController] is animating out (i.e. in the
/// [AnimationStatus.reverse] state).
/// ///
/// [shown] is: /// It is true in the opposite cases, i.e. when the overlay is not empty, and
/// - false when nothing is in the overlay. /// either the [animationController] is null, in the
/// - false when [animationController] is [AnimationStatus.dismissed]. /// [AnimationStatus.completed] state, or in the [AnimationStatus.forward]
/// - false when [animationController] is animating out. /// state.
/// and true in all other circumstances.
bool get shown { bool get shown {
if (overlayEntry == null) { if (overlayEntry == null) {
return false; return false;
...@@ -225,17 +222,17 @@ class MagnifierController { ...@@ -225,17 +222,17 @@ class MagnifierController {
return true; return true;
} }
/// Shows the [RawMagnifier] that this controller controls. /// Displays the magnifier.
/// ///
/// Returns a future that completes when the magnifier is fully shown, i.e. done /// Returns a future that completes when the magnifier is fully shown, i.e. done
/// with its entry animation. /// with its entry animation.
/// ///
/// To control what overlays are shown in the magnifier, utilize [below]. See /// To control what overlays are shown in the magnifier, use `below`. See
/// [overlayEntry] for more details on how to utilize [below]. /// [overlayEntry] for more details on how to utilize `below`.
/// ///
/// If the magnifier already exists (i.e. [overlayEntry] != null), then [show] will /// If the magnifier already exists (i.e. [overlayEntry] != null), then [show]
/// override the old overlay and not play an exit animation. Consider awaiting [hide] /// will replace the old overlay without playing an exit animation. Consider
/// first, to guarantee /// awaiting [hide] first, to animate from the old magnifier to the new one.
Future<void> show({ Future<void> show({
required BuildContext context, required BuildContext context,
required WidgetBuilder builder, required WidgetBuilder builder,
......
...@@ -192,6 +192,7 @@ const double _kSelectableVerticalComparingThreshold = 3.0; ...@@ -192,6 +192,7 @@ const double _kSelectableVerticalComparingThreshold = 3.0;
/// ``` /// ```
/// ///
/// See also: /// See also:
///
/// * [SelectionArea], which creates a [SelectableRegion] with /// * [SelectionArea], which creates a [SelectableRegion] with
/// platform-adaptive selection controls. /// platform-adaptive selection controls.
/// * [SelectionHandler], which contains APIs to handle selection events from the /// * [SelectionHandler], which contains APIs to handle selection events from the
...@@ -216,13 +217,13 @@ class SelectableRegion extends StatefulWidget { ...@@ -216,13 +217,13 @@ class SelectableRegion extends StatefulWidget {
this.onSelectionChanged, this.onSelectionChanged,
}); });
/// {@macro flutter.widgets.magnifier.TextMagnifierConfiguration.intro} /// The configuration for the magnifier used with selections in this region.
///
/// {@macro flutter.widgets.magnifier.intro}
/// ///
/// By default, [SelectableRegion]'s [TextMagnifierConfiguration] is disabled. /// By default, [SelectableRegion]'s [TextMagnifierConfiguration] is disabled.
/// For a version of [SelectableRegion] that adapts automatically to the
/// current platform, consider [SelectionArea].
/// ///
/// {@macro flutter.widgets.magnifier.TextMagnifierConfiguration.details} /// {@macro flutter.widgets.magnifier.intro}
final TextMagnifierConfiguration magnifierConfiguration; final TextMagnifierConfiguration magnifierConfiguration;
/// {@macro flutter.widgets.Focus.focusNode} /// {@macro flutter.widgets.Focus.focusNode}
......
...@@ -989,19 +989,18 @@ class SelectionOverlay { ...@@ -989,19 +989,18 @@ class SelectionOverlay {
final ValueNotifier<MagnifierInfo> _magnifierInfo = final ValueNotifier<MagnifierInfo> _magnifierInfo =
ValueNotifier<MagnifierInfo>(MagnifierInfo.empty); ValueNotifier<MagnifierInfo>(MagnifierInfo.empty);
/// [MagnifierController.show] and [MagnifierController.hide] should not be called directly, except // [MagnifierController.show] and [MagnifierController.hide] should not be
/// from inside [showMagnifier] and [hideMagnifier]. If it is desired to show or hide the magnifier, // called directly, except from inside [showMagnifier] and [hideMagnifier]. If
/// call [showMagnifier] or [hideMagnifier]. This is because the magnifier needs to orchestrate // it is desired to show or hide the magnifier, call [showMagnifier] or
/// with other properties in [SelectionOverlay]. // [hideMagnifier]. This is because the magnifier needs to orchestrate with
// other properties in [SelectionOverlay].
final MagnifierController _magnifierController = MagnifierController(); final MagnifierController _magnifierController = MagnifierController();
/// {@macro flutter.widgets.magnifier.TextMagnifierConfiguration.intro} /// The configuration for the magnifier.
///
/// {@macro flutter.widgets.magnifier.intro}
/// ///
/// By default, [SelectionOverlay]'s [TextMagnifierConfiguration] is disabled. /// By default, [SelectionOverlay]'s [TextMagnifierConfiguration] is disabled.
/// ///
/// {@macro flutter.widgets.magnifier.TextMagnifierConfiguration.details} /// {@macro flutter.widgets.magnifier.intro}
final TextMagnifierConfiguration magnifierConfiguration; final TextMagnifierConfiguration magnifierConfiguration;
/// {@template flutter.widgets.SelectionOverlay.toolbarIsVisible} /// {@template flutter.widgets.SelectionOverlay.toolbarIsVisible}
...@@ -1047,11 +1046,12 @@ class SelectionOverlay { ...@@ -1047,11 +1046,12 @@ class SelectionOverlay {
} }
_magnifierController.show( _magnifierController.show(
context: context, context: context,
below: magnifierConfiguration.shouldDisplayHandlesInMagnifier below: magnifierConfiguration.shouldDisplayHandlesInMagnifier
? null ? null
: _handles?.start, : _handles?.start,
builder: (_) => builtMagnifier); builder: (_) => builtMagnifier,
);
} }
/// {@template flutter.widgets.SelectionOverlay.hideMagnifier} /// {@template flutter.widgets.SelectionOverlay.hideMagnifier}
......
...@@ -6,9 +6,12 @@ import 'dart:math' as math; ...@@ -6,9 +6,12 @@ import 'dart:math' as math;
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
/// Positions the toolbar above [anchorAbove] if it fits, or otherwise below /// A [SingleChildLayoutDelegate] for use with [CustomSingleChildLayout] that
/// positions its child above [anchorAbove] if it fits, or otherwise below
/// [anchorBelow]. /// [anchorBelow].
/// ///
/// Primarily intended for use with toolbars or context menus.
///
/// See also: /// See also:
/// ///
/// * [TextSelectionToolbar], which uses this to position itself. /// * [TextSelectionToolbar], which uses this to position itself.
...@@ -16,6 +19,8 @@ import 'package:flutter/rendering.dart'; ...@@ -16,6 +19,8 @@ import 'package:flutter/rendering.dart';
/// itself. /// itself.
class TextSelectionToolbarLayoutDelegate extends SingleChildLayoutDelegate { class TextSelectionToolbarLayoutDelegate extends SingleChildLayoutDelegate {
/// Creates an instance of TextSelectionToolbarLayoutDelegate. /// Creates an instance of TextSelectionToolbarLayoutDelegate.
///
/// The [fitsAbove] parameter is optional; if omitted, it will be calculated.
TextSelectionToolbarLayoutDelegate({ TextSelectionToolbarLayoutDelegate({
required this.anchorAbove, required this.anchorAbove,
required this.anchorBelow, required this.anchorBelow,
...@@ -41,8 +46,8 @@ class TextSelectionToolbarLayoutDelegate extends SingleChildLayoutDelegate { ...@@ -41,8 +46,8 @@ class TextSelectionToolbarLayoutDelegate extends SingleChildLayoutDelegate {
/// If not provided, it will be calculated. /// If not provided, it will be calculated.
final bool? fitsAbove; final bool? fitsAbove;
/// Return the value that centers width as closely as possible to position /// Return the distance from zero that centers `width` as closely as possible
/// while fitting inside of min and max. /// to `position` from zero while fitting between zero and `max`.
static double centerOn(double position, double width, double max) { static double centerOn(double position, double width, double max) {
// If it overflows on the left, put it as far left as possible. // If it overflows on the left, put it as far left as possible.
if (position - width / 2.0 < 0.0) { if (position - width / 2.0 < 0.0) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment