Merge pull request #2207 from Hixie/size-obs-5
SizeObserver crusade: RawInputLine
This commit is contained in:
commit
e843d9d0af
@ -9,6 +9,7 @@ import 'package:flutter/gestures.dart';
|
||||
import 'basic_types.dart';
|
||||
import 'box.dart';
|
||||
import 'object.dart';
|
||||
import 'viewport.dart';
|
||||
|
||||
const _kCaretGap = 1.0; // pixels
|
||||
const _kCaretHeightOffset = 2.0; // pixels
|
||||
@ -24,9 +25,9 @@ class RenderEditableLine extends RenderBox {
|
||||
bool showCursor: false,
|
||||
Color selectionColor,
|
||||
TextSelection selection,
|
||||
Offset paintOffset: Offset.zero,
|
||||
this.onSelectionChanged,
|
||||
this.onContentSizeChanged
|
||||
Offset paintOffset: Offset.zero,
|
||||
this.onPaintOffsetUpdateNeeded
|
||||
}) : _textPainter = new TextPainter(text),
|
||||
_cursorColor = cursorColor,
|
||||
_showCursor = showCursor,
|
||||
@ -45,8 +46,8 @@ class RenderEditableLine extends RenderBox {
|
||||
..onTapCancel = _handleTapCancel;
|
||||
}
|
||||
|
||||
ValueChanged<Size> onContentSizeChanged;
|
||||
ValueChanged<TextSelection> onSelectionChanged;
|
||||
ViewportDimensionsChangeCallback onPaintOffsetUpdateNeeded;
|
||||
|
||||
/// The text to display
|
||||
TextSpan get text => _textPainter.text;
|
||||
@ -201,16 +202,15 @@ class RenderEditableLine extends RenderBox {
|
||||
Rect _caretPrototype;
|
||||
|
||||
void performLayout() {
|
||||
Size oldSize = hasSize ? size : null;
|
||||
size = new Size(constraints.maxWidth, constraints.constrainHeight(_preferredHeight));
|
||||
_caretPrototype = new Rect.fromLTWH(0.0, _kCaretHeightOffset, _kCaretWidth, size.height - 2.0 * _kCaretHeightOffset);
|
||||
_selectionRects = null;
|
||||
_layoutText(new BoxConstraints(minHeight: constraints.minHeight, maxHeight: constraints.maxHeight));
|
||||
Size contentSize = new Size(_textPainter.width + _kCaretGap + _kCaretWidth, _textPainter.height);
|
||||
if (_contentSize != contentSize) {
|
||||
_contentSize = contentSize;
|
||||
if (onContentSizeChanged != null)
|
||||
onContentSizeChanged(_contentSize);
|
||||
}
|
||||
if (onPaintOffsetUpdateNeeded != null && (size != oldSize || contentSize != _contentSize))
|
||||
onPaintOffsetUpdateNeeded(new ViewportDimensions(containerSize: size, contentSize: contentSize));
|
||||
_contentSize = contentSize;
|
||||
}
|
||||
|
||||
void _paintCaret(Canvas canvas, Offset effectiveOffset) {
|
||||
|
@ -189,9 +189,6 @@ class RawInputLineState extends ScrollableState<RawInputLine> {
|
||||
Timer _cursorTimer;
|
||||
bool _showCursor = false;
|
||||
|
||||
double _contentWidth = 0.0;
|
||||
double _containerWidth = 0.0;
|
||||
|
||||
_KeyboardClientImpl _keyboardClient;
|
||||
KeyboardHandle _keyboardHandle;
|
||||
|
||||
@ -218,24 +215,28 @@ class RawInputLineState extends ScrollableState<RawInputLine> {
|
||||
|
||||
bool get _isAttachedToKeyboard => _keyboardHandle != null && _keyboardHandle.attached;
|
||||
|
||||
void _handleContainerSizeChanged(Size newSize) {
|
||||
_containerWidth = newSize.width;
|
||||
_updateScrollBehavior();
|
||||
}
|
||||
double _contentWidth = 0.0;
|
||||
double _containerWidth = 0.0;
|
||||
|
||||
void _handleContentSizeChanged(Size newSize) {
|
||||
_contentWidth = newSize.width;
|
||||
_updateScrollBehavior();
|
||||
}
|
||||
|
||||
void _updateScrollBehavior() {
|
||||
// Set the scroll offset to match the content width so that the cursor
|
||||
// (which is always at the end of the text) will be visible.
|
||||
Offset _handlePaintOffsetUpdateNeeded(ViewportDimensions dimensions) {
|
||||
// We make various state changes here but don't have to do so in a
|
||||
// setState() callback because we are called during layout and all
|
||||
// we're updating is the new offset, which we are providing to the
|
||||
// render object via our return value.
|
||||
_containerWidth = dimensions.containerSize.width;
|
||||
_contentWidth = dimensions.contentSize.width;
|
||||
scrollTo(scrollBehavior.updateExtents(
|
||||
contentExtent: _contentWidth,
|
||||
containerExtent: _containerWidth,
|
||||
scrollOffset: _contentWidth
|
||||
// Set the scroll offset to match the content width so that the
|
||||
// cursor (which is always at the end of the text) will be
|
||||
// visible.
|
||||
// TODO(ianh): We should really only do this when text is added,
|
||||
// not generally any time the size changes.
|
||||
scrollOffset: pixelOffsetToScrollOffset(-_contentWidth)
|
||||
));
|
||||
updateGestureDetector();
|
||||
return scrollOffsetToPixelDelta(scrollOffset);
|
||||
}
|
||||
|
||||
void _attachOrDetachKeyboard(bool focused) {
|
||||
@ -327,19 +328,16 @@ class RawInputLineState extends ScrollableState<RawInputLine> {
|
||||
else if (_cursorTimer != null && (!focused || !config.value.selection.isCollapsed))
|
||||
_stopCursorTimer();
|
||||
|
||||
return new SizeObserver(
|
||||
onSizeChanged: _handleContainerSizeChanged,
|
||||
child: new _EditableLineWidget(
|
||||
value: config.value,
|
||||
style: config.style,
|
||||
cursorColor: config.cursorColor,
|
||||
showCursor: _showCursor,
|
||||
selectionColor: config.selectionColor,
|
||||
hideText: config.hideText,
|
||||
onContentSizeChanged: _handleContentSizeChanged,
|
||||
onSelectionChanged: _handleSelectionChanged,
|
||||
paintOffset: new Offset(-scrollOffset, 0.0)
|
||||
)
|
||||
return new _EditableLineWidget(
|
||||
value: config.value,
|
||||
style: config.style,
|
||||
cursorColor: config.cursorColor,
|
||||
showCursor: _showCursor,
|
||||
selectionColor: config.selectionColor,
|
||||
hideText: config.hideText,
|
||||
onSelectionChanged: _handleSelectionChanged,
|
||||
paintOffset: scrollOffsetToPixelDelta(scrollOffset),
|
||||
onPaintOffsetUpdateNeeded: _handlePaintOffsetUpdateNeeded
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -353,9 +351,9 @@ class _EditableLineWidget extends LeafRenderObjectWidget {
|
||||
this.showCursor,
|
||||
this.selectionColor,
|
||||
this.hideText,
|
||||
this.onContentSizeChanged,
|
||||
this.onSelectionChanged,
|
||||
this.paintOffset
|
||||
this.paintOffset,
|
||||
this.onPaintOffsetUpdateNeeded
|
||||
}) : super(key: key);
|
||||
|
||||
final InputValue value;
|
||||
@ -364,9 +362,9 @@ class _EditableLineWidget extends LeafRenderObjectWidget {
|
||||
final bool showCursor;
|
||||
final Color selectionColor;
|
||||
final bool hideText;
|
||||
final ValueChanged<Size> onContentSizeChanged;
|
||||
final ValueChanged<TextSelection> onSelectionChanged;
|
||||
final Offset paintOffset;
|
||||
final ViewportDimensionsChangeCallback onPaintOffsetUpdateNeeded;
|
||||
|
||||
RenderEditableLine createRenderObject() {
|
||||
return new RenderEditableLine(
|
||||
@ -375,9 +373,9 @@ class _EditableLineWidget extends LeafRenderObjectWidget {
|
||||
showCursor: showCursor,
|
||||
selectionColor: selectionColor,
|
||||
selection: value.selection,
|
||||
onContentSizeChanged: onContentSizeChanged,
|
||||
onSelectionChanged: onSelectionChanged,
|
||||
paintOffset: paintOffset
|
||||
paintOffset: paintOffset,
|
||||
onPaintOffsetUpdateNeeded: onPaintOffsetUpdateNeeded
|
||||
);
|
||||
}
|
||||
|
||||
@ -389,9 +387,9 @@ class _EditableLineWidget extends LeafRenderObjectWidget {
|
||||
..showCursor = showCursor
|
||||
..selectionColor = selectionColor
|
||||
..selection = value.selection
|
||||
..onContentSizeChanged = onContentSizeChanged
|
||||
..onSelectionChanged = onSelectionChanged
|
||||
..paintOffset = paintOffset;
|
||||
..paintOffset = paintOffset
|
||||
..onPaintOffsetUpdateNeeded = onPaintOffsetUpdateNeeded;
|
||||
}
|
||||
|
||||
TextSpan get _styledTextSpan {
|
||||
|
@ -380,6 +380,10 @@ abstract class ScrollableState<T extends Scrollable> extends State<T> {
|
||||
///
|
||||
/// If a non-null [duration] is provided, the widget will animate to the new
|
||||
/// scroll offset over the given duration with the given curve.
|
||||
///
|
||||
/// This function does not accept a zero duration. To jump-scroll to
|
||||
/// the new offset, do not provide a duration, rather than providing
|
||||
/// a zero duration.
|
||||
Future scrollTo(double newScrollOffset, { Duration duration, Curve curve: Curves.ease }) {
|
||||
if (newScrollOffset == _scrollOffset)
|
||||
return new Future.value();
|
||||
@ -390,6 +394,7 @@ abstract class ScrollableState<T extends Scrollable> extends State<T> {
|
||||
return new Future.value();
|
||||
}
|
||||
|
||||
assert(duration > Duration.ZERO);
|
||||
return _animateTo(newScrollOffset, duration, curve);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user