mirror of
https://github.com/flutter/flutter
synced 2024-08-24 18:36:03 +00:00
Various improvements to text-editing-related documentation. (#142561)
This commit is contained in:
parent
4becae25b0
commit
9fccb32a58
|
@ -763,16 +763,15 @@ class CupertinoTextField extends StatefulWidget {
|
|||
);
|
||||
}
|
||||
|
||||
/// {@macro flutter.widgets.magnifier.TextMagnifierConfiguration.intro}
|
||||
/// Configuration for the text field magnifier.
|
||||
///
|
||||
/// By default (when this property is set to null), a [CupertinoTextMagnifier]
|
||||
/// is used on mobile platforms, and nothing on desktop platforms. To suppress
|
||||
/// the magnifier on all platforms, consider passing
|
||||
/// [TextMagnifierConfiguration.disabled] explicitly.
|
||||
///
|
||||
/// {@macro flutter.widgets.magnifier.intro}
|
||||
///
|
||||
/// {@macro flutter.widgets.magnifier.TextMagnifierConfiguration.details}
|
||||
///
|
||||
/// By default, builds a [CupertinoTextMagnifier] on iOS and Android nothing on all other
|
||||
/// platforms. If it is desired to suppress the magnifier, consider passing
|
||||
/// [TextMagnifierConfiguration.disabled].
|
||||
///
|
||||
/// {@tool dartpad}
|
||||
/// This sample demonstrates how to customize the magnifier that this text field uses.
|
||||
///
|
||||
|
|
|
@ -502,15 +502,13 @@ class SelectableText extends StatefulWidget {
|
|||
);
|
||||
}
|
||||
|
||||
/// {@macro flutter.widgets.magnifier.TextMagnifierConfiguration.intro}
|
||||
///
|
||||
/// {@macro flutter.widgets.magnifier.intro}
|
||||
///
|
||||
/// {@macro flutter.widgets.magnifier.TextMagnifierConfiguration.details}
|
||||
/// The configuration for the magnifier used when the text is selected.
|
||||
///
|
||||
/// By default, builds a [CupertinoTextMagnifier] on iOS and [TextMagnifier]
|
||||
/// on Android, and builds nothing on all other platforms. If it is desired to
|
||||
/// suppress the magnifier, consider passing [TextMagnifierConfiguration.disabled].
|
||||
/// on Android, and builds nothing on all other platforms. To suppress the
|
||||
/// magnifier, consider passing [TextMagnifierConfiguration.disabled].
|
||||
///
|
||||
/// {@macro flutter.widgets.magnifier.intro}
|
||||
final TextMagnifierConfiguration? magnifierConfiguration;
|
||||
|
||||
@override
|
||||
|
|
|
@ -33,6 +33,7 @@ import 'theme.dart';
|
|||
/// {@end-tool}
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [SelectableRegion], which provides an overview of the selection system.
|
||||
class SelectionArea extends StatefulWidget {
|
||||
/// Creates a [SelectionArea].
|
||||
|
@ -48,15 +49,13 @@ class SelectionArea extends StatefulWidget {
|
|||
required this.child,
|
||||
});
|
||||
|
||||
/// {@macro flutter.widgets.magnifier.TextMagnifierConfiguration.intro}
|
||||
///
|
||||
/// {@macro flutter.widgets.magnifier.intro}
|
||||
///
|
||||
/// {@macro flutter.widgets.magnifier.TextMagnifierConfiguration.details}
|
||||
/// The configuration for the magnifier in the selection region.
|
||||
///
|
||||
/// By default, builds a [CupertinoTextMagnifier] on iOS and [TextMagnifier]
|
||||
/// on Android, and builds nothing on all other platforms. If it is desired to
|
||||
/// suppress the magnifier, consider passing [TextMagnifierConfiguration.disabled].
|
||||
/// on Android, and builds nothing on all other platforms. To suppress the
|
||||
/// magnifier, consider passing [TextMagnifierConfiguration.disabled].
|
||||
///
|
||||
/// {@macro flutter.widgets.magnifier.intro}
|
||||
final TextMagnifierConfiguration? magnifierConfiguration;
|
||||
|
||||
/// {@macro flutter.widgets.Focus.focusNode}
|
||||
|
|
|
@ -349,15 +349,13 @@ class TextField extends StatefulWidget {
|
|||
keyboardType = keyboardType ?? (maxLines == 1 ? TextInputType.text : TextInputType.multiline),
|
||||
enableInteractiveSelection = enableInteractiveSelection ?? (!readOnly || !obscureText);
|
||||
|
||||
/// {@macro flutter.widgets.magnifier.TextMagnifierConfiguration.intro}
|
||||
///
|
||||
/// {@macro flutter.widgets.magnifier.intro}
|
||||
///
|
||||
/// {@macro flutter.widgets.magnifier.TextMagnifierConfiguration.details}
|
||||
/// The configuration for the magnifier of this text field.
|
||||
///
|
||||
/// By default, builds a [CupertinoTextMagnifier] on iOS and [TextMagnifier]
|
||||
/// on Android, and builds nothing on all other platforms. If it is desired to
|
||||
/// suppress the magnifier, consider passing [TextMagnifierConfiguration.disabled].
|
||||
/// on Android, and builds nothing on all other platforms. To suppress the
|
||||
/// magnifier, consider passing [TextMagnifierConfiguration.disabled].
|
||||
///
|
||||
/// {@macro flutter.widgets.magnifier.intro}
|
||||
///
|
||||
/// {@tool dartpad}
|
||||
/// This sample demonstrates how to customize the magnifier that this text field uses.
|
||||
|
|
|
@ -1799,11 +1799,28 @@ class EditableText extends StatefulWidget {
|
|||
/// {@template flutter.widgets.EditableText.contextMenuBuilder}
|
||||
/// Builds the text selection toolbar when requested by the user.
|
||||
///
|
||||
/// `primaryAnchor` is the desired anchor position for the context menu, while
|
||||
/// `secondaryAnchor` is the fallback location if the menu doesn't fit.
|
||||
/// The context menu is built when [EditableTextState.showToolbar] is called,
|
||||
/// 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
|
||||
/// this widget.
|
||||
/// If no callback is provided, no context menu will be shown.
|
||||
///
|
||||
/// 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
|
||||
/// that does not mix in [TextSelectionHandleControls], [contextMenuBuilder]
|
||||
|
@ -1834,8 +1851,6 @@ class EditableText extends StatefulWidget {
|
|||
/// * [BrowserContextMenu], which allows the browser's context menu on web
|
||||
/// to be disabled and Flutter-rendered context menus to appear.
|
||||
/// {@endtemplate}
|
||||
///
|
||||
/// If not provided, no context menu will be shown.
|
||||
final EditableTextContextMenuBuilder? contextMenuBuilder;
|
||||
|
||||
/// {@template flutter.widgets.EditableText.spellCheckConfiguration}
|
||||
|
@ -1852,11 +1867,10 @@ class EditableText extends StatefulWidget {
|
|||
/// {@endtemplate}
|
||||
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.TextMagnifierConfiguration.details}
|
||||
final TextMagnifierConfiguration magnifierConfiguration;
|
||||
|
||||
bool get _userSelectionEnabled => enableInteractiveSelection && (!readOnly || !obscureText);
|
||||
|
|
|
@ -15,19 +15,17 @@ import 'inherited_theme.dart';
|
|||
import 'navigator.dart';
|
||||
import 'overlay.dart';
|
||||
|
||||
/// {@template flutter.widgets.magnifier.MagnifierBuilder}
|
||||
/// Signature for a builder that builds a [Widget] with a [MagnifierController].
|
||||
///
|
||||
/// Consuming [MagnifierController] or [ValueNotifier]<[MagnifierInfo]> is not
|
||||
/// 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}
|
||||
/// The builder is called exactly once per magnifier.
|
||||
///
|
||||
/// 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
|
||||
/// magnifier.
|
||||
/// The `magnifierInfo` parameter is updated with new [MagnifierInfo] instances
|
||||
/// during the lifetime of the built magnifier, e.g. as the user moves their
|
||||
/// finger around the text field.
|
||||
typedef MagnifierBuilder = Widget? Function(
|
||||
BuildContext context,
|
||||
MagnifierController controller,
|
||||
|
@ -57,9 +55,9 @@ class MagnifierInfo {
|
|||
/// The offset of the gesture position that the magnifier should be shown at.
|
||||
final Offset globalGesturePosition;
|
||||
|
||||
/// The rect of the current line the magnifier should be shown at,
|
||||
/// without taking into account any padding of the field; only the position
|
||||
/// of the first and last character.
|
||||
/// The rect of the current line the magnifier should be shown at, without
|
||||
/// taking into account any padding of the field; only the position of the
|
||||
/// first and last character.
|
||||
final Rect currentLineBoundaries;
|
||||
|
||||
/// The rect of the handle that the magnifier should follow.
|
||||
|
@ -89,48 +87,45 @@ class MagnifierInfo {
|
|||
);
|
||||
}
|
||||
|
||||
/// {@template flutter.widgets.magnifier.TextMagnifierConfiguration.intro}
|
||||
/// A configuration object for a magnifier.
|
||||
/// {@endtemplate}
|
||||
/// A configuration object for a magnifier (e.g. in a text field).
|
||||
///
|
||||
/// {@macro flutter.widgets.magnifier.intro}
|
||||
///
|
||||
/// {@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}
|
||||
/// In general, most features of the magnifier can be configured by controlling
|
||||
/// the widgets built by the [magnifierBuilder].
|
||||
class TextMagnifierConfiguration {
|
||||
/// Constructs a [TextMagnifierConfiguration] from parts.
|
||||
///
|
||||
/// If [magnifierBuilder] is null, a default [MagnifierBuilder] will be used
|
||||
/// that never builds a magnifier.
|
||||
/// that does not build a magnifier.
|
||||
const TextMagnifierConfiguration({
|
||||
MagnifierBuilder? magnifierBuilder,
|
||||
this.shouldDisplayHandlesInMagnifier = true
|
||||
this.shouldDisplayHandlesInMagnifier = true,
|
||||
}) : _magnifierBuilder = magnifierBuilder;
|
||||
|
||||
/// The passed in [MagnifierBuilder].
|
||||
///
|
||||
/// 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.
|
||||
/// The builder callback that creates the widget that renders the magnifier.
|
||||
MagnifierBuilder get magnifierBuilder => _magnifierBuilder ?? _none;
|
||||
final MagnifierBuilder? _magnifierBuilder;
|
||||
|
||||
/// {@macro flutter.widgets.magnifier.MagnifierBuilder}
|
||||
MagnifierBuilder get magnifierBuilder => _magnifierBuilder ?? (_, __, ___) => null;
|
||||
static Widget? _none(
|
||||
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;
|
||||
|
||||
/// A constant for a [TextMagnifierConfiguration] that is disabled.
|
||||
///
|
||||
/// In particular, this [TextMagnifierConfiguration] is considered disabled
|
||||
/// because it never builds anything, regardless of platform.
|
||||
/// A constant for a [TextMagnifierConfiguration] that is disabled, meaning it
|
||||
/// never builds anything, regardless of platform.
|
||||
static const TextMagnifierConfiguration disabled = TextMagnifierConfiguration();
|
||||
}
|
||||
|
||||
/// A controller for a magnifier.
|
||||
///
|
||||
/// [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.
|
||||
///
|
||||
|
@ -156,11 +151,11 @@ class MagnifierController {
|
|||
|
||||
/// The magnifier's [OverlayEntry], if currently in the overlay.
|
||||
///
|
||||
/// This is public in case other overlay entries need to be positioned
|
||||
/// above or below this [overlayEntry]. Anything in the paint order after
|
||||
/// the [RawMagnifier] will not be displayed in the magnifier; this means that if it
|
||||
/// is desired for an overlay entry to be displayed in the magnifier,
|
||||
/// it _must_ be positioned below the magnifier.
|
||||
/// This is exposed so that other overlay entries can be positioned above or
|
||||
/// below this [overlayEntry]. Anything in the paint order after the
|
||||
/// [RawMagnifier] in this [OverlayEntry] will not be displayed in the
|
||||
/// magnifier; if it is desired for an overlay entry to be displayed in the
|
||||
/// magnifier, it _must_ be positioned below the magnifier.
|
||||
///
|
||||
/// {@tool snippet}
|
||||
/// ```dart
|
||||
|
@ -198,20 +193,22 @@ class MagnifierController {
|
|||
/// ```
|
||||
/// {@end-tool}
|
||||
///
|
||||
/// A null check on [overlayEntry] will not suffice to check if a magnifier is in the
|
||||
/// overlay or not; instead, you should check [shown]. This is because it is possible,
|
||||
/// such as in cases where [hide] was called with `removeFromOverlay` false, that the magnifier
|
||||
/// is not shown, but the entry is not null.
|
||||
/// To check if a magnifier is in the overlay, use [shown]. The [overlayEntry]
|
||||
/// field may be non-null even when the magnifier is not visible.
|
||||
OverlayEntry? get overlayEntry => _overlayEntry;
|
||||
OverlayEntry? _overlayEntry;
|
||||
|
||||
/// If the magnifier is shown or not.
|
||||
/// Whether the magnifier is currently being shown.
|
||||
///
|
||||
/// [shown] is:
|
||||
/// - false when nothing is in the overlay.
|
||||
/// - false when [animationController] is [AnimationStatus.dismissed].
|
||||
/// - false when [animationController] is animating out.
|
||||
/// and true in all other circumstances.
|
||||
/// 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).
|
||||
///
|
||||
/// It is true in the opposite cases, i.e. when the overlay is not empty, and
|
||||
/// either the [animationController] is null, in the
|
||||
/// [AnimationStatus.completed] state, or in the [AnimationStatus.forward]
|
||||
/// state.
|
||||
bool get shown {
|
||||
if (overlayEntry == null) {
|
||||
return false;
|
||||
|
@ -225,17 +222,17 @@ class MagnifierController {
|
|||
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
|
||||
/// with its entry animation.
|
||||
///
|
||||
/// To control what overlays are shown in the magnifier, utilize [below]. See
|
||||
/// [overlayEntry] for more details on how to utilize [below].
|
||||
/// To control what overlays are shown in the magnifier, use `below`. See
|
||||
/// [overlayEntry] for more details on how to utilize `below`.
|
||||
///
|
||||
/// If the magnifier already exists (i.e. [overlayEntry] != null), then [show] will
|
||||
/// override the old overlay and not play an exit animation. Consider awaiting [hide]
|
||||
/// first, to guarantee
|
||||
/// If the magnifier already exists (i.e. [overlayEntry] != null), then [show]
|
||||
/// will replace the old overlay without playing an exit animation. Consider
|
||||
/// awaiting [hide] first, to animate from the old magnifier to the new one.
|
||||
Future<void> show({
|
||||
required BuildContext context,
|
||||
required WidgetBuilder builder,
|
||||
|
|
|
@ -192,6 +192,7 @@ const double _kSelectableVerticalComparingThreshold = 3.0;
|
|||
/// ```
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [SelectionArea], which creates a [SelectableRegion] with
|
||||
/// platform-adaptive selection controls.
|
||||
/// * [SelectionHandler], which contains APIs to handle selection events from the
|
||||
|
@ -216,13 +217,13 @@ class SelectableRegion extends StatefulWidget {
|
|||
this.onSelectionChanged,
|
||||
});
|
||||
|
||||
/// {@macro flutter.widgets.magnifier.TextMagnifierConfiguration.intro}
|
||||
///
|
||||
/// {@macro flutter.widgets.magnifier.intro}
|
||||
/// The configuration for the magnifier used with selections in this region.
|
||||
///
|
||||
/// 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;
|
||||
|
||||
/// {@macro flutter.widgets.Focus.focusNode}
|
||||
|
|
|
@ -989,19 +989,18 @@ class SelectionOverlay {
|
|||
final ValueNotifier<MagnifierInfo> _magnifierInfo =
|
||||
ValueNotifier<MagnifierInfo>(MagnifierInfo.empty);
|
||||
|
||||
/// [MagnifierController.show] and [MagnifierController.hide] should not be called directly, except
|
||||
/// from inside [showMagnifier] and [hideMagnifier]. If it is desired to show or hide the magnifier,
|
||||
/// call [showMagnifier] or [hideMagnifier]. This is because the magnifier needs to orchestrate
|
||||
/// with other properties in [SelectionOverlay].
|
||||
// [MagnifierController.show] and [MagnifierController.hide] should not be
|
||||
// called directly, except from inside [showMagnifier] and [hideMagnifier]. If
|
||||
// it is desired to show or hide the magnifier, call [showMagnifier] or
|
||||
// [hideMagnifier]. This is because the magnifier needs to orchestrate with
|
||||
// other properties in [SelectionOverlay].
|
||||
final MagnifierController _magnifierController = MagnifierController();
|
||||
|
||||
/// {@macro flutter.widgets.magnifier.TextMagnifierConfiguration.intro}
|
||||
///
|
||||
/// {@macro flutter.widgets.magnifier.intro}
|
||||
/// The configuration for the magnifier.
|
||||
///
|
||||
/// By default, [SelectionOverlay]'s [TextMagnifierConfiguration] is disabled.
|
||||
///
|
||||
/// {@macro flutter.widgets.magnifier.TextMagnifierConfiguration.details}
|
||||
/// {@macro flutter.widgets.magnifier.intro}
|
||||
final TextMagnifierConfiguration magnifierConfiguration;
|
||||
|
||||
/// {@template flutter.widgets.SelectionOverlay.toolbarIsVisible}
|
||||
|
@ -1047,11 +1046,12 @@ class SelectionOverlay {
|
|||
}
|
||||
|
||||
_magnifierController.show(
|
||||
context: context,
|
||||
below: magnifierConfiguration.shouldDisplayHandlesInMagnifier
|
||||
? null
|
||||
: _handles?.start,
|
||||
builder: (_) => builtMagnifier);
|
||||
context: context,
|
||||
below: magnifierConfiguration.shouldDisplayHandlesInMagnifier
|
||||
? null
|
||||
: _handles?.start,
|
||||
builder: (_) => builtMagnifier,
|
||||
);
|
||||
}
|
||||
|
||||
/// {@template flutter.widgets.SelectionOverlay.hideMagnifier}
|
||||
|
|
|
@ -6,9 +6,12 @@ import 'dart:math' as math;
|
|||
|
||||
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].
|
||||
///
|
||||
/// Primarily intended for use with toolbars or context menus.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [TextSelectionToolbar], which uses this to position itself.
|
||||
|
@ -16,6 +19,8 @@ import 'package:flutter/rendering.dart';
|
|||
/// itself.
|
||||
class TextSelectionToolbarLayoutDelegate extends SingleChildLayoutDelegate {
|
||||
/// Creates an instance of TextSelectionToolbarLayoutDelegate.
|
||||
///
|
||||
/// The [fitsAbove] parameter is optional; if omitted, it will be calculated.
|
||||
TextSelectionToolbarLayoutDelegate({
|
||||
required this.anchorAbove,
|
||||
required this.anchorBelow,
|
||||
|
@ -41,8 +46,8 @@ class TextSelectionToolbarLayoutDelegate extends SingleChildLayoutDelegate {
|
|||
/// If not provided, it will be calculated.
|
||||
final bool? fitsAbove;
|
||||
|
||||
/// Return the value that centers width as closely as possible to position
|
||||
/// while fitting inside of min and max.
|
||||
/// Return the distance from zero that centers `width` as closely as possible
|
||||
/// to `position` from zero while fitting between zero and `max`.
|
||||
static double centerOn(double position, double width, double max) {
|
||||
// If it overflows on the left, put it as far left as possible.
|
||||
if (position - width / 2.0 < 0.0) {
|
||||
|
|
Loading…
Reference in a new issue