浏览代码

implement Cupertino text field + text selection

/main
xingwei.zhu 5 年前
当前提交
aa75a8a6
共有 5 个文件被更改,包括 912 次插入1 次删除
  1. 2
      Runtime/material/text_selection.cs
  2. 574
      Runtime/cupertino/text_field.cs
  3. 11
      Runtime/cupertino/text_field.cs.meta
  4. 315
      Runtime/cupertino/text_selection.cs
  5. 11
      Runtime/cupertino/text_selection.cs.meta

2
Runtime/material/text_selection.cs


namespace Unity.UIWidgets.material {
public static class MaterialUtils {
public readonly static TextSelectionControls materialTextSelectionControls =
public static readonly TextSelectionControls materialTextSelectionControls =
new _MaterialTextSelectionControls();
internal const float _kHandleSize = 22.0f;

574
Runtime/cupertino/text_field.cs


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)
)
)
)
);
}
}
}

11
Runtime/cupertino/text_field.cs.meta


fileFormatVersion: 2
guid: a300f388a142347fab65f219e2843698
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

315
Runtime/cupertino/text_selection.cs


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;
}
}
}

11
Runtime/cupertino/text_selection.cs.meta


fileFormatVersion: 2
guid: 2afc9187fdd8b4f7abbb404a4cb3cf71
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
正在加载...
取消
保存