浏览代码

Update editable text.

/main
Yuncong Zhang 6 年前
当前提交
991f9270
共有 5 个文件被更改,包括 226 次插入43 次删除
  1. 7
      Runtime/material/card.cs
  2. 1
      Runtime/material/text_field.cs
  3. 26
      Runtime/material/text_theme.cs
  4. 229
      Runtime/widgets/editable_text.cs
  5. 6
      Runtime/widgets/icon_theme_data.cs

7
Runtime/material/card.cs


public readonly Widget child;
const double _defaultElevation = 1.0;
const float _defaultElevation = 1.0f;
elevation: this.elevation ?? cardTheme.elevation ?? 1.0f,
elevation: this.elevation ?? cardTheme.elevation ?? _defaultElevation,
borderOnForeground: this.borderOnForeground,
clipBehavior: this.clipBehavior ?? cardTheme.clipBehavior ?? _defaultClipBehavior,
child: this.child)
);

1
Runtime/material/text_field.cs


ignoring: !(this.widget.enabled ?? this.widget.decoration?.enabled ?? true),
child: new TextSelectionGestureDetector(
onTapDown: this._handleTapDown,
// onForcePressStart: forcePressEnabled ? this._handleForcePressStarted : null, // TODO: Remove this when force press is added
onSingleTapUp: this._handleSingleTapUp,
onSingleTapCancel: this._handleSingleTapCancel,
onSingleLongTapStart: this._handleLongPress,

26
Runtime/material/text_theme.cs


return this._cachedHashCode.Value;
}
unchecked {
var hashCode = this.display4.GetHashCode();
hashCode = (hashCode * 397) ^ this.display3.GetHashCode();
hashCode = (hashCode * 397) ^ this.display2.GetHashCode();
hashCode = (hashCode * 397) ^ this.display1.GetHashCode();
hashCode = (hashCode * 397) ^ this.headline.GetHashCode();
hashCode = (hashCode * 397) ^ this.title.GetHashCode();
hashCode = (hashCode * 397) ^ this.subhead.GetHashCode();
hashCode = (hashCode * 397) ^ this.body2.GetHashCode();
hashCode = (hashCode * 397) ^ this.body1.GetHashCode();
hashCode = (hashCode * 397) ^ this.caption.GetHashCode();
hashCode = (hashCode * 397) ^ this.button.GetHashCode();
hashCode = (hashCode * 397) ^ this.subtitle.GetHashCode();
hashCode = (hashCode * 397) ^ this.overline.GetHashCode();
var hashCode = this.display4?.GetHashCode() ?? 0;
hashCode = (hashCode * 397) ^ this.display3?.GetHashCode() ?? 0;
hashCode = (hashCode * 397) ^ this.display2?.GetHashCode() ?? 0;
hashCode = (hashCode * 397) ^ this.display1?.GetHashCode() ?? 0;
hashCode = (hashCode * 397) ^ this.headline?.GetHashCode() ?? 0;
hashCode = (hashCode * 397) ^ this.title?.GetHashCode() ?? 0;
hashCode = (hashCode * 397) ^ this.subhead?.GetHashCode() ?? 0;
hashCode = (hashCode * 397) ^ this.body2?.GetHashCode() ?? 0;
hashCode = (hashCode * 397) ^ this.body1?.GetHashCode() ?? 0;
hashCode = (hashCode * 397) ^ this.caption?.GetHashCode() ?? 0;
hashCode = (hashCode * 397) ^ this.button?.GetHashCode() ?? 0;
hashCode = (hashCode * 397) ^ this.subtitle?.GetHashCode() ?? 0;
hashCode = (hashCode * 397) ^ this.overline?.GetHashCode() ?? 0;
this._cachedHashCode = hashCode;
return hashCode;

229
Runtime/widgets/editable_text.cs


public override State createState() {
return new EditableTextState();
}
public static bool debugDeterministicCursor = false;
public override void debugFillProperties(DiagnosticPropertiesBuilder properties) {
base.debugFillProperties(properties);

public class EditableTextState : AutomaticKeepAliveClientWithTickerProviderStateMixin<EditableText>,
WidgetsBindingObserver, TextInputClient,
TextSelectionDelegate {
static readonly TimeSpan _fadeDuration = TimeSpan.FromMilliseconds(500);
static readonly TimeSpan _floatingCursorResetTime = TimeSpan.FromMilliseconds(150);
TextInputConnection _textInputConnection;
TextSelectionOverlay _selectionOverlay;
public ScrollController _scrollController = new ScrollController();
AnimationController _cursorBlinkOpacityController;
public ScrollController _scrollController = new ScrollController();
AnimationController _cursorBlinkOpacityController;
TextInputConnection _textInputConnection;
TextSelectionOverlay _selectionOverlay;
int _obscureShowCharTicksPending = 0;
int _obscureLatestCharIndex;
static readonly TimeSpan _fadeDuration = TimeSpan.FromMilliseconds(500);
static readonly TimeSpan _floatingCursorResetTime = TimeSpan.FromMilliseconds(150);
AnimationController _floatingCursorResetController;
Color _cursorColor {
get {
return this.widget.cursorColor.withOpacity(this._cursorBlinkOpacityController.value);
}
}
public override void initState() {
base.initState();

this._cursorBlinkOpacityController = new AnimationController(vsync: this, duration: _fadeDuration);
this._cursorBlinkOpacityController.addListener(this._onCursorColorTick);
this._floatingCursorResetController = new AnimationController(vsync: this);
// this._floatingCursorResetController.addListener(_onFloatingCursorResetTick); // TODO: remove comment when _onFLoatingCursorResetTick is ready
}
public override void didChangeDependencies() {

public override void dispose() {
this.widget.controller.removeListener(this._didChangeTextEditingValue);
this._cursorBlinkOpacityController.removeListener(this._onCursorColorTick);
// this._floatingCursorResetController.removeListener(this._onFloatingCursorResetTick); // TODO: remove comment when _onFloatingCursorResetTick is ready
this._closeInputConnectionIfNeeded();
D.assert(!this._hasInputConnection);
this._stopCursorTimer();

this._lastKnownRemoteTextEditingValue = value;
this._formatAndSetValue(value);
this._stopCursorTimer(resetCharTicks: false);
this._startCursorTimer();
}
public void performAction(TextInputAction action) {

break;
}
}
Rect _startCaretRect;
TextPosition _lastTextPosition;
Offset _pointOffsetOrigin;
Offset _lastBoundedOffset;
Offset _floatingCursorOffset {
get {
return new Offset(0, this.renderEditable.preferredLineHeight / 2);
}
}
// TODO: remove comment when renderEditable is updated and FloatingCursorDragState is ready
// void updateFloatingCursor(RawFloatingCursorPoint point) {
// switch(point.state){
// case FloatingCursorDragState.Start:
// TextPosition currentTextPosition = new TextPosition(offset: this.renderEditable.selection.baseOffset);
// this._startCaretRect = this.renderEditable.getLocalRectForCaret(currentTextPosition);
// this.renderEditable.setFloatingCursor(point.state, this._startCaretRect.center - this._floatingCursorOffset, currentTextPosition);
// break;
// case FloatingCursorDragState.Update:
// // We want to send in points that are centered around a (0,0) origin, so we cache the
// // position on the first update call.
// if (this._pointOffsetOrigin != null) {
// Offset centeredPoint = point.offset - this._pointOffsetOrigin;
// Offset rawCursorOffset = this._startCaretRect.center + centeredPoint - this._floatingCursorOffset;
// this._lastBoundedOffset = this.renderEditable.calculateBoundedFloatingCursorOffset(rawCursorOffset);
// this._lastTextPosition = this.renderEditable.getPositionForPoint(this.renderEditable.localToGlobal(this._lastBoundedOffset + this._floatingCursorOffset));
// this.renderEditable.setFloatingCursor(point.state, this._lastBoundedOffset, this._lastTextPosition);
// } else {
// this._pointOffsetOrigin = point.offset;
// }
// break;
// case FloatingCursorDragState.End:
// this._floatingCursorResetController.setValue(0.0f);
// this._floatingCursorResetController.animateTo(1.0f, duration: _floatingCursorResetTime, curve: Curves.decelerate);
// break;
// }
// }
// TODO: remove comment when RenderEditable.setFloatingCursor, Floating CursorDragState, and force press is ready
// void _onFloatingCursorResetTick() {
// Offset finalPosition = this.renderEditable.getLocalRectForCaret(this._lastTextPosition).centerLeft - this._floatingCursorOffset;
// if (this._floatingCursorResetController.isCompleted) {
// this.renderEditable.setFloatingCursor(FloatingCursorDragState.End, finalPosition, this._lastTextPosition);
// if (this._lastTextPosition.offset != this.renderEditable.selection.baseOffset)
// this._handleSelectionChanged(TextSelection.collapsed(offset: this._lastTextPosition.offset), this.renderEditable, SelectionChangedCause.forcePress);
// this._startCaretRect = null;
// this._lastTextPosition = null;
// this._pointOffsetOrigin = null;
// this._lastBoundedOffset = null;
// } else {
// float lerpValue = this._floatingCursorResetController.value;
// float lerpX = MathUtils.lerpFloat(this._lastBoundedOffset.dx, finalPosition.dx, lerpValue);
// float lerpY = MathUtils.lerpFloat(this._lastBoundedOffset.dy, finalPosition.dy, lerpValue);
//
// this.renderEditable.setFloatingCursor(FloatingCursorDragState.Update, new Offset(lerpX, lerpY), this._lastTextPosition, resetLerpValue: lerpValue);
// }
// }
void _finalizeEditing(bool shouldUnfocus) {
if (this.widget.onEditingComplete != null) {

// Calculate the new scroll offset so the cursor remains visible.
float _getScrollOffsetForCaret(Rect caretRect) {
float caretStart = this._isMultiline ? caretRect.top : caretRect.left;
float caretEnd = this._isMultiline ? caretRect.bottom : caretRect.right;
float caretStart;
float caretEnd;
if (this._isMultiline) {
// The caret is vertically centered within the line. Expand the caret's
// height so that it spans the line because we're going to ensure that the entire
// expanded caret is scrolled into view.
float lineHeight = this.renderEditable.preferredLineHeight;
float caretOffset = (lineHeight - caretRect.height) / 2;
caretStart = caretRect.top - caretOffset;
caretEnd = caretRect.bottom + caretOffset;
} else {
caretStart = caretRect.left;
caretEnd = caretRect.right;
}
float scrollOffset = this._scrollController.offset;
float viewportExtent = this._scrollController.position.viewportDimension;
if (caretStart < 0.0) {

this._openInputConnection();
}
else {
// TODO: remove comment when FocusScope.ancestorsOf is ready
// List<FocusScopeNode> ancestorScopes = FocusScope.ancestorsOf(this.context);
// for (int i = ancestorScopes.Count - 1; i >= 1; i -= 1)
// ancestorScopes[i].setFirstFocus(ancestorScopes[i - 1]);
FocusScope.of(this.context).requestFocus(this.widget.focusNode);
}
}

renderObject: renderObject,
selectionControls: this.widget.selectionControls,
selectionDelegate: this
// dragStartBehavior: this.widget.dragStartBehavior // TODO: remove comment when TextSelectionOverlay is updated
);
bool longPress = cause == SelectionChangedCause.longPress;
if (cause != SelectionChangedCause.keyboard && (this._value.text.isNotEmpty() || longPress)) {

}
void _formatAndSetValue(TextEditingValue value) {
var textChanged = (this._value == null ? null : this._value.text) != (value == null ? null : value.text);
if (this.widget.inputFormatters != null && this.widget.inputFormatters.isNotEmpty()) {
var textChanged = this._value?.text != value?.text;
if (textChanged && this.widget.inputFormatters != null && this.widget.inputFormatters.isNotEmpty()) {
foreach (var formatter in this.widget.inputFormatters) {
value = formatter.formatEditUpdate(this._value, value);
}

this.widget.onChanged(value.text);
}
}
void _onCursorColorTick() {
this.renderEditable.cursorColor = this.widget.cursorColor.withOpacity(this._cursorBlinkOpacityController.value);
this._cursorVisibilityNotifier.value = this._cursorBlinkOpacityController.value > 0;
}
public bool cursorCurrentlyVisible {
get { return this._cursorVisibilityNotifier.value; }

get { return _kCursorBlinkHalfPeriod; }
}
public TextSelectionOverlay selectionOverlay {
get {
return this._selectionOverlay;
}
}
int _obscureShowCharTicksPending = 0;
int _obscureLatestCharIndex;
this._targetCursorVisibility = !this._targetCursorVisibility;
float targetOpacity = this._targetCursorVisibility ? 1.0f : 0.0f;
if (this.widget.cursorOpacityAnimates) {
this._cursorBlinkOpacityController.animateTo(targetOpacity, curve: Curves.easeOut);
} else {
this._cursorBlinkOpacityController.setValue(targetOpacity);
}
void _cursorWaitForStart() {
D.assert(_kCursorBlinkHalfPeriod > _fadeDuration);
this._cursorTimer?.cancel();
this._cursorTimer = Window.instance.run(_kCursorBlinkHalfPeriod, this._cursorTick, periodic: true);
}
this._targetCursorVisibility = true;
this._cursorBlinkOpacityController.setValue(1.0f);
this._cursorTimer = Window.instance.run(_kCursorBlinkHalfPeriod, this._cursorTick,
periodic: true);
}
if (EditableText.debugDeterministicCursor)
return;
void _stopCursorTimer() {
if (this._cursorTimer != null) {
this._cursorTimer.cancel();
if (this.widget.cursorOpacityAnimates) {
this._cursorTimer = Window.instance.run(_kCursorBlinkWaitForStart, this._cursorWaitForStart, periodic: true);
}
else {
this._cursorTimer = Window.instance.run(_kCursorBlinkHalfPeriod, this._cursorTick, periodic: true);
}
void _stopCursorTimer(bool resetCharTicks = true) {
this._cursorTimer?.cancel();
this._targetCursorVisibility = false;
this._cursorBlinkOpacityController.setValue(0.0f);
this._obscureShowCharTicksPending = 0;
if (EditableText.debugDeterministicCursor)
return;
if (resetCharTicks)
this._obscureShowCharTicksPending = 0;
if (this.widget.cursorOpacityAnimates) {
this._cursorBlinkOpacityController.stop();
this._cursorBlinkOpacityController.setValue(0.0f);
}
}
void _startOrStopCursorTimerIfNeeded() {

this._formatAndSetValue(value);
}
}
float _devicePixelRatio {
get { return MediaQuery.of(this.context).devicePixelRatio; }
}
bool showToolbar() {
if (this._selectionOverlay == null)
return false;
this._selectionOverlay.showToolbar();
return true;
}
public void hideToolbar() {
this._selectionOverlay?.hide();

axisDirection: this._isMultiline ? AxisDirection.down : AxisDirection.right,
controller: this._scrollController,
physics: new ClampingScrollPhysics(),
dragStartBehavior: this.widget.dragStartBehavior,
viewportBuilder: (BuildContext _context, ViewportOffset offset) =>
new CompositedTransformTarget(
link: this._layerLink,

value: this._value,
cursorColor: this.widget.cursorColor,
showCursor: this._cursorVisibilityNotifier,
cursorColor: this._cursorColor,
// backgroundCursorColor: this.widget.backgroundCursorColor, // TODO
showCursor: EditableText.debugDeterministicCursor
? new ValueNotifier<bool>(true)
: this._cursorVisibilityNotifier,
hasFocus: this._hasFocus,
maxLines: this.widget.maxLines,
selectionColor: this.widget.selectionColor,

rendererIgnoresPointer: this.widget.rendererIgnoresPointer,
cursorWidth: this.widget.cursorWidth,
cursorRadius: this.widget.cursorRadius,
// cursorOffset: this.widget.cursorOffset, // TODO
// paintCursorAboveText: this.widget.paintCursorAboveText, // TODO
// devicePixelRatio: _devicePixelRatio // TODO
)
)
);

public readonly TextSpan textSpan;
public readonly TextEditingValue value;
public readonly Color cursorColor;
public readonly Color backgroundColor;
public readonly ValueNotifier<bool> showCursor;
public readonly bool hasFocus;
public readonly int? maxLines;

public readonly bool rendererIgnoresPointer;
public readonly float? cursorWidth;
public readonly Radius cursorRadius;
public readonly Offset cursorOffset;
public readonly bool? paintCursorAboveText;
public readonly float? devicePixelRatio;
Color cursorColor = null, ValueNotifier<bool> showCursor = null, bool hasFocus = false,
Color cursorColor = null, Color backgroundColor = null, ValueNotifier<bool> showCursor = null, bool hasFocus = false,
Radius cursorRadius = null, bool enableInteractiveSelection = true) : base(key) {
Radius cursorRadius = null, Offset cursorOffset = null, bool enableInteractiveSelection = true,
bool? paintCursorAboveText = null, float? devicePixelRatio = null) : base(key) {
this.backgroundColor = backgroundColor;
this.showCursor = showCursor;
this.hasFocus = hasFocus;
this.maxLines = maxLines;

this.textSelectionDelegate = textSelectionDelegate;
this.cursorWidth = cursorWidth;
this.cursorRadius = cursorRadius;
this.cursorOffset = cursorOffset;
this.paintCursorAboveText = paintCursorAboveText;
this.devicePixelRatio = devicePixelRatio;
}
public override RenderObject createRenderObject(BuildContext context) {

offset: this.offset,
showCursor: this.showCursor,
cursorColor: this.cursorColor,
// backgroundColor: this.backgroundColor, // TODO
hasFocus: this.hasFocus,
maxLines: this.maxLines,
selectionColor: this.selectionColor,

ignorePointer: this.rendererIgnoresPointer,
cursorWidth: this.cursorWidth ?? 1.0f,
cursorRadius: this.cursorRadius,
// cursorOffset: this.cursorOffset, // TODO
// paintCursorAboveText: this.paintCursorAboveText, // TODO
// devicePixelRatio: this.devicePixelRatio // TODO
);
}

edit.cursorColor = this.cursorColor;
// edit.backgroundColor = this.backgroundColor; // TODO
edit.showCursor = this.showCursor;
edit.hasFocus = this.hasFocus;
edit.maxLines = this.maxLines;

edit.textSelectionDelegate = this.textSelectionDelegate;
edit.cursorWidth = this.cursorWidth ?? 1.0f;
edit.cursorRadius = this.cursorRadius;
// edit.cursorOffset = this.cursorOffset; // TODO
// edit.paintCursorAboveText = this.paintCursorAboveText; // TODO
// edit.devicePixelRatio = this.devicePixelRatio; // TODO
}
}
}

6
Runtime/widgets/icon_theme_data.cs


public static IconThemeData lerp(IconThemeData a, IconThemeData b, float t) {
return new IconThemeData(
color: Color.lerp(a.color, b.color, t),
opacity: MathUtils.lerpNullableFloat(a.opacity, b.opacity, t),
size: MathUtils.lerpNullableFloat(a.size, b.size, t));
color: Color.lerp(a?.color, b?.color, t),
opacity: MathUtils.lerpNullableFloat(a?.opacity, b?.opacity, t),
size: MathUtils.lerpNullableFloat(a?.size, b?.size, t));
}

正在加载...
取消
保存