123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599 |
- import 'dart:ui' as ui show BoxHeightStyle, BoxWidthStyle;
- import 'package:flutter/gestures.dart';
- import 'package:flutter/material.dart';
- import 'package:flutter/services.dart';
- class PasswordTextField extends StatefulWidget {
- const PasswordTextField({
- super.key,
- this.visibleIcon = Icons.remove_red_eye_outlined,
- this.inVisibleIcon = Icons.remove_red_eye_outlined,
- this.initialObscurity = false,
- this.controller,
- this.focusNode,
- this.undoController,
- this.decoration = const InputDecoration(),
- this.keyboardType,
- this.textInputAction,
- this.textCapitalization = TextCapitalization.none,
- this.style,
- this.strutStyle,
- this.textAlign = TextAlign.start,
- this.textAlignVertical,
- this.textDirection,
- this.readOnly = false,
- this.showCursor,
- this.autofocus = false,
- this.obscuringCharacter = '•',
- this.autocorrect = true,
- this.enableSuggestions = true,
- this.maxLines = 1,
- this.minLines,
- this.expands = false,
- this.maxLength,
- this.maxLengthEnforcement,
- this.onChanged,
- this.onEditingComplete,
- this.onSubmitted,
- this.onAppPrivateCommand,
- this.inputFormatters,
- this.enabled,
- this.cursorWidth = 2.0,
- this.cursorHeight,
- this.cursorRadius,
- this.cursorOpacityAnimates,
- this.cursorColor,
- this.selectionHeightStyle = ui.BoxHeightStyle.tight,
- this.selectionWidthStyle = ui.BoxWidthStyle.tight,
- this.keyboardAppearance,
- this.scrollPadding = const EdgeInsets.all(20.0),
- this.dragStartBehavior = DragStartBehavior.start,
- this.enableInteractiveSelection = true,
- this.selectionControls,
- this.onTap,
- this.onTapOutside,
- this.mouseCursor,
- this.buildCounter,
- this.scrollController,
- this.scrollPhysics,
- this.autofillHints = const <String>[],
- this.contentInsertionConfiguration,
- this.clipBehavior = Clip.hardEdge,
- this.restorationId,
- this.scribbleEnabled = true,
- this.enableIMEPersonalizedLearning = true,
- this.contextMenuBuilder,
- this.canRequestFocus = true,
- this.spellCheckConfiguration,
- this.magnifierConfiguration,
- });
- /// Displaying toggle icon(show).
- ///
- /// Defaults is [Icons.visibility].
- final IconData visibleIcon;
- /// Displaying toggle icon(hide).
- ///
- /// Defaults is [Icons.visibility_off].
- final IconData inVisibleIcon;
- /// The obscure feature is enabled by default.
- ///
- /// Default is [false].
- final bool initialObscurity;
- /// {@macro flutter.widgets.magnifier.TextMagnifierConfiguration.intro}
- ///
- /// {@macro flutter.widgets.magnifier.intro}
- ///
- /// {@macro flutter.widgets.magnifier.TextMagnifierConfiguration.details}
- ///
- /// 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].
- ///
- /// {@tool dartpad}
- /// This sample demonstrates how to customize the magnifier that this text field uses.
- ///
- /// ** See code in examples/api/lib/widgets/text_magnifier/text_magnifier.0.dart **
- /// {@end-tool}
- final TextMagnifierConfiguration? magnifierConfiguration;
- /// Controls the text being edited.
- ///
- /// If null, this widget will create its own [TextEditingController].
- final TextEditingController? controller;
- /// Defines the keyboard focus for this widget.
- ///
- /// The [focusNode] is a long-lived object that's typically managed by a
- /// [StatefulWidget] parent. See [FocusNode] for more information.
- ///
- /// To give the keyboard focus to this widget, provide a [focusNode] and then
- /// use the current [FocusScope] to request the focus:
- ///
- /// ```dart
- /// FocusScope.of(context).requestFocus(myFocusNode);
- /// ```
- ///
- /// This happens automatically when the widget is tapped.
- ///
- /// To be notified when the widget gains or loses the focus, add a listener
- /// to the [focusNode]:
- ///
- /// ```dart
- /// myFocusNode.addListener(() { print(myFocusNode.hasFocus); });
- /// ```
- ///
- /// If null, this widget will create its own [FocusNode].
- ///
- /// ## Keyboard
- ///
- /// Requesting the focus will typically cause the keyboard to be shown
- /// if it's not showing already.
- ///
- /// On Android, the user can hide the keyboard - without changing the focus -
- /// with the system back button. They can restore the keyboard's visibility
- /// by tapping on a text field. The user might hide the keyboard and
- /// switch to a physical keyboard, or they might just need to get it
- /// out of the way for a moment, to expose something it's
- /// obscuring. In this case requesting the focus again will not
- /// cause the focus to change, and will not make the keyboard visible.
- ///
- /// This widget builds an [EditableText] and will ensure that the keyboard is
- /// showing when it is tapped by calling [EditableTextState.requestKeyboard()].
- final FocusNode? focusNode;
- /// The decoration to show around the text field.
- ///
- /// By default, draws a horizontal line under the text field but can be
- /// configured to show an icon, label, hint text, and error text.
- ///
- /// Specify null to remove the decoration entirely (including the
- /// extra padding introduced by the decoration to save space for the labels).
- final InputDecoration decoration;
- /// {@macro flutter.widgets.editableText.keyboardType}
- final TextInputType? keyboardType;
- /// The type of action button to use for the keyboard.
- ///
- /// Defaults to [TextInputAction.newline] if [keyboardType] is
- /// [TextInputType.multiline] and [TextInputAction.done] otherwise.
- final TextInputAction? textInputAction;
- /// {@macro flutter.widgets.editableText.textCapitalization}
- final TextCapitalization textCapitalization;
- /// The style to use for the text being edited.
- ///
- /// This text style is also used as the base style for the [decoration].
- ///
- /// If null, defaults to the `titleMedium` text style from the current [Theme].
- final TextStyle? style;
- /// {@macro flutter.widgets.editableText.strutStyle}
- final StrutStyle? strutStyle;
- /// {@macro flutter.widgets.editableText.textAlign}
- final TextAlign textAlign;
- /// {@macro flutter.material.InputDecorator.textAlignVertical}
- final TextAlignVertical? textAlignVertical;
- /// {@macro flutter.widgets.editableText.textDirection}
- final TextDirection? textDirection;
- /// {@macro flutter.widgets.editableText.autofocus}
- final bool autofocus;
- /// {@macro flutter.widgets.editableText.obscuringCharacter}
- final String obscuringCharacter;
- /// {@macro flutter.widgets.editableText.autocorrect}
- final bool autocorrect;
- /// {@macro flutter.services.TextInputConfiguration.enableSuggestions}
- final bool enableSuggestions;
- /// {@macro flutter.widgets.editableText.maxLines}
- /// * [expands], which determines whether the field should fill the height of
- /// its parent.
- final int? maxLines;
- /// {@macro flutter.widgets.editableText.minLines}
- /// * [expands], which determines whether the field should fill the height of
- /// its parent.
- final int? minLines;
- /// {@macro flutter.widgets.editableText.expands}
- final bool expands;
- /// {@macro flutter.widgets.editableText.readOnly}
- final bool readOnly;
- /// {@macro flutter.widgets.editableText.showCursor}
- final bool? showCursor;
- /// The maximum number of characters (Unicode grapheme clusters) to allow in
- /// the text field.
- ///
- /// If set, a character counter will be displayed below the
- /// field showing how many characters have been entered. If set to a number
- /// greater than 0, it will also display the maximum number allowed. If set
- /// to [TextField.noMaxLength] then only the current character count is displayed.
- ///
- /// After [maxLength] characters have been input, additional input
- /// is ignored, unless [maxLengthEnforcement] is set to
- /// [MaxLengthEnforcement.none].
- ///
- /// The text field enforces the length with a [LengthLimitingTextInputFormatter],
- /// which is evaluated after the supplied [inputFormatters], if any.
- ///
- /// This value must be either null, [TextField.noMaxLength], or greater than 0.
- /// If null (the default) then there is no limit to the number of characters
- /// that can be entered. If set to [TextField.noMaxLength], then no limit will
- /// be enforced, but the number of characters entered will still be displayed.
- ///
- /// Whitespace characters (e.g. newline, space, tab) are included in the
- /// character count.
- ///
- /// If [maxLengthEnforcement] is [MaxLengthEnforcement.none], then more than
- /// [maxLength] characters may be entered, but the error counter and divider
- /// will switch to the [decoration]'s [InputDecoration.errorStyle] when the
- /// limit is exceeded.
- ///
- /// {@macro flutter.services.lengthLimitingTextInputFormatter.maxLength}
- final int? maxLength;
- /// Determines how the [maxLength] limit should be enforced.
- ///
- /// {@macro flutter.services.textFormatter.effectiveMaxLengthEnforcement}
- ///
- /// {@macro flutter.services.textFormatter.maxLengthEnforcement}
- final MaxLengthEnforcement? maxLengthEnforcement;
- /// {@macro flutter.widgets.editableText.onChanged}
- ///
- /// See also:
- ///
- /// * [inputFormatters], which are called before [onChanged]
- /// runs and can validate and change ("format") the input value.
- /// * [onEditingComplete], [onSubmitted]:
- /// which are more specialized input change notifications.
- final ValueChanged<String>? onChanged;
- /// {@macro flutter.widgets.editableText.onEditingComplete}
- final VoidCallback? onEditingComplete;
- /// {@macro flutter.widgets.editableText.onSubmitted}
- ///
- /// See also:
- ///
- /// * [TextInputAction.next] and [TextInputAction.previous], which
- /// automatically shift the focus to the next/previous focusable item when
- /// the user is done editing.
- final ValueChanged<String>? onSubmitted;
- /// {@macro flutter.widgets.editableText.onAppPrivateCommand}
- final AppPrivateCommandCallback? onAppPrivateCommand;
- /// {@macro flutter.widgets.editableText.inputFormatters}
- final List<TextInputFormatter>? inputFormatters;
- /// If false the text field is "disabled": it ignores taps and its
- /// [decoration] is rendered in grey.
- ///
- /// If non-null this property overrides the [decoration]'s
- /// [InputDecoration.enabled] property.
- final bool? enabled;
- /// {@macro flutter.widgets.editableText.cursorWidth}
- final double cursorWidth;
- /// {@macro flutter.widgets.editableText.cursorHeight}
- final double? cursorHeight;
- /// {@macro flutter.widgets.editableText.cursorRadius}
- final Radius? cursorRadius;
- /// {@macro flutter.widgets.editableText.cursorOpacityAnimates}
- final bool? cursorOpacityAnimates;
- /// The color of the cursor.
- ///
- /// The cursor indicates the current location of text insertion point in
- /// the field.
- ///
- /// If this is null it will default to the ambient
- /// [DefaultSelectionStyle.cursorColor]. If that is null, and the
- /// [ThemeData.platform] is [TargetPlatform.iOS] or [TargetPlatform.macOS]
- /// it will use [CupertinoThemeData.primaryColor]. Otherwise it will use
- /// the value of [ColorScheme.primary] of [ThemeData.colorScheme].
- final Color? cursorColor;
- /// Controls how tall the selection highlight boxes are computed to be.
- ///
- /// See [ui.BoxHeightStyle] for details on available styles.
- final ui.BoxHeightStyle selectionHeightStyle;
- /// Controls how wide the selection highlight boxes are computed to be.
- ///
- /// See [ui.BoxWidthStyle] for details on available styles.
- final ui.BoxWidthStyle selectionWidthStyle;
- /// The appearance of the keyboard.
- ///
- /// This setting is only honored on iOS devices.
- ///
- /// If unset, defaults to [ThemeData.brightness].
- final Brightness? keyboardAppearance;
- /// {@macro flutter.widgets.editableText.scrollPadding}
- final EdgeInsets scrollPadding;
- /// {@macro flutter.widgets.editableText.enableInteractiveSelection}
- final bool enableInteractiveSelection;
- /// {@macro flutter.widgets.editableText.selectionControls}
- final TextSelectionControls? selectionControls;
- /// {@macro flutter.widgets.scrollable.dragStartBehavior}
- final DragStartBehavior dragStartBehavior;
- /// {@macro flutter.widgets.editableText.selectionEnabled}
- bool get selectionEnabled => enableInteractiveSelection;
- /// {@template flutter.material.textfield.onTap}
- /// Called for each distinct tap except for every second tap of a double tap.
- ///
- /// The text field builds a [GestureDetector] to handle input events like tap,
- /// to trigger focus requests, to move the caret, adjust the selection, etc.
- /// Handling some of those events by wrapping the text field with a competing
- /// GestureDetector is problematic.
- ///
- /// To unconditionally handle taps, without interfering with the text field's
- /// internal gesture detector, provide this callback.
- ///
- /// If the text field is created with [enabled] false, taps will not be
- /// recognized.
- ///
- /// To be notified when the text field gains or loses the focus, provide a
- /// [focusNode] and add a listener to that.
- ///
- /// To listen to arbitrary pointer events without competing with the
- /// text field's internal gesture detector, use a [Listener].
- /// {@endtemplate}
- final GestureTapCallback? onTap;
- /// {@macro flutter.widgets.editableText.onTapOutside}
- ///
- /// {@tool dartpad}
- /// This example shows how to use a `TextFieldTapRegion` to wrap a set of
- /// "spinner" buttons that increment and decrement a value in the [TextField]
- /// without causing the text field to lose keyboard focus.
- ///
- /// This example includes a generic `SpinnerField<T>` class that you can copy
- /// into your own project and customize.
- ///
- /// ** See code in examples/api/lib/widgets/tap_region/text_field_tap_region.0.dart **
- /// {@end-tool}
- ///
- /// See also:
- ///
- /// * [TapRegion] for how the region group is determined.
- final TapRegionCallback? onTapOutside;
- /// The cursor for a mouse pointer when it enters or is hovering over the
- /// widget.
- ///
- /// If [mouseCursor] is a [MaterialStateProperty<MouseCursor>],
- /// [MaterialStateProperty.resolve] is used for the following [MaterialState]s:
- ///
- /// * [MaterialState.error].
- /// * [MaterialState.hovered].
- /// * [MaterialState.focused].
- /// * [MaterialState.disabled].
- ///
- /// If this property is null, [MaterialStateMouseCursor.textable] will be used.
- ///
- /// The [mouseCursor] is the only property of [TextField] that controls the
- /// appearance of the mouse pointer. All other properties related to "cursor"
- /// stand for the text cursor, which is usually a blinking vertical line at
- /// the editing position.
- final MouseCursor? mouseCursor;
- /// Callback that generates a custom [InputDecoration.counter] widget.
- ///
- /// See [InputCounterWidgetBuilder] for an explanation of the passed in
- /// arguments. The returned widget will be placed below the line in place of
- /// the default widget built when [InputDecoration.counterText] is specified.
- ///
- /// The returned widget will be wrapped in a [Semantics] widget for
- /// accessibility, but it also needs to be accessible itself. For example,
- /// if returning a Text widget, set the [Text.semanticsLabel] property.
- ///
- /// {@tool snippet}
- /// ```dart
- /// Widget counter(
- /// BuildContext context,
- /// {
- /// required int currentLength,
- /// required int? maxLength,
- /// required bool isFocused,
- /// }
- /// ) {
- /// return Text(
- /// '$currentLength of $maxLength characters',
- /// semanticsLabel: 'character count',
- /// );
- /// }
- /// ```
- /// {@end-tool}
- ///
- /// If buildCounter returns null, then no counter and no Semantics widget will
- /// be created at all.
- final InputCounterWidgetBuilder? buildCounter;
- /// {@macro flutter.widgets.editableText.scrollPhysics}
- final ScrollPhysics? scrollPhysics;
- /// {@macro flutter.widgets.editableText.scrollController}
- final ScrollController? scrollController;
- /// {@macro flutter.widgets.editableText.autofillHints}
- /// {@macro flutter.services.AutofillConfiguration.autofillHints}
- final Iterable<String>? autofillHints;
- /// {@macro flutter.material.Material.clipBehavior}
- ///
- /// Defaults to [Clip.hardEdge].
- final Clip clipBehavior;
- /// {@template flutter.material.textfield.restorationId}
- /// Restoration ID to save and restore the state of the text field.
- ///
- /// If non-null, the text field will persist and restore its current scroll
- /// offset and - if no [controller] has been provided - the content of the
- /// text field. If a [controller] has been provided, it is the responsibility
- /// of the owner of that controller to persist and restore it, e.g. by using
- /// a [RestorableTextEditingController].
- ///
- /// The state of this widget is persisted in a [RestorationBucket] claimed
- /// from the surrounding [RestorationScope] using the provided restoration ID.
- ///
- /// See also:
- ///
- /// * [RestorationManager], which explains how state restoration works in
- /// Flutter.
- /// {@endtemplate}
- final String? restorationId;
- /// {@macro flutter.widgets.editableText.scribbleEnabled}
- final bool scribbleEnabled;
- /// {@macro flutter.services.TextInputConfiguration.enableIMEPersonalizedLearning}
- final bool enableIMEPersonalizedLearning;
- /// {@macro flutter.widgets.editableText.contentInsertionConfiguration}
- final ContentInsertionConfiguration? contentInsertionConfiguration;
- /// {@macro flutter.widgets.EditableText.contextMenuBuilder}
- ///
- /// If not provided, will build a default menu based on the platform.
- ///
- /// See also:
- ///
- /// * [AdaptiveTextSelectionToolbar], which is built by default.
- final EditableTextContextMenuBuilder? contextMenuBuilder;
- /// Determine whether this text field can request the primary focus.
- ///
- /// Defaults to true. If false, the text field will not request focus
- /// when tapped, or when its context menu is displayed. If false it will not
- /// be possible to move the focus to the text field with tab key.
- final bool canRequestFocus;
- /// {@macro flutter.widgets.undoHistory.controller}
- final UndoHistoryController? undoController;
- /// {@macro flutter.widgets.EditableText.spellCheckConfiguration}
- ///
- /// If [SpellCheckConfiguration.misspelledTextStyle] is not specified in this
- /// configuration, then [materialMisspelledTextStyle] is used by default.
- final SpellCheckConfiguration? spellCheckConfiguration;
- @override
- State<PasswordTextField> createState() => _PasswordTextFieldState();
- }
- class _PasswordTextFieldState extends State<PasswordTextField> {
- late bool _obscure;
- @override
- void initState() {
- _obscure = widget.initialObscurity;
- super.initState();
- }
- @override
- Widget build(BuildContext context) {
- return TextField(
- obscureText: _obscure,
- decoration: widget.decoration.copyWith(
- suffixIcon: IconButton(
- icon: Icon(
- _obscure ? widget.inVisibleIcon : widget.visibleIcon,
- size: 18, color: const Color(0xFFBBBBBB)
- ),
- onPressed: () {
- setState(() {
- _obscure = !_obscure;
- });
- },
- ),
- ),
- controller: widget.controller,
- focusNode: widget.focusNode,
- undoController: widget.undoController,
- keyboardType: widget.keyboardType,
- textInputAction: widget.textInputAction,
- textCapitalization: widget.textCapitalization,
- style: widget.style,
- strutStyle: widget.strutStyle,
- textAlign: widget.textAlign,
- textAlignVertical: widget.textAlignVertical,
- textDirection: widget.textDirection,
- readOnly: widget.readOnly,
- showCursor: widget.showCursor,
- autofocus: widget.autofocus,
- obscuringCharacter: widget.obscuringCharacter,
- autocorrect: widget.autocorrect,
- enableSuggestions: widget.enableSuggestions,
- maxLines: widget.maxLines,
- minLines: widget.minLines,
- expands: widget.expands,
- maxLength: widget.maxLength,
- maxLengthEnforcement: widget.maxLengthEnforcement,
- onChanged: widget.onChanged,
- onEditingComplete: widget.onEditingComplete,
- onSubmitted: widget.onSubmitted,
- onAppPrivateCommand: widget.onAppPrivateCommand,
- inputFormatters: widget.inputFormatters,
- enabled: widget.enabled,
- cursorWidth: widget.cursorWidth,
- cursorHeight: widget.cursorHeight,
- cursorRadius: widget.cursorRadius,
- cursorOpacityAnimates: widget.cursorOpacityAnimates,
- cursorColor: widget.cursorColor,
- selectionHeightStyle: widget.selectionHeightStyle,
- selectionWidthStyle: widget.selectionWidthStyle,
- keyboardAppearance: widget.keyboardAppearance,
- scrollPadding: widget.scrollPadding,
- dragStartBehavior: widget.dragStartBehavior,
- enableInteractiveSelection: widget.enableInteractiveSelection,
- selectionControls: widget.selectionControls,
- onTap: widget.onTap,
- onTapOutside: widget.onTapOutside,
- mouseCursor: widget.mouseCursor,
- buildCounter: widget.buildCounter,
- scrollController: widget.scrollController,
- scrollPhysics: widget.scrollPhysics,
- autofillHints: widget.autofillHints,
- contentInsertionConfiguration: widget.contentInsertionConfiguration,
- clipBehavior: widget.clipBehavior,
- restorationId: widget.restorationId,
- scribbleEnabled: widget.scribbleEnabled,
- enableIMEPersonalizedLearning: widget.enableIMEPersonalizedLearning,
- contextMenuBuilder: widget.contextMenuBuilder,
- canRequestFocus: widget.canRequestFocus,
- spellCheckConfiguration: widget.spellCheckConfiguration,
- magnifierConfiguration: widget.magnifierConfiguration,
- );
- }
- }
|