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
fb5b1570
Unverified
Commit
fb5b1570
authored
Aug 19, 2019
by
Gary Qian
Committed by
GitHub
Aug 19, 2019
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Clamp scrollOffset to prevent textfield bouncing (#38573)
parent
1c0c3896
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
109 additions
and
2 deletions
+109
-2
editable.dart
packages/flutter/lib/src/rendering/editable.dart
+8
-2
editable_text.dart
packages/flutter/lib/src/widgets/editable_text.dart
+8
-0
editable_test.dart
packages/flutter/test/rendering/editable_test.dart
+43
-0
editable_text_test.dart
packages/flutter/test/widgets/editable_text_test.dart
+50
-0
No files found.
packages/flutter/lib/src/rendering/editable.dart
View file @
fb5b1570
...
@@ -1017,6 +1017,14 @@ class RenderEditable extends RenderBox {
...
@@ -1017,6 +1017,14 @@ class RenderEditable extends RenderBox {
return
enableInteractiveSelection
??
!
obscureText
;
return
enableInteractiveSelection
??
!
obscureText
;
}
}
/// The maximum amount the text is allowed to scroll.
///
/// This value is only valid after layout and can change as additional
/// text is entered or removed in order to accommodate expanding when
/// [expands] is set to true.
double
get
maxScrollExtent
=>
_maxScrollExtent
;
double
_maxScrollExtent
=
0
;
double
get
_caretMargin
=>
_kCaretGap
+
cursorWidth
;
double
get
_caretMargin
=>
_kCaretGap
+
cursorWidth
;
@override
@override
...
@@ -1229,8 +1237,6 @@ class RenderEditable extends RenderBox {
...
@@ -1229,8 +1237,6 @@ class RenderEditable extends RenderBox {
return
null
;
return
null
;
}
}
double
_maxScrollExtent
=
0
;
// We need to check the paint offset here because during animation, the start of
// We need to check the paint offset here because during animation, the start of
// the text may position outside the visible region even when the text fits.
// the text may position outside the visible region even when the text fits.
bool
get
_hasVisualOverflow
=>
_maxScrollExtent
>
0
||
_paintOffset
!=
Offset
.
zero
;
bool
get
_hasVisualOverflow
=>
_maxScrollExtent
>
0
||
_paintOffset
!=
Offset
.
zero
;
...
...
packages/flutter/lib/src/widgets/editable_text.dart
View file @
fb5b1570
...
@@ -1286,6 +1286,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
...
@@ -1286,6 +1286,7 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
caretStart
=
caretRect
.
top
-
caretOffset
;
caretStart
=
caretRect
.
top
-
caretOffset
;
caretEnd
=
caretRect
.
bottom
+
caretOffset
;
caretEnd
=
caretRect
.
bottom
+
caretOffset
;
}
else
{
}
else
{
// Scrolls horizontally for single-line fields.
caretStart
=
caretRect
.
left
;
caretStart
=
caretRect
.
left
;
caretEnd
=
caretRect
.
right
;
caretEnd
=
caretRect
.
right
;
}
}
...
@@ -1297,6 +1298,13 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
...
@@ -1297,6 +1298,13 @@ class EditableTextState extends State<EditableText> with AutomaticKeepAliveClien
}
else
if
(
caretEnd
>=
viewportExtent
)
{
// cursor after end of bounds
}
else
if
(
caretEnd
>=
viewportExtent
)
{
// cursor after end of bounds
scrollOffset
+=
caretEnd
-
viewportExtent
;
scrollOffset
+=
caretEnd
-
viewportExtent
;
}
}
if
(
_isMultiline
)
{
// Clamp the final results to prevent programmatically scrolling to
// out-of-paragraph-bounds positions when encountering tall fonts/scripts that
// extend past the ascent.
scrollOffset
=
scrollOffset
.
clamp
(
0.0
,
renderEditable
.
maxScrollExtent
);
}
return
scrollOffset
;
return
scrollOffset
;
}
}
...
...
packages/flutter/test/rendering/editable_test.dart
View file @
fb5b1570
...
@@ -544,4 +544,47 @@ void main() {
...
@@ -544,4 +544,47 @@ void main() {
editable
.
hasFocus
=
false
;
editable
.
hasFocus
=
false
;
expect
(
editable
.
hasFocus
,
false
);
expect
(
editable
.
hasFocus
,
false
);
});
});
test
(
'has correct maxScrollExtent'
,
()
{
final
TextSelectionDelegate
delegate
=
FakeEditableTextState
();
EditableText
.
debugDeterministicCursor
=
true
;
final
RenderEditable
editable
=
RenderEditable
(
maxLines:
2
,
backgroundCursorColor:
Colors
.
grey
,
textDirection:
TextDirection
.
ltr
,
cursorColor:
const
Color
.
fromARGB
(
0xFF
,
0xFF
,
0x00
,
0x00
),
offset:
ViewportOffset
.
zero
(),
textSelectionDelegate:
delegate
,
text:
const
TextSpan
(
text:
'撒地方加咖啡哈金凤凰卡号方式剪坏算法发挥福建垃
\n
asfjafjajfjaslfjaskjflasjfksajf撒分开建安路口附近拉设
\n
计费可使肌肤撒附近埃里克圾房卡设计费"'
,
style:
TextStyle
(
height:
1.0
,
fontSize:
10.0
,
fontFamily:
'Roboto'
,
),
),
startHandleLayerLink:
LayerLink
(),
endHandleLayerLink:
LayerLink
(),
selection:
const
TextSelection
.
collapsed
(
offset:
4
,
affinity:
TextAffinity
.
upstream
,
),
);
editable
.
layout
(
BoxConstraints
.
loose
(
const
Size
(
100.0
,
1000.0
)));
expect
(
editable
.
size
,
equals
(
const
Size
(
100
,
20
)));
expect
(
editable
.
maxLines
,
equals
(
2
));
expect
(
editable
.
maxScrollExtent
,
equals
(
90
));
editable
.
layout
(
BoxConstraints
.
loose
(
const
Size
(
150.0
,
1000.0
)));
expect
(
editable
.
maxScrollExtent
,
equals
(
50
));
editable
.
layout
(
BoxConstraints
.
loose
(
const
Size
(
200.0
,
1000.0
)));
expect
(
editable
.
maxScrollExtent
,
equals
(
40
));
editable
.
layout
(
BoxConstraints
.
loose
(
const
Size
(
500.0
,
1000.0
)));
expect
(
editable
.
maxScrollExtent
,
equals
(
10
));
editable
.
layout
(
BoxConstraints
.
loose
(
const
Size
(
1000.0
,
1000.0
)));
expect
(
editable
.
maxScrollExtent
,
equals
(
10
));
});
}
}
packages/flutter/test/widgets/editable_text_test.dart
View file @
fb5b1570
...
@@ -2568,6 +2568,56 @@ void main() {
...
@@ -2568,6 +2568,56 @@ void main() {
debugDefaultTargetPlatformOverride
=
null
;
debugDefaultTargetPlatformOverride
=
null
;
},
skip:
isBrowser
);
},
skip:
isBrowser
);
testWidgets
(
'scrolling doesn
\'
t bounce'
,
(
WidgetTester
tester
)
async
{
// 3 lines of text, where the last line overflows and requires scrolling.
const
String
testText
=
'XXXXX
\n
XXXXX
\n
XXXXX'
;
final
TextEditingController
controller
=
TextEditingController
(
text:
testText
);
await
tester
.
pumpWidget
(
MaterialApp
(
home:
Align
(
alignment:
Alignment
.
topLeft
,
child:
SizedBox
(
width:
100
,
child:
EditableText
(
showSelectionHandles:
true
,
maxLines:
2
,
controller:
controller
,
focusNode:
FocusNode
(),
style:
Typography
(
platform:
TargetPlatform
.
android
).
black
.
subhead
.
copyWith
(
fontFamily:
'Roboto'
),
cursorColor:
Colors
.
blue
,
backgroundCursorColor:
Colors
.
grey
,
selectionControls:
materialTextSelectionControls
,
keyboardType:
TextInputType
.
text
,
),
),
),
));
final
EditableTextState
state
=
tester
.
state
<
EditableTextState
>(
find
.
byType
(
EditableText
));
final
RenderEditable
renderEditable
=
state
.
renderEditable
;
final
Scrollable
scrollable
=
tester
.
widget
<
Scrollable
>(
find
.
byType
(
Scrollable
));
expect
(
scrollable
.
controller
.
position
.
viewportDimension
,
equals
(
28
));
expect
(
scrollable
.
controller
.
position
.
pixels
,
equals
(
0
));
expect
(
renderEditable
.
maxScrollExtent
,
equals
(
14
));
scrollable
.
controller
.
jumpTo
(
20.0
);
await
tester
.
pump
();
expect
(
scrollable
.
controller
.
position
.
pixels
,
equals
(
20
));
state
.
bringIntoView
(
const
TextPosition
(
offset:
0
));
await
tester
.
pump
();
expect
(
scrollable
.
controller
.
position
.
pixels
,
equals
(
0
));
state
.
bringIntoView
(
const
TextPosition
(
offset:
13
));
await
tester
.
pump
();
expect
(
scrollable
.
controller
.
position
.
pixels
,
equals
(
14
));
expect
(
scrollable
.
controller
.
position
.
pixels
,
equals
(
renderEditable
.
maxScrollExtent
));
},
skip:
isBrowser
);
}
}
class
MockTextSelectionControls
extends
Mock
implements
TextSelectionControls
{
class
MockTextSelectionControls
extends
Mock
implements
TextSelectionControls
{
...
...
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