Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
527fddc6
Commit
527fddc6
authored
Feb 16, 2017
by
Adam Barth
Committed by
GitHub
Feb 16, 2017
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Port EditableText to Scrollable2 (#8167)
parent
3985ddbc
Changes
6
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
169 additions
and
163 deletions
+169
-163
rendering.dart
packages/flutter/lib/rendering.dart
+1
-1
input.dart
packages/flutter/lib/src/material/input.dart
+0
-1
editable.dart
packages/flutter/lib/src/rendering/editable.dart
+106
-58
editable_text.dart
packages/flutter/lib/src/widgets/editable_text.dart
+57
-98
single_child_scroll_view.dart
...ges/flutter/lib/src/widgets/single_child_scroll_view.dart
+4
-4
input_test.dart
packages/flutter/test/widgets/input_test.dart
+1
-1
No files found.
packages/flutter/lib/rendering.dart
View file @
527fddc6
...
...
@@ -28,7 +28,7 @@ export 'src/rendering/block.dart';
export
'src/rendering/box.dart'
;
export
'src/rendering/custom_layout.dart'
;
export
'src/rendering/debug.dart'
;
export
'src/rendering/editable
_line
.dart'
;
export
'src/rendering/editable.dart'
;
export
'src/rendering/error.dart'
;
export
'src/rendering/flex.dart'
;
export
'src/rendering/flow.dart'
;
...
...
packages/flutter/lib/src/material/input.dart
View file @
527fddc6
...
...
@@ -147,7 +147,6 @@ class _InputFieldState extends State<InputField> {
cursorColor:
themeData
.
textSelectionColor
,
selectionColor:
themeData
.
textSelectionColor
,
selectionControls:
materialTextSelectionControls
,
platform:
Theme
.
of
(
context
).
platform
,
keyboardType:
config
.
keyboardType
,
onChanged:
config
.
onChanged
,
onSubmitted:
config
.
onSubmitted
,
...
...
packages/flutter/lib/src/rendering/editable
_line
.dart
→
packages/flutter/lib/src/rendering/editable.dart
View file @
527fddc6
...
...
@@ -2,13 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'dart:math'
as
math
;
import
'dart:ui'
as
ui
show
TextBox
;
import
'package:flutter/gestures.dart'
;
import
'package:meta/meta.dart'
;
import
'box.dart'
;
import
'object.dart'
;
import
'viewport.dart'
;
import
'viewport
_offset
.dart'
;
const
double
_kCaretGap
=
1.0
;
// pixels
const
double
_kCaretHeightOffset
=
2.0
;
// pixels
...
...
@@ -39,14 +41,6 @@ class TextSelectionPoint {
final
TextDirection
direction
;
}
/// Signature for the callback used by [RenderEditable] to determine the paint offset when
/// the dimensions of the render box change.
///
/// The return value should be the new paint offset to use.
///
/// Used by [RenderEditable.onPaintOffsetUpdateNeeded].
typedef
Offset
RenderEditablePaintOffsetNeededCallback
(
ViewportDimensions
dimensions
,
Rect
caretRect
);
/// A single line of editable text.
class
RenderEditable
extends
RenderBox
{
/// Creates a render object for a single line of editable text.
...
...
@@ -58,15 +52,18 @@ class RenderEditable extends RenderBox {
Color
selectionColor
,
double
textScaleFactor:
1.0
,
TextSelection
selection
,
@required
ViewportOffset
offset
,
this
.
onSelectionChanged
,
Offset
paintOffset:
Offset
.
zero
,
this
.
onPaintOffsetUpdateNeeded
,
})
:
_textPainter
=
new
TextPainter
(
text:
text
,
textScaleFactor:
textScaleFactor
),
_cursorColor
=
cursorColor
,
_showCursor
=
showCursor
,
_maxLines
=
maxLines
,
_selection
=
selection
,
_paintOffset
=
paintOffset
{
_offset
=
offset
{
assert
(
showCursor
!=
null
);
assert
(
maxLines
!=
null
);
assert
(
textScaleFactor
!=
null
);
assert
(
offset
!=
null
);
assert
(!
showCursor
||
cursorColor
!=
null
);
_tap
=
new
TapGestureRecognizer
()
..
onTapDown
=
_handleTapDown
...
...
@@ -79,9 +76,6 @@ class RenderEditable extends RenderBox {
/// Called when the selection changes.
SelectionChangedHandler
onSelectionChanged
;
/// Called when the inner or outer dimensions of this render object change.
RenderEditablePaintOffsetNeededCallback
onPaintOffsetUpdateNeeded
;
/// The text to display
TextSpan
get
text
=>
_textPainter
.
text
;
final
TextPainter
_textPainter
;
...
...
@@ -106,6 +100,7 @@ class RenderEditable extends RenderBox {
bool
get
showCursor
=>
_showCursor
;
bool
_showCursor
;
set
showCursor
(
bool
value
)
{
assert
(
value
!=
null
);
if
(
_showCursor
==
value
)
return
;
_showCursor
=
value
;
...
...
@@ -118,6 +113,7 @@ class RenderEditable extends RenderBox {
int
get
maxLines
=>
_maxLines
;
int
_maxLines
;
set
maxLines
(
int
value
)
{
assert
(
value
!=
null
);
if
(
_maxLines
==
value
)
return
;
_maxLines
=
value
;
...
...
@@ -165,15 +161,58 @@ class RenderEditable extends RenderBox {
/// If the text content is larger than the editable line itself, the editable
/// line clips the text. This property controls which part of the text is
/// visible by shifting the text by the given offset before clipping.
Offset
get
paintOffset
=>
_paintOffset
;
Offset
_paintOffset
;
set
paintOffset
(
Offset
value
)
{
if
(
_paintOffset
==
value
)
ViewportOffset
get
offset
=>
_offset
;
ViewportOffset
_offset
;
set
offset
(
ViewportOffset
value
)
{
assert
(
value
!=
null
);
if
(
_offset
==
value
)
return
;
_paintOffset
=
value
;
markNeedsPaint
();
if
(
attached
)
_offset
.
removeListener
(
markNeedsPaint
);
_offset
=
value
;
if
(
attached
)
_offset
.
addListener
(
markNeedsPaint
);
markNeedsLayout
();
}
bool
get
_isMultiline
=>
maxLines
>
1
;
Axis
get
_viewportAxis
=>
_isMultiline
?
Axis
.
vertical
:
Axis
.
horizontal
;
Offset
get
_paintOffset
{
switch
(
_viewportAxis
)
{
case
Axis
.
horizontal
:
return
new
Offset
(-
offset
.
pixels
,
0.0
);
case
Axis
.
vertical
:
return
new
Offset
(
0.0
,
-
offset
.
pixels
);
}
return
null
;
}
double
get
_viewportExtent
{
assert
(
hasSize
);
switch
(
_viewportAxis
)
{
case
Axis
.
horizontal
:
return
size
.
width
;
case
Axis
.
vertical
:
return
size
.
height
;
}
return
null
;
}
double
_getMaxScrollExtent
(
Size
contentSize
)
{
assert
(
hasSize
);
switch
(
_viewportAxis
)
{
case
Axis
.
horizontal
:
return
math
.
max
(
0.0
,
contentSize
.
width
-
size
.
width
);
case
Axis
.
vertical
:
return
math
.
max
(
0.0
,
contentSize
.
height
-
size
.
height
);
}
return
null
;
}
bool
_hasVisualOverflow
=
false
;
/// Returns the global coordinates of the endpoints of the given selection.
///
/// If the selection is collapsed (and therefore occupies a single point), the
...
...
@@ -187,17 +226,17 @@ class RenderEditable extends RenderBox {
// clean at this point.
_textPainter
.
layout
(
maxWidth:
_maxContentWidth
);
Offset
o
ffset
=
_paintOffset
;
final
Offset
paintO
ffset
=
_paintOffset
;
if
(
selection
.
isCollapsed
)
{
// TODO(mpcomplete): This doesn't work well at an RTL/LTR boundary.
Offset
caretOffset
=
_textPainter
.
getOffsetForCaret
(
selection
.
extent
,
_caretPrototype
);
Point
start
=
new
Point
(
0.0
,
_preferredLineHeight
)
+
caretOffset
+
o
ffset
;
final
Offset
caretOffset
=
_textPainter
.
getOffsetForCaret
(
selection
.
extent
,
_caretPrototype
);
final
Point
start
=
new
Point
(
0.0
,
_preferredLineHeight
)
+
caretOffset
+
paintO
ffset
;
return
<
TextSelectionPoint
>[
new
TextSelectionPoint
(
localToGlobal
(
start
),
null
)];
}
else
{
List
<
ui
.
TextBox
>
boxes
=
_textPainter
.
getBoxesForSelection
(
selection
);
Point
start
=
new
Point
(
boxes
.
first
.
start
,
boxes
.
first
.
bottom
)
+
o
ffset
;
Point
end
=
new
Point
(
boxes
.
last
.
end
,
boxes
.
last
.
bottom
)
+
o
ffset
;
final
List
<
ui
.
TextBox
>
boxes
=
_textPainter
.
getBoxesForSelection
(
selection
);
final
Point
start
=
new
Point
(
boxes
.
first
.
start
,
boxes
.
first
.
bottom
)
+
paintO
ffset
;
final
Point
end
=
new
Point
(
boxes
.
last
.
end
,
boxes
.
last
.
bottom
)
+
paintO
ffset
;
return
<
TextSelectionPoint
>[
new
TextSelectionPoint
(
localToGlobal
(
start
),
boxes
.
first
.
direction
),
new
TextSelectionPoint
(
localToGlobal
(
end
),
boxes
.
last
.
direction
),
...
...
@@ -207,26 +246,24 @@ class RenderEditable extends RenderBox {
/// Returns the position in the text for the given global coordinate.
TextPosition
getPositionForPoint
(
Point
globalPosition
)
{
globalPosition
+=
-
paintOffset
;
globalPosition
+=
-
_
paintOffset
;
return
_textPainter
.
getPositionForOffset
(
globalToLocal
(
globalPosition
).
toOffset
());
}
/// Returns the Rect in local coordinates for the caret at the given text
/// position.
Rect
getLocalRectForCaret
(
TextPosition
caretPosition
)
{
Offset
caretOffset
=
_textPainter
.
getOffsetForCaret
(
caretPosition
,
_caretPrototype
);
final
Offset
caretOffset
=
_textPainter
.
getOffsetForCaret
(
caretPosition
,
_caretPrototype
);
// This rect is the same as _caretPrototype but without the vertical padding.
return
new
Rect
.
fromLTWH
(
0.0
,
0.0
,
_kCaretWidth
,
_preferredLineHeight
).
shift
(
caretOffset
+
_paintOffset
);
}
Size
_contentSize
;
double
get
_preferredLineHeight
=>
_textPainter
.
preferredLineHeight
;
double
get
_maxContentWidth
{
return
_maxLines
>
1
?
constraints
.
maxWidth
-
(
_kCaretGap
+
_kCaretWidth
)
:
double
.
INFINITY
;
if
(
_maxLines
>
1
)
return
constraints
.
maxWidth
-
(
_kCaretGap
+
_kCaretWidth
);
return
double
.
INFINITY
;
}
@override
...
...
@@ -257,15 +294,15 @@ class RenderEditable extends RenderBox {
Point
_lastTapDownPosition
;
Point
_longPressPosition
;
void
_handleTapDown
(
TapDownDetails
details
)
{
_lastTapDownPosition
=
details
.
globalPosition
+
-
paintOffset
;
_lastTapDownPosition
=
details
.
globalPosition
+
-
_
paintOffset
;
}
void
_handleTap
()
{
assert
(
_lastTapDownPosition
!=
null
);
final
Point
global
=
_lastTapDownPosition
;
final
Point
global
Position
=
_lastTapDownPosition
;
_lastTapDownPosition
=
null
;
if
(
onSelectionChanged
!=
null
)
{
TextPosition
position
=
_textPainter
.
getPositionForOffset
(
globalToLocal
(
global
).
toOffset
());
TextPosition
position
=
_textPainter
.
getPositionForOffset
(
globalToLocal
(
global
Position
).
toOffset
());
onSelectionChanged
(
new
TextSelection
.
fromPosition
(
position
),
this
,
false
);
}
}
...
...
@@ -277,16 +314,16 @@ class RenderEditable extends RenderBox {
}
void
_handleLongPress
()
{
final
Point
global
=
_longPressPosition
;
final
Point
global
Position
=
_longPressPosition
;
_longPressPosition
=
null
;
if
(
onSelectionChanged
!=
null
)
{
TextPosition
position
=
_textPainter
.
getPositionForOffset
(
globalToLocal
(
global
).
toOffset
());
final
TextPosition
position
=
_textPainter
.
getPositionForOffset
(
globalToLocal
(
globalPosition
).
toOffset
());
onSelectionChanged
(
_selectWordAtOffset
(
position
),
this
,
true
);
}
}
TextSelection
_selectWordAtOffset
(
TextPosition
position
)
{
TextRange
word
=
_textPainter
.
getWordBoundary
(
position
);
final
TextRange
word
=
_textPainter
.
getWordBoundary
(
position
);
// When long-pressing past the end of the text, we want a collapsed cursor.
if
(
position
.
offset
>=
word
.
end
)
return
new
TextSelection
.
fromPosition
(
position
);
...
...
@@ -297,41 +334,34 @@ class RenderEditable extends RenderBox {
@override
void
performLayout
()
{
Size
oldSize
=
hasSize
?
size
:
null
;
_caretPrototype
=
new
Rect
.
fromLTWH
(
0.0
,
_kCaretHeightOffset
,
_kCaretWidth
,
_preferredLineHeight
-
2.0
*
_kCaretHeightOffset
);
_selectionRects
=
null
;
_textPainter
.
layout
(
maxWidth:
_maxContentWidth
);
size
=
new
Size
(
constraints
.
maxWidth
,
constraints
.
constrainHeight
(
_textPainter
.
height
.
clamp
(
_preferredLineHeight
,
_preferredLineHeight
*
_maxLines
)
));
Size
contentSize
=
new
Size
(
_textPainter
.
width
+
_kCaretGap
+
_kCaretWidth
,
_textPainter
.
height
);
assert
(
_selection
!=
null
);
Rect
caretRect
=
getLocalRectForCaret
(
_selection
.
extent
);
if
(
onPaintOffsetUpdateNeeded
!=
null
&&
(
size
!=
oldSize
||
contentSize
!=
_contentSize
||
!
_withinBounds
(
caretRect
)))
onPaintOffsetUpdateNeeded
(
new
ViewportDimensions
(
containerSize:
size
,
contentSize:
contentSize
),
caretRect
);
_contentSize
=
contentSize
;
}
bool
_withinBounds
(
Rect
caretRect
)
{
Rect
bounds
=
new
Rect
.
fromLTWH
(
0.0
,
0.0
,
size
.
width
,
size
.
height
);
return
(
bounds
.
contains
(
caretRect
.
topLeft
)
&&
bounds
.
contains
(
caretRect
.
bottomRight
));
final
Size
contentSize
=
new
Size
(
_textPainter
.
width
+
_kCaretGap
+
_kCaretWidth
,
_textPainter
.
height
);
final
double
_maxScrollExtent
=
_getMaxScrollExtent
(
contentSize
);
_hasVisualOverflow
=
_maxScrollExtent
>
0.0
;
offset
.
applyViewportDimension
(
_viewportExtent
);
offset
.
applyContentDimensions
(
0.0
,
_maxScrollExtent
);
}
void
_paintCaret
(
Canvas
canvas
,
Offset
effectiveOffset
)
{
Offset
caretOffset
=
_textPainter
.
getOffsetForCaret
(
_selection
.
extent
,
_caretPrototype
);
Paint
paint
=
new
Paint
()..
color
=
_cursorColor
;
final
Offset
caretOffset
=
_textPainter
.
getOffsetForCaret
(
_selection
.
extent
,
_caretPrototype
);
final
Paint
paint
=
new
Paint
()..
color
=
_cursorColor
;
canvas
.
drawRect
(
_caretPrototype
.
shift
(
caretOffset
+
effectiveOffset
),
paint
);
}
void
_paintSelection
(
Canvas
canvas
,
Offset
effectiveOffset
)
{
assert
(
_selectionRects
!=
null
);
Paint
paint
=
new
Paint
()..
color
=
_selectionColor
;
final
Paint
paint
=
new
Paint
()..
color
=
_selectionColor
;
for
(
ui
.
TextBox
box
in
_selectionRects
)
canvas
.
drawRect
(
box
.
toRect
().
shift
(
effectiveOffset
),
paint
);
}
void
_paintContents
(
PaintingContext
context
,
Offset
offset
)
{
Offset
effectiveOffset
=
offset
+
_paintOffset
;
final
Offset
effectiveOffset
=
offset
+
_paintOffset
;
if
(
_selection
!=
null
)
{
if
(
_selection
.
isCollapsed
&&
_showCursor
&&
cursorColor
!=
null
)
{
...
...
@@ -345,8 +375,6 @@ class RenderEditable extends RenderBox {
_textPainter
.
paint
(
context
.
canvas
,
effectiveOffset
);
}
bool
get
_hasVisualOverflow
=>
_contentSize
.
width
>
size
.
width
;
@override
void
paint
(
PaintingContext
context
,
Offset
offset
)
{
if
(
_hasVisualOverflow
)
...
...
@@ -357,4 +385,24 @@ class RenderEditable extends RenderBox {
@override
Rect
describeApproximatePaintClip
(
RenderObject
child
)
=>
_hasVisualOverflow
?
Point
.
origin
&
size
:
null
;
@override
void
debugFillDescription
(
List
<
String
>
description
)
{
super
.
debugFillDescription
(
description
);
description
.
add
(
'cursorColor:
$_cursorColor
'
);
description
.
add
(
'showCursor:
$_showCursor
'
);
description
.
add
(
'maxLines:
$_maxLines
'
);
description
.
add
(
'selectionColor:
$_selectionColor
'
);
description
.
add
(
'textScaleFactor:
$textScaleFactor
'
);
description
.
add
(
'selection:
$_selection
'
);
description
.
add
(
'offset:
$_offset
'
);
}
@override
String
debugDescribeChildren
(
String
prefix
)
{
return
'
$prefix
\
u2558
\
u2550
\
u2566
\
u2550
\
u2550 text
\
u2550
\
u2550
\
u2550
\n
'
'
${text.toString("$prefix \u2551 ")}
'
// TextSpan includes a newline
'
$prefix
\
u255A
\
u2550
\
u2550
\
u2550
\
u2550
\
u2550
\
u2550
\
u2550
\
u2550
\
u2550
\
u2550
\
u2550
\n
'
'
$prefix
\n
'
;
}
}
packages/flutter/lib/src/widgets/editable_text.dart
View file @
527fddc6
...
...
@@ -5,14 +5,15 @@
import
'dart:async'
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter/rendering.dart'
show
RenderEditable
,
SelectionChangedHandler
,
RenderEditablePaintOffsetNeededCallback
;
import
'package:flutter/rendering.dart'
;
import
'package:flutter/services.dart'
;
import
'basic.dart'
;
import
'focus.dart'
;
import
'framework.dart'
;
import
'media_query.dart'
;
import
'scroll_behavior.dart'
;
import
'scroll_controller.dart'
;
import
'scroll_physics.dart'
;
import
'scrollable.dart'
;
import
'text_selection.dart'
;
...
...
@@ -135,32 +136,33 @@ class InputValue {
/// * [InputField], which adds tap-to-focus and cut, copy, and paste commands.
/// * [TextField], which is a full-featured, material-design text input field
/// with placeholder text, labels, and [Form] integration.
class
EditableText
extends
S
crollable
{
// ignore: DEPRECATED_MEMBER_USE
class
EditableText
extends
S
tatefulWidget
{
/// Creates a basic text input control.
///
/// The [value] argument must not be null.
EditableText
({
Key
key
,
@required
this
.
value
,
this
.
focusKey
,
@required
this
.
focusKey
,
this
.
obscureText
:
false
,
this
.
style
,
this
.
cursorColor
,
@required
this
.
style
,
@required
this
.
cursorColor
,
this
.
textScaleFactor
,
int
maxLines:
1
,
this
.
maxLines
:
1
,
this
.
autofocus
:
false
,
this
.
selectionColor
,
this
.
selectionControls
,
@required
this
.
platform
,
this
.
keyboardType
,
this
.
onChanged
,
this
.
onSubmitted
})
:
maxLines
=
maxLines
,
super
(
key:
key
,
initialScrollOffset:
0.0
,
scrollDirection:
maxLines
>
1
?
Axis
.
vertical
:
Axis
.
horizontal
)
{
this
.
onSubmitted
,
})
:
super
(
key:
key
)
{
assert
(
value
!=
null
);
assert
(
focusKey
!=
null
);
assert
(
obscureText
!=
null
);
assert
(
style
!=
null
);
assert
(
cursorColor
!=
null
);
assert
(
maxLines
!=
null
);
assert
(
autofocus
!=
null
);
}
/// The string being displayed in this widget.
...
...
@@ -206,12 +208,6 @@ class EditableText extends Scrollable { // ignore: DEPRECATED_MEMBER_USE
/// Optional delegate for building the text selection handles and toolbar.
final
TextSelectionControls
selectionControls
;
/// The platform whose behavior should be approximated, in particular
/// for scroll physics. (See [ScrollBehavior.platform].)
///
/// Must not be null.
final
TargetPlatform
platform
;
/// The type of keyboard to use for editing the text.
final
TextInputType
keyboardType
;
...
...
@@ -226,7 +222,7 @@ class EditableText extends Scrollable { // ignore: DEPRECATED_MEMBER_USE
}
/// State for a [EditableText].
class
EditableTextState
extends
S
crollableState
<
EditableText
>
implements
TextInputClient
{
// ignore: DEPRECATED_MEMBER_USE
class
EditableTextState
extends
S
tate
<
EditableText
>
implements
TextInputClient
{
Timer
_cursorTimer
;
bool
_showCursor
=
false
;
...
...
@@ -234,11 +230,7 @@ class EditableTextState extends ScrollableState<EditableText> implements TextInp
TextInputConnection
_textInputConnection
;
TextSelectionOverlay
_selectionOverlay
;
@override
ExtentScrollBehavior
createScrollBehavior
()
=>
new
BoundedBehavior
(
platform:
config
.
platform
);
@override
BoundedBehavior
get
scrollBehavior
=>
super
.
scrollBehavior
;
final
ScrollController
_scrollController
=
new
ScrollController
();
@override
void
initState
()
{
...
...
@@ -259,41 +251,17 @@ class EditableTextState extends ScrollableState<EditableText> implements TextInp
bool
get
_isMultiline
=>
config
.
maxLines
>
1
;
double
_contentExtent
=
0.0
;
double
_containerExtent
=
0.0
;
Offset
_handlePaintOffsetUpdateNeeded
(
ViewportDimensions
dimensions
,
Rect
caretRect
)
{
// 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.
_contentExtent
=
_isMultiline
?
dimensions
.
contentSize
.
height
:
dimensions
.
contentSize
.
width
;
_containerExtent
=
_isMultiline
?
dimensions
.
containerSize
.
height
:
dimensions
.
containerSize
.
width
;
didUpdateScrollBehavior
(
scrollBehavior
.
updateExtents
(
contentExtent:
_contentExtent
,
containerExtent:
_containerExtent
,
// TODO(ianh): We should really only do this when text is added,
// not generally any time the size changes.
scrollOffset:
_getScrollOffsetForCaret
(
caretRect
,
_containerExtent
)
));
updateGestureDetector
();
return
scrollOffsetToPixelDelta
(
scrollOffset
);
}
// Calculate the new scroll offset so the cursor remains visible.
double
_getScrollOffsetForCaret
(
Rect
caretRect
,
double
containerExtent
)
{
double
caretStart
=
_isMultiline
?
caretRect
.
top
:
caretRect
.
left
;
double
caretEnd
=
_isMultiline
?
caretRect
.
bottom
:
caretRect
.
right
;
double
newScrollOffset
=
scrollOffset
;
double
_getScrollOffsetForCaret
(
Rect
caretRect
)
{
final
double
caretStart
=
_isMultiline
?
caretRect
.
top
:
caretRect
.
left
;
final
double
caretEnd
=
_isMultiline
?
caretRect
.
bottom
:
caretRect
.
right
;
double
scrollOffset
=
_scrollController
.
offset
;
final
double
viewportExtent
=
_scrollController
.
position
.
viewportDimension
;
if
(
caretStart
<
0.0
)
// cursor before start of bounds
newScrollOffset
+=
pixelOffsetToScrollOffset
(-
caretStart
)
;
else
if
(
caretEnd
>=
container
Extent
)
// cursor after end of bounds
newScrollOffset
+=
pixelOffsetToScrollOffset
(-(
caretEnd
-
containerExtent
))
;
return
newS
crollOffset
;
scrollOffset
+=
caretStart
;
else
if
(
caretEnd
>=
viewport
Extent
)
// cursor after end of bounds
scrollOffset
+=
caretEnd
-
viewportExtent
;
return
s
crollOffset
;
}
// True if the focus was explicitly requested last frame. This ensures we
...
...
@@ -302,8 +270,7 @@ class EditableTextState extends ScrollableState<EditableText> implements TextInp
void
_attachOrDetachKeyboard
(
bool
focused
)
{
if
(
focused
&&
!
_isAttachedToKeyboard
&&
(
_requestingFocus
||
config
.
autofocus
))
{
_textInputConnection
=
TextInput
.
attach
(
this
,
new
TextInputConfiguration
(
inputType:
config
.
keyboardType
))
_textInputConnection
=
TextInput
.
attach
(
this
,
new
TextInputConfiguration
(
inputType:
config
.
keyboardType
))
..
setEditingState
(
_getTextEditingStateFromInputValue
(
_currentValue
))
..
show
();
}
else
if
(!
focused
)
{
...
...
@@ -364,7 +331,7 @@ class EditableTextState extends ScrollableState<EditableText> implements TextInp
// EditableWidget, not just changes triggered by user gestures.
requestKeyboard
();
InputValue
newInput
=
_currentValue
.
copyWith
(
selection:
selection
,
composing:
TextRange
.
empty
);
final
InputValue
newInput
=
_currentValue
.
copyWith
(
selection:
selection
,
composing:
TextRange
.
empty
);
if
(
config
.
onChanged
!=
null
)
config
.
onChanged
(
newInput
);
...
...
@@ -393,14 +360,7 @@ class EditableTextState extends ScrollableState<EditableText> implements TextInp
assert
(!
newInput
.
composing
.
isValid
);
// composing range must be empty while selecting
if
(
config
.
onChanged
!=
null
)
config
.
onChanged
(
newInput
);
didUpdateScrollBehavior
(
scrollBehavior
.
updateExtents
(
// TODO(mpcomplete): should just be able to pass
// scrollBehavior.containerExtent here (and remove the member var), but
// scrollBehavior gets re-created too often, and is sometimes
// uninitialized here. Investigate if this is a bug.
scrollOffset:
_getScrollOffsetForCaret
(
caretRect
,
_containerExtent
)
));
_scrollController
.
jumpTo
(
_getScrollOffsetForCaret
(
caretRect
));
}
/// Whether the blinking cursor is actually visible at this precise moment
...
...
@@ -429,9 +389,12 @@ class EditableTextState extends ScrollableState<EditableText> implements TextInp
_textInputConnection
.
close
();
_textInputConnection
=
null
;
}
assert
(!
_isAttachedToKeyboard
);
if
(
_cursorTimer
!=
null
)
_stopCursorTimer
();
assert
(
_cursorTimer
==
null
);
_selectionOverlay
?.
dispose
();
_selectionOverlay
=
null
;
super
.
dispose
();
}
...
...
@@ -442,11 +405,7 @@ class EditableTextState extends ScrollableState<EditableText> implements TextInp
}
@override
Widget
buildContent
(
BuildContext
context
)
{
assert
(
config
.
style
!=
null
);
assert
(
config
.
focusKey
!=
null
);
assert
(
config
.
cursorColor
!=
null
);
Widget
build
(
BuildContext
context
)
{
bool
focused
=
Focus
.
at
(
config
.
focusKey
.
currentContext
);
_attachOrDetachKeyboard
(
focused
);
...
...
@@ -464,8 +423,12 @@ class EditableTextState extends ScrollableState<EditableText> implements TextInp
}
}
return
new
ClipRect
(
child:
new
_Editable
(
return
new
Scrollable2
(
axisDirection:
_isMultiline
?
AxisDirection
.
down
:
AxisDirection
.
right
,
controller:
_scrollController
,
physics:
const
ClampingScrollPhysics
(),
viewportBuilder:
(
BuildContext
context
,
ViewportOffset
offset
)
{
return
new
_Editable
(
value:
_currentValue
,
style:
config
.
style
,
cursorColor:
config
.
cursorColor
,
...
...
@@ -474,10 +437,10 @@ class EditableTextState extends ScrollableState<EditableText> implements TextInp
selectionColor:
config
.
selectionColor
,
textScaleFactor:
config
.
textScaleFactor
??
MediaQuery
.
of
(
context
).
textScaleFactor
,
obscureText:
config
.
obscureText
,
offset:
offset
,
onSelectionChanged:
_handleSelectionChanged
,
paintOffset:
scrollOffsetToPixelDelta
(
scrollOffset
),
onPaintOffsetUpdateNeeded:
_handlePaintOffsetUpdateNeeded
)
);
},
);
}
}
...
...
@@ -493,9 +456,8 @@ class _Editable extends LeafRenderObjectWidget {
this
.
selectionColor
,
this
.
textScaleFactor
,
this
.
obscureText
,
this
.
offset
,
this
.
onSelectionChanged
,
this
.
paintOffset
,
this
.
onPaintOffsetUpdateNeeded
})
:
super
(
key:
key
);
final
InputValue
value
;
...
...
@@ -506,9 +468,8 @@ class _Editable extends LeafRenderObjectWidget {
final
Color
selectionColor
;
final
double
textScaleFactor
;
final
bool
obscureText
;
final
ViewportOffset
offset
;
final
SelectionChangedHandler
onSelectionChanged
;
final
Offset
paintOffset
;
final
RenderEditablePaintOffsetNeededCallback
onPaintOffsetUpdateNeeded
;
@override
RenderEditable
createRenderObject
(
BuildContext
context
)
{
...
...
@@ -520,9 +481,8 @@ class _Editable extends LeafRenderObjectWidget {
selectionColor:
selectionColor
,
textScaleFactor:
textScaleFactor
,
selection:
value
.
selection
,
offset:
offset
,
onSelectionChanged:
onSelectionChanged
,
paintOffset:
paintOffset
,
onPaintOffsetUpdateNeeded:
onPaintOffsetUpdateNeeded
);
}
...
...
@@ -536,9 +496,8 @@ class _Editable extends LeafRenderObjectWidget {
..
selectionColor
=
selectionColor
..
textScaleFactor
=
textScaleFactor
..
selection
=
value
.
selection
..
onSelectionChanged
=
onSelectionChanged
..
paintOffset
=
paintOffset
..
onPaintOffsetUpdateNeeded
=
onPaintOffsetUpdateNeeded
;
..
offset
=
offset
..
onSelectionChanged
=
onSelectionChanged
;
}
TextSpan
get
_styledTextSpan
{
...
...
packages/flutter/lib/src/widgets/single_child_scroll_view.dart
View file @
527fddc6
...
...
@@ -184,13 +184,13 @@ class _RenderSingleChildViewport extends RenderBox with RenderObjectWithChildMix
@override
bool
get
isRepaintBoundary
=>
true
;
double
get
_
effective
Extent
{
double
get
_
viewport
Extent
{
assert
(
hasSize
);
switch
(
axis
)
{
case
Axis
.
vertical
:
return
size
.
height
;
case
Axis
.
horizontal
:
return
size
.
width
;
case
Axis
.
vertical
:
return
size
.
height
;
}
return
null
;
}
...
...
@@ -265,7 +265,7 @@ class _RenderSingleChildViewport extends RenderBox with RenderObjectWithChildMix
size
=
constraints
.
constrain
(
child
.
size
);
}
offset
.
applyViewportDimension
(
_
effective
Extent
);
offset
.
applyViewportDimension
(
_
viewport
Extent
);
offset
.
applyContentDimensions
(
_minScrollExtent
,
_maxScrollExtent
);
}
...
...
packages/flutter/test/widgets/input_test.dart
View file @
527fddc6
...
...
@@ -581,7 +581,6 @@ void main() {
expect
(
inputValue
.
text
,
cutValue
);
},
skip:
Platform
.
isMacOS
);
// Skip due to https://github.com/flutter/flutter/issues/6961
testWidgets
(
'Can scroll multiline input'
,
(
WidgetTester
tester
)
async
{
GlobalKey
inputKey
=
new
GlobalKey
();
InputValue
inputValue
=
InputValue
.
empty
;
...
...
@@ -640,6 +639,7 @@ void main() {
// Now the first line is scrolled up, and the fourth line is visible.
Point
newFirstPos
=
textOffsetToPosition
(
tester
,
kFourLines
.
indexOf
(
'First'
));
Point
newFourthPos
=
textOffsetToPosition
(
tester
,
kFourLines
.
indexOf
(
'Fourth'
));
expect
(
newFirstPos
.
y
,
lessThan
(
firstPos
.
y
));
expect
(
inputBox
.
hitTest
(
new
HitTestResult
(),
position:
inputBox
.
globalToLocal
(
newFirstPos
)),
isFalse
);
expect
(
inputBox
.
hitTest
(
new
HitTestResult
(),
position:
inputBox
.
globalToLocal
(
newFourthPos
)),
isTrue
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment