xingwei.zhu
5 年前
当前提交
aa75a8a6
共有 5 个文件被更改,包括 912 次插入 和 1 次删除
-
2Runtime/material/text_selection.cs
-
574Runtime/cupertino/text_field.cs
-
11Runtime/cupertino/text_field.cs.meta
-
315Runtime/cupertino/text_selection.cs
-
11Runtime/cupertino/text_selection.cs.meta
|
|||
using System.Collections.Generic; |
|||
using Unity.UIWidgets.foundation; |
|||
using Unity.UIWidgets.gestures; |
|||
using Unity.UIWidgets.painting; |
|||
using Unity.UIWidgets.rendering; |
|||
using Unity.UIWidgets.service; |
|||
using Unity.UIWidgets.ui; |
|||
using Unity.UIWidgets.widgets; |
|||
using TextStyle = Unity.UIWidgets.painting.TextStyle; |
|||
|
|||
namespace Unity.UIWidgets.cupertino { |
|||
class CupertinoTextFieldUtils { |
|||
public static readonly BorderSide _kDefaultRoundedBorderSide = new BorderSide( |
|||
color: CupertinoColors.lightBackgroundGray, |
|||
style: BorderStyle.solid, |
|||
width: 0.0f |
|||
); |
|||
|
|||
public static readonly Border _kDefaultRoundedBorder = new Border( |
|||
top: _kDefaultRoundedBorderSide, |
|||
bottom: _kDefaultRoundedBorderSide, |
|||
left: _kDefaultRoundedBorderSide, |
|||
right: _kDefaultRoundedBorderSide |
|||
); |
|||
|
|||
public static readonly BoxDecoration _kDefaultRoundedBorderDecoration = new BoxDecoration( |
|||
border: _kDefaultRoundedBorder, |
|||
borderRadius: BorderRadius.all(Radius.circular(4.0f)) |
|||
); |
|||
|
|||
public static readonly Color _kSelectionHighlightColor = new Color(0x667FAACF); |
|||
|
|||
public static readonly Color _kInactiveTextColor = new Color(0xFFC2C2C2); |
|||
|
|||
public static readonly Color _kDisabledBackground = new Color(0xFFFAFAFA); |
|||
|
|||
public const int _iOSHorizontalCursorOffsetPixels = -2; |
|||
} |
|||
|
|||
public enum OverlayVisibilityMode { |
|||
never, |
|||
editing, |
|||
notEditing, |
|||
always |
|||
} |
|||
|
|||
public class CupertinoTextField : StatefulWidget { |
|||
public CupertinoTextField( |
|||
Key key = null, |
|||
TextEditingController controller = null, |
|||
FocusNode focusNode = null, |
|||
BoxDecoration decoration = null, |
|||
EdgeInsets padding = null, |
|||
string placeholder = null, |
|||
TextStyle placeholderStyle = null, |
|||
Widget prefix = null, |
|||
OverlayVisibilityMode prefixMode = OverlayVisibilityMode.always, |
|||
Widget suffix = null, |
|||
OverlayVisibilityMode suffixMode = OverlayVisibilityMode.always, |
|||
OverlayVisibilityMode clearButtonMode = OverlayVisibilityMode.never, |
|||
TextInputType keyboardType = null, |
|||
TextInputAction? textInputAction = null, |
|||
TextCapitalization textCapitalization = TextCapitalization.none, |
|||
TextStyle style = null, |
|||
StrutStyle strutStyle = null, |
|||
TextAlign textAlign = TextAlign.left, |
|||
bool autofocus = false, |
|||
bool obscureText = false, |
|||
bool autocorrect = true, |
|||
int? maxLines = 1, |
|||
int? minLines = null, |
|||
bool expands = false, |
|||
int? maxLength = null, |
|||
bool maxLengthEnforced = true, |
|||
ValueChanged<string> onChanged = null, |
|||
VoidCallback onEditingComplete = null, |
|||
ValueChanged<string> onSubmitted = null, |
|||
List<TextInputFormatter> inputFormatters = null, |
|||
bool? enabled = null, |
|||
float cursorWidth = 2.0f, |
|||
Radius cursorRadius = null, |
|||
Color cursorColor = null, |
|||
Brightness? keyboardAppearance = null, |
|||
EdgeInsets scrollPadding = null, |
|||
DragStartBehavior dragStartBehavior = DragStartBehavior.start, |
|||
ScrollPhysics scrollPhysics = null) : base(key: key) { |
|||
D.assert(maxLines == null || maxLines > 0); |
|||
D.assert(minLines == null || minLines > 0); |
|||
D.assert(maxLines == null || minLines == null || maxLines >= minLines, |
|||
() => "minLines can't be greater than maxLines"); |
|||
D.assert(!expands || (maxLines == null && minLines == null), |
|||
() => "minLines and maxLines must be null when expands is true."); |
|||
D.assert(maxLength == null || maxLength > 0); |
|||
|
|||
this.controller = controller; |
|||
this.focusNode = focusNode; |
|||
this.decoration = decoration ?? CupertinoTextFieldUtils._kDefaultRoundedBorderDecoration; |
|||
this.padding = padding ?? EdgeInsets.all(6.0f); |
|||
this.placeholder = placeholder; |
|||
this.placeholderStyle = placeholderStyle ?? new TextStyle( |
|||
fontWeight: FontWeight.w300, |
|||
color: CupertinoTextFieldUtils._kInactiveTextColor |
|||
); |
|||
this.prefix = prefix; |
|||
this.prefixMode = prefixMode; |
|||
this.suffix = suffix; |
|||
this.suffixMode = suffixMode; |
|||
this.clearButtonMode = clearButtonMode; |
|||
this.textInputAction = textInputAction; |
|||
this.textCapitalization = textCapitalization; |
|||
this.style = style; |
|||
this.strutStyle = strutStyle; |
|||
this.textAlign = textAlign; |
|||
this.autofocus = autofocus; |
|||
this.obscureText = obscureText; |
|||
this.autocorrect = autocorrect; |
|||
this.maxLines = maxLines; |
|||
this.minLines = minLines; |
|||
this.expands = expands; |
|||
this.maxLength = maxLength; |
|||
this.maxLengthEnforced = maxLengthEnforced; |
|||
this.onChanged = onChanged; |
|||
this.onEditingComplete = onEditingComplete; |
|||
this.onSubmitted = onSubmitted; |
|||
this.inputFormatters = inputFormatters; |
|||
this.enabled = enabled; |
|||
this.cursorWidth = cursorWidth; |
|||
this.cursorRadius = cursorRadius ?? Radius.circular(2.0f); |
|||
this.cursorColor = cursorColor; |
|||
this.keyboardAppearance = keyboardAppearance; |
|||
this.scrollPadding = scrollPadding ?? EdgeInsets.all(20.0f); |
|||
this.dragStartBehavior = dragStartBehavior; |
|||
this.scrollPhysics = scrollPhysics; |
|||
this.keyboardType = keyboardType ?? (maxLines == 1 ? TextInputType.text : TextInputType.multiline); |
|||
} |
|||
|
|||
public readonly TextEditingController controller; |
|||
|
|||
public readonly FocusNode focusNode; |
|||
|
|||
public readonly BoxDecoration decoration; |
|||
|
|||
public readonly EdgeInsets padding; |
|||
|
|||
public readonly string placeholder; |
|||
|
|||
public readonly TextStyle placeholderStyle; |
|||
|
|||
public readonly Widget prefix; |
|||
|
|||
public readonly OverlayVisibilityMode prefixMode; |
|||
|
|||
public readonly Widget suffix; |
|||
|
|||
public readonly OverlayVisibilityMode suffixMode; |
|||
|
|||
public readonly OverlayVisibilityMode clearButtonMode; |
|||
|
|||
public readonly TextInputType keyboardType; |
|||
|
|||
public readonly TextInputAction? textInputAction; |
|||
|
|||
public readonly TextCapitalization textCapitalization; |
|||
|
|||
public readonly TextStyle style; |
|||
|
|||
public readonly StrutStyle strutStyle; |
|||
|
|||
public readonly TextAlign textAlign; |
|||
|
|||
public readonly bool autofocus; |
|||
|
|||
public readonly bool obscureText; |
|||
|
|||
public readonly bool autocorrect; |
|||
|
|||
public readonly int? maxLines; |
|||
|
|||
public readonly int? minLines; |
|||
|
|||
public readonly bool expands; |
|||
|
|||
public readonly int? maxLength; |
|||
|
|||
public readonly bool maxLengthEnforced; |
|||
|
|||
public readonly ValueChanged<string> onChanged; |
|||
|
|||
public readonly VoidCallback onEditingComplete; |
|||
|
|||
public readonly ValueChanged<string> onSubmitted; |
|||
|
|||
public readonly List<TextInputFormatter> inputFormatters; |
|||
|
|||
public readonly bool? enabled; |
|||
|
|||
public readonly float cursorWidth; |
|||
|
|||
public readonly Radius cursorRadius; |
|||
|
|||
public readonly Color cursorColor; |
|||
|
|||
public readonly Brightness? keyboardAppearance; |
|||
|
|||
public readonly EdgeInsets scrollPadding; |
|||
|
|||
public readonly DragStartBehavior dragStartBehavior; |
|||
|
|||
public readonly ScrollPhysics scrollPhysics; |
|||
|
|||
public override State createState() { |
|||
return new _CupertinoTextFieldState(); |
|||
} |
|||
|
|||
public override void debugFillProperties(DiagnosticPropertiesBuilder properties) { |
|||
base.debugFillProperties(properties); |
|||
|
|||
properties.add( |
|||
new DiagnosticsProperty<TextEditingController>("controller", this.controller, defaultValue: null)); |
|||
properties.add(new DiagnosticsProperty<FocusNode>("focusNode", this.focusNode, defaultValue: null)); |
|||
properties.add(new DiagnosticsProperty<BoxDecoration>("decoration", this.decoration)); |
|||
properties.add(new DiagnosticsProperty<EdgeInsets>("padding", this.padding)); |
|||
properties.add(new StringProperty("placeholder", this.placeholder)); |
|||
properties.add(new DiagnosticsProperty<TextStyle>("placeholderStyle", this.placeholderStyle)); |
|||
properties.add(new DiagnosticsProperty<OverlayVisibilityMode>("prefix", |
|||
this.prefix == null ? OverlayVisibilityMode.never : this.prefixMode)); |
|||
properties.add(new DiagnosticsProperty<OverlayVisibilityMode>("suffix", |
|||
this.suffix == null ? OverlayVisibilityMode.never : this.suffixMode)); |
|||
properties.add(new DiagnosticsProperty<OverlayVisibilityMode>("clearButtonMode", this.clearButtonMode)); |
|||
properties.add(new DiagnosticsProperty<TextInputType>("keyboardType", this.keyboardType, |
|||
defaultValue: TextInputType.text)); |
|||
properties.add(new DiagnosticsProperty<TextStyle>("style", this.style, defaultValue: null)); |
|||
properties.add(new DiagnosticsProperty<bool>("autofocus", this.autofocus, defaultValue: false)); |
|||
properties.add(new DiagnosticsProperty<bool>("obscureText", this.obscureText, defaultValue: false)); |
|||
properties.add(new DiagnosticsProperty<bool>("autocorrect", this.autocorrect, defaultValue: false)); |
|||
properties.add(new IntProperty("maxLines", this.maxLines, defaultValue: 1)); |
|||
properties.add(new IntProperty("minLines", this.minLines, defaultValue: null)); |
|||
properties.add(new DiagnosticsProperty<bool>("expands", this.expands, defaultValue: false)); |
|||
properties.add(new IntProperty("maxLength", this.maxLength, defaultValue: null)); |
|||
properties.add(new FlagProperty("maxLengthEnforced", value: this.maxLengthEnforced, |
|||
ifTrue: "max length enforced")); |
|||
properties.add(new DiagnosticsProperty<Color>("cursorColor", this.cursorColor, defaultValue: null)); |
|||
properties.add( |
|||
new DiagnosticsProperty<ScrollPhysics>("scrollPhysics", this.scrollPhysics, defaultValue: null)); |
|||
} |
|||
} |
|||
|
|||
class _CupertinoTextFieldState : AutomaticKeepAliveClientMixin<CupertinoTextField> { |
|||
GlobalKey<EditableTextState> _editableTextKey = GlobalKey<EditableTextState>.key(); |
|||
|
|||
TextEditingController _controller; |
|||
|
|||
TextEditingController _effectiveController { |
|||
get { return this.widget.controller ?? this._controller; } |
|||
} |
|||
|
|||
FocusNode _focusNode; |
|||
|
|||
FocusNode _effectiveFocusNode { |
|||
get { return this.widget.focusNode ?? this._focusNode ?? (this._focusNode = new FocusNode()); } |
|||
} |
|||
|
|||
public override void initState() { |
|||
base.initState(); |
|||
if (this.widget.controller == null) { |
|||
this._controller = new TextEditingController(); |
|||
this._controller.addListener(this.updateKeepAlive); |
|||
} |
|||
} |
|||
|
|||
public override void didUpdateWidget(StatefulWidget oldWidget) { |
|||
base.didUpdateWidget(oldWidget); |
|||
CupertinoTextField _oldWidget = (CupertinoTextField) oldWidget; |
|||
|
|||
if (this.widget.controller == null && _oldWidget.controller != null) { |
|||
this._controller = TextEditingController.fromValue(_oldWidget.controller.value); |
|||
this._controller.addListener(this.updateKeepAlive); |
|||
} |
|||
else if (this.widget.controller != null && _oldWidget.controller == null) { |
|||
this._controller = null; |
|||
} |
|||
|
|||
bool isEnabled = this.widget.enabled ?? true; |
|||
bool wasEnabled = _oldWidget.enabled ?? true; |
|||
|
|||
if (wasEnabled && !isEnabled) { |
|||
this._effectiveFocusNode.unfocus(); |
|||
} |
|||
} |
|||
|
|||
public override void dispose() { |
|||
this._focusNode?.dispose(); |
|||
this._controller?.removeListener(this.updateKeepAlive); |
|||
base.dispose(); |
|||
} |
|||
|
|||
void _requestKeyboard() { |
|||
this._editableTextKey.currentState?.requestKeyboard(); |
|||
} |
|||
|
|||
RenderEditable _renderEditable { |
|||
get { return this._editableTextKey.currentState.renderEditable; } |
|||
} |
|||
|
|||
void _handleTapDown(TapDownDetails details) { |
|||
this._renderEditable.handleTapDown(details); |
|||
} |
|||
|
|||
|
|||
void _handleSingleTapUp(TapUpDetails details) { |
|||
this._renderEditable.selectWordEdge(cause: SelectionChangedCause.tap); |
|||
this._requestKeyboard(); |
|||
} |
|||
|
|||
void _handleSingleLongTapStart(LongPressStartDetails details) { |
|||
this._renderEditable.selectPositionAt( |
|||
from: details.globalPosition, |
|||
cause: SelectionChangedCause.longPress |
|||
); |
|||
} |
|||
|
|||
void _handleSingleLongTapMoveUpdate(LongPressMoveUpdateDetails details) { |
|||
this._renderEditable.selectPositionAt( |
|||
from: details.globalPosition, |
|||
cause: SelectionChangedCause.longPress |
|||
); |
|||
} |
|||
|
|||
void _handleSingleLongTapEnd(LongPressEndDetails details) { |
|||
this._editableTextKey.currentState.showToolbar(); |
|||
} |
|||
|
|||
void _handleDoubleTapDown(TapDownDetails details) { |
|||
this._renderEditable.selectWord(cause: SelectionChangedCause.tap); |
|||
this._editableTextKey.currentState.showToolbar(); |
|||
} |
|||
|
|||
void _handleMouseDragSelectionStart(DragStartDetails details) { |
|||
this._renderEditable.selectPositionAt( |
|||
from: details.globalPosition, |
|||
cause: SelectionChangedCause.drag |
|||
); |
|||
} |
|||
|
|||
void _handleMouseDragSelectionUpdate( |
|||
DragStartDetails startDetails, |
|||
DragUpdateDetails updateDetails |
|||
) { |
|||
this._renderEditable.selectPositionAt( |
|||
from: startDetails.globalPosition, |
|||
to: updateDetails.globalPosition, |
|||
cause: SelectionChangedCause.drag |
|||
); |
|||
} |
|||
|
|||
void _handleMouseDragSelectionEnd(DragEndDetails details) { |
|||
this._requestKeyboard(); |
|||
} |
|||
|
|||
void _handleSelectionChanged(TextSelection selection, SelectionChangedCause cause) { |
|||
if (cause == SelectionChangedCause.longPress) { |
|||
this._editableTextKey.currentState?.bringIntoView(selection.basePos); |
|||
} |
|||
} |
|||
|
|||
protected override bool wantKeepAlive { |
|||
get { return this._controller?.text?.isNotEmpty() == true; } |
|||
} |
|||
|
|||
bool _shouldShowAttachment( |
|||
OverlayVisibilityMode attachment, |
|||
bool hasText |
|||
) { |
|||
switch (attachment) { |
|||
case OverlayVisibilityMode.never: |
|||
return false; |
|||
case OverlayVisibilityMode.always: |
|||
return true; |
|||
case OverlayVisibilityMode.editing: |
|||
return hasText; |
|||
case OverlayVisibilityMode.notEditing: |
|||
return !hasText; |
|||
} |
|||
|
|||
D.assert(false); |
|||
return false; |
|||
} |
|||
|
|||
bool _showPrefixWidget(TextEditingValue text) { |
|||
return this.widget.prefix != null && this._shouldShowAttachment( |
|||
attachment: this.widget.prefixMode, |
|||
hasText: text.text.isNotEmpty() |
|||
); |
|||
} |
|||
|
|||
bool _showSuffixWidget(TextEditingValue text) { |
|||
return this.widget.suffix != null && this._shouldShowAttachment( |
|||
attachment: this.widget.suffixMode, |
|||
hasText: text.text.isNotEmpty() |
|||
); |
|||
} |
|||
|
|||
bool _showClearButton(TextEditingValue text) { |
|||
return this._shouldShowAttachment( |
|||
attachment: this.widget.clearButtonMode, |
|||
hasText: text.text.isNotEmpty() |
|||
); |
|||
} |
|||
|
|||
Widget _addTextDependentAttachments(Widget editableText, TextStyle textStyle, TextStyle placeholderStyle) { |
|||
D.assert(editableText != null); |
|||
D.assert(textStyle != null); |
|||
D.assert(placeholderStyle != null); |
|||
|
|||
if (this.widget.placeholder == null && |
|||
this.widget.clearButtonMode == OverlayVisibilityMode.never && |
|||
this.widget.prefix == null && |
|||
this.widget.suffix == null) { |
|||
return editableText; |
|||
} |
|||
|
|||
return new ValueListenableBuilder<TextEditingValue>( |
|||
valueListenable: this._effectiveController, |
|||
child: editableText, |
|||
builder: (BuildContext context, TextEditingValue text, Widget child) => { |
|||
List<Widget> rowChildren = new List<Widget>(); |
|||
|
|||
if (this._showPrefixWidget(text)) { |
|||
rowChildren.Add(this.widget.prefix); |
|||
} |
|||
|
|||
List<Widget> stackChildren = new List<Widget>(); |
|||
if (this.widget.placeholder != null && text.text.isEmpty()) { |
|||
stackChildren.Add( |
|||
new Padding( |
|||
padding: this.widget.padding, |
|||
child: new Text( |
|||
this.widget.placeholder, |
|||
maxLines: 1, |
|||
overflow: TextOverflow.ellipsis, |
|||
style: placeholderStyle |
|||
) |
|||
) |
|||
); |
|||
} |
|||
|
|||
stackChildren.Add(child); |
|||
rowChildren.Add( |
|||
new Expanded |
|||
(child: new Stack |
|||
(children: stackChildren))); |
|||
|
|||
if (this._showSuffixWidget(text)) { |
|||
rowChildren.Add(this.widget.suffix); |
|||
} |
|||
else if (this._showClearButton(text)) { |
|||
rowChildren.Add( |
|||
new GestureDetector( |
|||
onTap: this.widget.enabled ?? true |
|||
? () => { |
|||
bool textChanged = this._effectiveController.text.isNotEmpty(); |
|||
this._effectiveController.clear(); |
|||
if (this.widget.onChanged != null && textChanged) { |
|||
this.widget.onChanged(this._effectiveController.text); |
|||
} |
|||
} |
|||
: (GestureTapCallback) null, |
|||
child: new Padding( |
|||
padding: EdgeInsets.symmetric(horizontal: 6.0f), |
|||
child: new Icon( |
|||
CupertinoIcons.clear_thick_circled, |
|||
size: 18.0f, |
|||
color: CupertinoTextFieldUtils._kInactiveTextColor |
|||
) |
|||
) |
|||
) |
|||
); |
|||
} |
|||
|
|||
return new Row(children: rowChildren); |
|||
} |
|||
); |
|||
} |
|||
|
|||
public override Widget build(BuildContext context) { |
|||
base.build(context); |
|||
TextEditingController controller = this._effectiveController; |
|||
List<TextInputFormatter> formatters = this.widget.inputFormatters ?? new List<TextInputFormatter>(); |
|||
bool enabled = this.widget.enabled ?? true; |
|||
Offset cursorOffset = |
|||
new Offset( |
|||
CupertinoTextFieldUtils._iOSHorizontalCursorOffsetPixels / MediaQuery.of(context).devicePixelRatio, |
|||
0); |
|||
if (this.widget.maxLength != null && this.widget.maxLengthEnforced) { |
|||
formatters.Add(new LengthLimitingTextInputFormatter(this.widget.maxLength)); |
|||
} |
|||
|
|||
CupertinoThemeData themeData = CupertinoTheme.of(context); |
|||
TextStyle textStyle = themeData.textTheme.textStyle.merge(this.widget.style); |
|||
TextStyle placeholderStyle = textStyle.merge(this.widget.placeholderStyle); |
|||
Brightness keyboardAppearance = this.widget.keyboardAppearance ?? themeData.brightness; |
|||
Color cursorColor = this.widget.cursorColor ?? themeData.primaryColor; |
|||
|
|||
Widget paddedEditable = new Padding( |
|||
padding: this.widget.padding, |
|||
child: new RepaintBoundary( |
|||
child: new EditableText( |
|||
key: this._editableTextKey, |
|||
controller: controller, |
|||
focusNode: this._effectiveFocusNode, |
|||
keyboardType: this.widget.keyboardType, |
|||
textInputAction: this.widget.textInputAction, |
|||
textCapitalization: this.widget.textCapitalization, |
|||
style: textStyle, |
|||
strutStyle: this.widget.strutStyle, |
|||
textAlign: this.widget.textAlign, |
|||
autofocus: this.widget.autofocus, |
|||
obscureText: this.widget.obscureText, |
|||
autocorrect: this.widget.autocorrect, |
|||
maxLines: this.widget.maxLines, |
|||
minLines: this.widget.minLines, |
|||
expands: this.widget.expands, |
|||
selectionColor: CupertinoTextFieldUtils._kSelectionHighlightColor, |
|||
selectionControls: CupertinoTextSelectionUtils.cupertinoTextSelectionControls, |
|||
onChanged: this.widget.onChanged, |
|||
onSelectionChanged: this._handleSelectionChanged, |
|||
onEditingComplete: this.widget.onEditingComplete, |
|||
onSubmitted: this.widget.onSubmitted, |
|||
inputFormatters: formatters, |
|||
rendererIgnoresPointer: true, |
|||
cursorWidth: this.widget.cursorWidth, |
|||
cursorRadius: this.widget.cursorRadius, |
|||
cursorColor: cursorColor, |
|||
cursorOpacityAnimates: true, |
|||
cursorOffset: cursorOffset, |
|||
paintCursorAboveText: true, |
|||
backgroundCursorColor: CupertinoColors.inactiveGray, |
|||
scrollPadding: this.widget.scrollPadding, |
|||
keyboardAppearance: keyboardAppearance, |
|||
dragStartBehavior: this.widget.dragStartBehavior, |
|||
scrollPhysics: this.widget.scrollPhysics |
|||
) |
|||
) |
|||
); |
|||
|
|||
return new IgnorePointer( |
|||
ignoring: !enabled, |
|||
child: new Container( |
|||
decoration: this.widget.decoration, |
|||
child: new Container( |
|||
color: enabled |
|||
? null |
|||
: CupertinoTheme.of(context).brightness == Brightness.light |
|||
? CupertinoTextFieldUtils._kDisabledBackground |
|||
: CupertinoColors.darkBackgroundGray, |
|||
child: new TextSelectionGestureDetector( |
|||
onTapDown: this._handleTapDown, |
|||
onSingleTapUp: this._handleSingleTapUp, |
|||
onSingleLongTapStart: this._handleSingleLongTapStart, |
|||
onSingleLongTapMoveUpdate: this._handleSingleLongTapMoveUpdate, |
|||
onSingleLongTapEnd: this._handleSingleLongTapEnd, |
|||
onDoubleTapDown: this._handleDoubleTapDown, |
|||
onDragSelectionStart: this._handleMouseDragSelectionStart, |
|||
onDragSelectionUpdate: this._handleMouseDragSelectionUpdate, |
|||
onDragSelectionEnd: this._handleMouseDragSelectionEnd, |
|||
behavior: HitTestBehavior.translucent, |
|||
child: this._addTextDependentAttachments(paddedEditable, textStyle, placeholderStyle) |
|||
) |
|||
) |
|||
) |
|||
); |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: a300f388a142347fab65f219e2843698 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|
|||
using System.Collections.Generic; |
|||
using Unity.UIWidgets.foundation; |
|||
using Unity.UIWidgets.painting; |
|||
using Unity.UIWidgets.rendering; |
|||
using Unity.UIWidgets.service; |
|||
using Unity.UIWidgets.ui; |
|||
using Unity.UIWidgets.widgets; |
|||
using UnityEngine; |
|||
using Canvas = Unity.UIWidgets.ui.Canvas; |
|||
using Color = Unity.UIWidgets.ui.Color; |
|||
using Rect = Unity.UIWidgets.ui.Rect; |
|||
using TextStyle = Unity.UIWidgets.painting.TextStyle; |
|||
using Transform = Unity.UIWidgets.widgets.Transform; |
|||
|
|||
namespace Unity.UIWidgets.cupertino { |
|||
public static class CupertinoTextSelectionUtils { |
|||
public static TextSelectionControls cupertinoTextSelectionControls = new _CupertinoTextSelectionControls(); |
|||
|
|||
public const float _kHandlesPadding = 18.0f; |
|||
|
|||
public const float _kToolbarScreenPadding = 8.0f; |
|||
|
|||
public const float _kToolbarHeight = 36.0f; |
|||
|
|||
public static readonly Color _kToolbarBackgroundColor = new Color(0xFF2E2E2E); |
|||
|
|||
public static readonly Color _kToolbarDividerColor = new Color(0xFFB9B9B9); |
|||
|
|||
public static readonly Color _kHandlesColor = new Color(0xFF136FE0); |
|||
|
|||
public static readonly Size _kSelectionOffset = new Size(20.0f, 30.0f); |
|||
|
|||
public static readonly Size _kToolbarTriangleSize = new Size(18.0f, 9.0f); |
|||
|
|||
public static readonly EdgeInsets _kToolbarButtonPadding = |
|||
EdgeInsets.symmetric(vertical: 10.0f, horizontal: 18.0f); |
|||
|
|||
public static readonly BorderRadius _kToolbarBorderRadius = BorderRadius.all(Radius.circular(7.5f)); |
|||
|
|||
public static readonly TextStyle _kToolbarButtonFontStyle = new TextStyle( |
|||
fontSize: 14.0f, |
|||
letterSpacing: -0.11f, |
|||
fontWeight: FontWeight.w300, |
|||
color: CupertinoColors.white |
|||
); |
|||
} |
|||
|
|||
class _TextSelectionToolbarNotchPainter : AbstractCustomPainter { |
|||
public override void paint(Canvas canvas, Size size) { |
|||
Paint paint = new Paint(); |
|||
paint.color = CupertinoTextSelectionUtils._kToolbarBackgroundColor; |
|||
paint.style = PaintingStyle.fill; |
|||
|
|||
Path triangle = new Path(); |
|||
triangle.lineTo(CupertinoTextSelectionUtils._kToolbarTriangleSize.width / 2, 0.0f); |
|||
triangle.lineTo(0.0f, CupertinoTextSelectionUtils._kToolbarTriangleSize.height); |
|||
triangle.lineTo(-(CupertinoTextSelectionUtils._kToolbarTriangleSize.width / 2), 0.0f); |
|||
triangle.close(); |
|||
canvas.drawPath(triangle, paint); |
|||
} |
|||
|
|||
public override bool shouldRepaint(CustomPainter oldPainter) { |
|||
return false; |
|||
} |
|||
} |
|||
|
|||
class _TextSelectionToolbar : StatelessWidget { |
|||
public _TextSelectionToolbar( |
|||
Key key = null, |
|||
VoidCallback handleCut = null, |
|||
VoidCallback handleCopy = null, |
|||
VoidCallback handlePaste = null, |
|||
VoidCallback handleSelectAll = null |
|||
) : base(key: key) { |
|||
this.handleCut = handleCut; |
|||
this.handleCopy = handleCopy; |
|||
this.handlePaste = handlePaste; |
|||
this.handleSelectAll = handleSelectAll; |
|||
} |
|||
|
|||
readonly VoidCallback handleCut; |
|||
|
|||
readonly VoidCallback handleCopy; |
|||
|
|||
readonly VoidCallback handlePaste; |
|||
|
|||
readonly VoidCallback handleSelectAll; |
|||
|
|||
|
|||
public override Widget build(BuildContext context) { |
|||
List<Widget> items = new List<Widget>(); |
|||
Widget onePhysicalPixelVerticalDivider = |
|||
new SizedBox(width: 1.0f / MediaQuery.of(context).devicePixelRatio); |
|||
CupertinoLocalizations localizations = CupertinoLocalizations.of(context); |
|||
|
|||
if (this.handleCut != null) { |
|||
items.Add(this._buildToolbarButton(localizations.cutButtonLabel, this.handleCut)); |
|||
} |
|||
|
|||
if (this.handleCopy != null) { |
|||
if (items.isNotEmpty()) { |
|||
items.Add(onePhysicalPixelVerticalDivider); |
|||
} |
|||
|
|||
items.Add(this._buildToolbarButton(localizations.copyButtonLabel, this.handleCopy)); |
|||
} |
|||
|
|||
if (this.handlePaste != null) { |
|||
if (items.isNotEmpty()) { |
|||
items.Add(onePhysicalPixelVerticalDivider); |
|||
} |
|||
|
|||
items.Add(this._buildToolbarButton(localizations.pasteButtonLabel, this.handlePaste)); |
|||
} |
|||
|
|||
if (this.handleSelectAll != null) { |
|||
if (items.isNotEmpty()) { |
|||
items.Add(onePhysicalPixelVerticalDivider); |
|||
} |
|||
|
|||
items.Add(this._buildToolbarButton(localizations.selectAllButtonLabel, this.handleSelectAll)); |
|||
} |
|||
|
|||
Widget triangle = SizedBox.fromSize( |
|||
size: CupertinoTextSelectionUtils._kToolbarTriangleSize, |
|||
child: new CustomPaint( |
|||
painter: new _TextSelectionToolbarNotchPainter() |
|||
) |
|||
); |
|||
|
|||
return new Column( |
|||
mainAxisSize: MainAxisSize.min, |
|||
children: new List<Widget> { |
|||
new ClipRRect( |
|||
borderRadius: CupertinoTextSelectionUtils._kToolbarBorderRadius, |
|||
child: new DecoratedBox( |
|||
decoration: new BoxDecoration( |
|||
color: CupertinoTextSelectionUtils._kToolbarDividerColor, |
|||
borderRadius: CupertinoTextSelectionUtils._kToolbarBorderRadius, |
|||
border: Border.all(color: CupertinoTextSelectionUtils._kToolbarBackgroundColor, |
|||
width: 0) |
|||
), |
|||
child: new Row(mainAxisSize: MainAxisSize.min, children: items) |
|||
) |
|||
), |
|||
triangle, |
|||
new Padding(padding: EdgeInsets.only(bottom: 10.0f)) |
|||
} |
|||
); |
|||
} |
|||
|
|||
CupertinoButton _buildToolbarButton(string text, VoidCallback onPressed) { |
|||
return new CupertinoButton( |
|||
child: new Text(text, style: CupertinoTextSelectionUtils._kToolbarButtonFontStyle), |
|||
color: CupertinoTextSelectionUtils._kToolbarBackgroundColor, |
|||
minSize: CupertinoTextSelectionUtils._kToolbarHeight, |
|||
padding: CupertinoTextSelectionUtils._kToolbarButtonPadding, |
|||
borderRadius: null, |
|||
pressedOpacity: 0.7f, |
|||
onPressed: onPressed |
|||
); |
|||
} |
|||
} |
|||
|
|||
class _TextSelectionToolbarLayout : SingleChildLayoutDelegate { |
|||
public _TextSelectionToolbarLayout( |
|||
Size screenSize, |
|||
Rect globalEditableRegion, |
|||
Offset position) { |
|||
this.screenSize = screenSize; |
|||
this.globalEditableRegion = globalEditableRegion; |
|||
this.position = position; |
|||
} |
|||
|
|||
readonly Size screenSize; |
|||
|
|||
readonly Rect globalEditableRegion; |
|||
|
|||
readonly Offset position; |
|||
|
|||
public override BoxConstraints getConstraintsForChild(BoxConstraints constraints) { |
|||
return constraints.loosen(); |
|||
} |
|||
|
|||
public override Offset getPositionForChild(Size size, Size childSize) { |
|||
Offset globalPosition = this.globalEditableRegion.topLeft + this.position; |
|||
|
|||
float x = globalPosition.dx - childSize.width / 2.0f; |
|||
float y = globalPosition.dy - childSize.height; |
|||
|
|||
if (x < CupertinoTextSelectionUtils._kToolbarScreenPadding) { |
|||
x = CupertinoTextSelectionUtils._kToolbarScreenPadding; |
|||
} |
|||
else if (x + childSize.width > this.screenSize.width - CupertinoTextSelectionUtils._kToolbarScreenPadding) { |
|||
x = this.screenSize.width - childSize.width - CupertinoTextSelectionUtils._kToolbarScreenPadding; |
|||
} |
|||
|
|||
if (y < CupertinoTextSelectionUtils._kToolbarScreenPadding) { |
|||
y = CupertinoTextSelectionUtils._kToolbarScreenPadding; |
|||
} |
|||
else if (y + childSize.height > |
|||
this.screenSize.height - CupertinoTextSelectionUtils._kToolbarScreenPadding) { |
|||
y = this.screenSize.height - childSize.height - CupertinoTextSelectionUtils._kToolbarScreenPadding; |
|||
} |
|||
|
|||
return new Offset(x, y); |
|||
} |
|||
|
|||
public override bool shouldRelayout(SingleChildLayoutDelegate oldDelegate) { |
|||
_TextSelectionToolbarLayout _oldDelegate = (_TextSelectionToolbarLayout) oldDelegate; |
|||
return this.screenSize != _oldDelegate.screenSize |
|||
|| this.globalEditableRegion != _oldDelegate.globalEditableRegion |
|||
|| this.position != _oldDelegate.position; |
|||
} |
|||
} |
|||
|
|||
class _TextSelectionHandlePainter : AbstractCustomPainter { |
|||
public _TextSelectionHandlePainter(Offset origin) { |
|||
this.origin = origin; |
|||
} |
|||
|
|||
readonly Offset origin; |
|||
|
|||
|
|||
public override void paint(Canvas canvas, Size size) { |
|||
Paint paint = new Paint(); |
|||
paint.color = CupertinoTextSelectionUtils._kHandlesColor; |
|||
paint.strokeWidth = 2.0f; |
|||
|
|||
canvas.drawCircle(this.origin.translate(0.0f, 4.0f), 5.5f, paint); |
|||
canvas.drawLine( |
|||
this.origin, |
|||
this.origin.translate( |
|||
0.0f, |
|||
-(size.height - 2.0f * CupertinoTextSelectionUtils._kHandlesPadding) |
|||
), |
|||
paint |
|||
); |
|||
} |
|||
|
|||
public override bool shouldRepaint(CustomPainter oldPainter) { |
|||
_TextSelectionHandlePainter _oldPainter = (_TextSelectionHandlePainter) oldPainter; |
|||
return this.origin != _oldPainter.origin; |
|||
} |
|||
} |
|||
|
|||
class _CupertinoTextSelectionControls : TextSelectionControls { |
|||
public override Size handleSize { |
|||
get { return CupertinoTextSelectionUtils._kSelectionOffset; } |
|||
} |
|||
|
|||
public override Widget buildToolbar(BuildContext context, Rect globalEditableRegion, Offset position, |
|||
TextSelectionDelegate del) { |
|||
D.assert(WidgetsD.debugCheckHasMediaQuery(context)); |
|||
return new ConstrainedBox( |
|||
constraints: BoxConstraints.tight(globalEditableRegion.size), |
|||
child: new CustomSingleChildLayout( |
|||
layoutDelegate: new _TextSelectionToolbarLayout( |
|||
MediaQuery.of(context).size, |
|||
globalEditableRegion, |
|||
position |
|||
), |
|||
child: new _TextSelectionToolbar( |
|||
handleCut: this.canCut(del) ? () => this.handleCut(del) : (VoidCallback) null, |
|||
handleCopy: this.canCopy(del) ? () => this.handleCopy(del) : (VoidCallback) null, |
|||
handlePaste: this.canPaste(del) ? () => this.handlePaste(del) : (VoidCallback) null, |
|||
handleSelectAll: this.canSelectAll(del) ? () => this.handleSelectAll(del) : (VoidCallback) null |
|||
) |
|||
) |
|||
); |
|||
} |
|||
|
|||
|
|||
public override Widget buildHandle(BuildContext context, TextSelectionHandleType type, float textLineHeight) { |
|||
Size desiredSize = new Size( |
|||
2.0f * CupertinoTextSelectionUtils._kHandlesPadding, |
|||
textLineHeight + 2.0f * CupertinoTextSelectionUtils._kHandlesPadding |
|||
); |
|||
|
|||
Widget handle = SizedBox.fromSize( |
|||
size: desiredSize, |
|||
child: new CustomPaint( |
|||
painter: new _TextSelectionHandlePainter( |
|||
origin: new Offset(CupertinoTextSelectionUtils._kHandlesPadding, |
|||
textLineHeight + CupertinoTextSelectionUtils._kHandlesPadding) |
|||
) |
|||
) |
|||
); |
|||
|
|||
switch (type) { |
|||
case TextSelectionHandleType.left: |
|||
Matrix3 matrix = Matrix3.makeRotate(Mathf.PI); |
|||
matrix.preTranslate(-CupertinoTextSelectionUtils._kHandlesPadding, |
|||
-CupertinoTextSelectionUtils._kHandlesPadding); |
|||
|
|||
return new Transform( |
|||
transform: matrix, |
|||
child: handle |
|||
); |
|||
case TextSelectionHandleType.right: |
|||
return new Transform( |
|||
transform: Matrix3.makeTrans( |
|||
-CupertinoTextSelectionUtils._kHandlesPadding, |
|||
-(textLineHeight + CupertinoTextSelectionUtils._kHandlesPadding) |
|||
), |
|||
child: handle |
|||
); |
|||
case TextSelectionHandleType.collapsed: |
|||
return new Container(); |
|||
} |
|||
|
|||
return null; |
|||
} |
|||
} |
|||
} |
|
|||
fileFormatVersion: 2 |
|||
guid: 2afc9187fdd8b4f7abbb404a4cb3cf71 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
撰写
预览
正在加载...
取消
保存
Reference in new issue