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
3998549d
Unverified
Commit
3998549d
authored
Mar 20, 2020
by
chunhtai
Committed by
GitHub
Mar 20, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Revert "fixes sliver list child layout offset calculation (#42703)" (#52923)
This reverts commit
11efa00f
.
parent
ec8448d0
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
21 additions
and
182 deletions
+21
-182
sliver.dart
packages/flutter/lib/src/rendering/sliver.dart
+3
-6
sliver_list.dart
packages/flutter/lib/src/rendering/sliver_list.dart
+7
-30
sliver_multi_box_adaptor.dart
...s/flutter/lib/src/rendering/sliver_multi_box_adaptor.dart
+1
-0
sliver.dart
packages/flutter/lib/src/widgets/sliver.dart
+2
-18
slivers_block_test.dart
packages/flutter/test/rendering/slivers_block_test.dart
+7
-9
sliver_list_test.dart
packages/flutter/test/widgets/sliver_list_test.dart
+0
-117
slivers_test.dart
packages/flutter/test/widgets/slivers_test.dart
+1
-2
No files found.
packages/flutter/lib/src/rendering/sliver.dart
View file @
3998549d
...
...
@@ -928,16 +928,13 @@ class SliverLogicalParentData extends ParentData {
///
/// The number of pixels from from the zero scroll offset of the parent sliver
/// (the line at which its [SliverConstraints.scrollOffset] is zero) to the
/// side of the child closest to that offset. A [layoutOffset] can be null
/// when it cannot be determined. The value will be set after layout.
/// side of the child closest to that offset.
///
/// In a typical list, this does not change as the parent is scrolled.
///
/// Defaults to null.
double
layoutOffset
;
double
layoutOffset
=
0.0
;
@override
String
toString
()
=>
'layoutOffset=
${layoutOffset
== null ? 'None': layoutOffset
.toStringAsFixed(1)}
'
;
String
toString
()
=>
'layoutOffset=
${layoutOffset.toStringAsFixed(1)}
'
;
}
/// Parent data for slivers that have multiple children and that position their
...
...
packages/flutter/lib/src/rendering/sliver_list.dart
View file @
3998549d
...
...
@@ -91,28 +91,8 @@ class RenderSliverList extends RenderSliverMultiBoxAdaptor {
// it's possible for a child to get removed without notice.
RenderBox
leadingChildWithLayout
,
trailingChildWithLayout
;
RenderBox
earliestUsefulChild
=
firstChild
;
// A firstChild with null layout offset is likely a result of children
// reordering.
//
// We rely on firstChild to have accurate layout offset. In the case of null
// layout offset, we have to find the first child that has valid layout
// offset.
if
(
childScrollOffset
(
firstChild
)
==
null
)
{
int
leadingChildrenWithoutLayoutOffset
=
0
;
while
(
childScrollOffset
(
earliestUsefulChild
)
==
null
)
{
earliestUsefulChild
=
childAfter
(
firstChild
);
leadingChildrenWithoutLayoutOffset
+=
1
;
}
// We should be able to destroy children with null layout offset safely,
// because they are likely outside of viewport
collectGarbage
(
leadingChildrenWithoutLayoutOffset
,
0
);
assert
(
firstChild
!=
null
);
}
// Find the last child that is at or before the scrollOffset.
earliestUsefulChild
=
firstChild
;
RenderBox
earliestUsefulChild
=
firstChild
;
for
(
double
earliestScrollOffset
=
childScrollOffset
(
earliestUsefulChild
);
earliestScrollOffset
>
scrollOffset
;
earliestScrollOffset
=
childScrollOffset
(
earliestUsefulChild
))
{
...
...
@@ -160,15 +140,12 @@ class RenderSliverList extends RenderSliverMultiBoxAdaptor {
correction
+=
paintExtentOf
(
firstChild
);
earliestUsefulChild
=
insertAndLayoutLeadingChild
(
childConstraints
,
parentUsesSize:
true
);
}
earliestUsefulChild
=
firstChild
;
if
((
correction
-
earliestScrollOffset
).
abs
()
>
precisionErrorTolerance
)
{
geometry
=
SliverGeometry
(
scrollOffsetCorrection:
correction
-
earliestScrollOffset
,
);
final
SliverMultiBoxAdaptorParentData
childParentData
=
firstChild
.
parentData
as
SliverMultiBoxAdaptorParentData
;
childParentData
.
layoutOffset
=
0.0
;
return
;
}
geometry
=
SliverGeometry
(
scrollOffsetCorrection:
correction
-
earliestScrollOffset
,
);
final
SliverMultiBoxAdaptorParentData
childParentData
=
firstChild
.
parentData
as
SliverMultiBoxAdaptorParentData
;
childParentData
.
layoutOffset
=
0.0
;
return
;
}
final
SliverMultiBoxAdaptorParentData
childParentData
=
earliestUsefulChild
.
parentData
as
SliverMultiBoxAdaptorParentData
;
...
...
packages/flutter/lib/src/rendering/sliver_multi_box_adaptor.dart
View file @
3998549d
...
...
@@ -578,6 +578,7 @@ abstract class RenderSliverMultiBoxAdaptor extends RenderSliver
assert
(
child
!=
null
);
assert
(
child
.
parent
==
this
);
final
SliverMultiBoxAdaptorParentData
childParentData
=
child
.
parentData
as
SliverMultiBoxAdaptorParentData
;
assert
(
childParentData
.
layoutOffset
!=
null
);
return
childParentData
.
layoutOffset
;
}
...
...
packages/flutter/lib/src/widgets/sliver.dart
View file @
3998549d
...
...
@@ -1069,7 +1069,6 @@ class SliverMultiBoxAdaptorElement extends RenderObjectElement implements Render
assert
(
_currentlyUpdatingChildIndex
==
null
);
try
{
final
SplayTreeMap
<
int
,
Element
>
newChildren
=
SplayTreeMap
<
int
,
Element
>();
final
Map
<
int
,
double
>
indexToLayoutOffset
=
HashMap
<
int
,
double
>();
void
processElement
(
int
index
)
{
_currentlyUpdatingChildIndex
=
index
;
...
...
@@ -1081,31 +1080,17 @@ class SliverMultiBoxAdaptorElement extends RenderObjectElement implements Render
if
(
newChild
!=
null
)
{
_childElements
[
index
]
=
newChild
;
final
SliverMultiBoxAdaptorParentData
parentData
=
newChild
.
renderObject
.
parentData
as
SliverMultiBoxAdaptorParentData
;
if
(
index
==
0
)
{
parentData
.
layoutOffset
=
0.0
;
}
else
if
(
indexToLayoutOffset
.
containsKey
(
index
))
{
parentData
.
layoutOffset
=
indexToLayoutOffset
[
index
];
}
if
(!
parentData
.
keptAlive
)
_currentBeforeChild
=
newChild
.
renderObject
as
RenderBox
;
}
else
{
_childElements
.
remove
(
index
);
}
}
for
(
final
int
index
in
_childElements
.
keys
.
toList
())
{
final
Key
key
=
_childElements
[
index
].
widget
.
key
;
final
int
newIndex
=
key
==
null
?
null
:
widget
.
delegate
.
findIndexByKey
(
key
);
final
SliverMultiBoxAdaptorParentData
childParentData
=
_childElements
[
index
].
renderObject
?.
parentData
as
SliverMultiBoxAdaptorParentData
;
if
(
childParentData
!=
null
&&
childParentData
.
layoutOffset
!=
null
)
indexToLayoutOffset
[
index
]
=
childParentData
.
layoutOffset
;
if
(
newIndex
!=
null
&&
newIndex
!=
index
)
{
// The layout offset of the child being moved is no longer accurate.
if
(
childParentData
!=
null
)
childParentData
.
layoutOffset
=
null
;
newChildren
[
newIndex
]
=
_childElements
[
index
];
// We need to make sure the original index gets processed.
newChildren
.
putIfAbsent
(
index
,
()
=>
null
);
...
...
@@ -1324,8 +1309,7 @@ class SliverMultiBoxAdaptorElement extends RenderObjectElement implements Render
break
;
}
return
parentData
.
layoutOffset
!=
null
&&
parentData
.
layoutOffset
<
renderObject
.
constraints
.
scrollOffset
+
renderObject
.
constraints
.
remainingPaintExtent
&&
return
parentData
.
layoutOffset
<
renderObject
.
constraints
.
scrollOffset
+
renderObject
.
constraints
.
remainingPaintExtent
&&
parentData
.
layoutOffset
+
itemExtent
>
renderObject
.
constraints
.
scrollOffset
;
}).
forEach
(
visitor
);
}
...
...
packages/flutter/test/rendering/slivers_block_test.dart
View file @
3998549d
...
...
@@ -340,20 +340,18 @@ void main() {
final
SliverMultiBoxAdaptorParentData
candidate
=
SliverMultiBoxAdaptorParentData
();
expect
(
candidate
.
keepAlive
,
isFalse
);
expect
(
candidate
.
index
,
isNull
);
expect
(
candidate
.
toString
(),
'index=null; layoutOffset=
None
'
);
expect
(
candidate
.
toString
(),
'index=null; layoutOffset=
0.0
'
);
candidate
.
keepAlive
=
null
;
expect
(
candidate
.
toString
(),
'index=null; layoutOffset=
None
'
);
expect
(
candidate
.
toString
(),
'index=null; layoutOffset=
0.0
'
);
candidate
.
keepAlive
=
true
;
expect
(
candidate
.
toString
(),
'index=null; keepAlive; layoutOffset=
None
'
);
expect
(
candidate
.
toString
(),
'index=null; keepAlive; layoutOffset=
0.0
'
);
candidate
.
keepAlive
=
false
;
expect
(
candidate
.
toString
(),
'index=null; layoutOffset=
None
'
);
expect
(
candidate
.
toString
(),
'index=null; layoutOffset=
0.0
'
);
candidate
.
index
=
0
;
expect
(
candidate
.
toString
(),
'index=0; layoutOffset=
None
'
);
expect
(
candidate
.
toString
(),
'index=0; layoutOffset=
0.0
'
);
candidate
.
index
=
1
;
expect
(
candidate
.
toString
(),
'index=1; layoutOffset=
None
'
);
expect
(
candidate
.
toString
(),
'index=1; layoutOffset=
0.0
'
);
candidate
.
index
=
-
1
;
expect
(
candidate
.
toString
(),
'index=-1; layoutOffset=None'
);
candidate
.
layoutOffset
=
100.0
;
expect
(
candidate
.
toString
(),
'index=-1; layoutOffset=100.0'
);
expect
(
candidate
.
toString
(),
'index=-1; layoutOffset=0.0'
);
});
}
packages/flutter/test/widgets/sliver_list_test.dart
View file @
3998549d
...
...
@@ -163,118 +163,6 @@ void main() {
expect
(
find
.
text
(
'Tile 1'
),
findsOneWidget
);
expect
(
find
.
text
(
'Tile 2'
),
findsOneWidget
);
});
testWidgets
(
'SliverList should recalculate inaccurate layout offset case 1'
,
(
WidgetTester
tester
)
async
{
// Regression test for https://github.com/flutter/flutter/issues/42142.
final
List
<
int
>
items
=
List
<
int
>.
generate
(
20
,
(
int
i
)
=>
i
);
final
ScrollController
controller
=
ScrollController
();
await
tester
.
pumpWidget
(
_buildSliverList
(
items:
List
<
int
>.
from
(
items
),
controller:
controller
,
itemHeight:
50
,
viewportHeight:
200
,
)
);
await
tester
.
pumpAndSettle
();
await
tester
.
drag
(
find
.
text
(
'Tile 2'
),
const
Offset
(
0.0
,
-
1000.0
));
await
tester
.
pumpAndSettle
();
// Viewport should be scrolled to the end of list.
expect
(
controller
.
offset
,
800.0
);
expect
(
find
.
text
(
'Tile 15'
),
findsNothing
);
expect
(
find
.
text
(
'Tile 16'
),
findsOneWidget
);
expect
(
find
.
text
(
'Tile 17'
),
findsOneWidget
);
expect
(
find
.
text
(
'Tile 18'
),
findsOneWidget
);
expect
(
find
.
text
(
'Tile 19'
),
findsOneWidget
);
// Prepends item to the list.
items
.
insert
(
0
,
-
1
);
await
tester
.
pumpWidget
(
_buildSliverList
(
items:
List
<
int
>.
from
(
items
),
controller:
controller
,
itemHeight:
50
,
viewportHeight:
200
,
)
);
await
tester
.
pump
();
// We need second pump to ensure the scheduled animation gets run.
await
tester
.
pumpAndSettle
();
// Scroll offset should stay the same, and the items in viewport should be
// shifted by one.
expect
(
controller
.
offset
,
800.0
);
expect
(
find
.
text
(
'Tile 14'
),
findsNothing
);
expect
(
find
.
text
(
'Tile 15'
),
findsOneWidget
);
expect
(
find
.
text
(
'Tile 16'
),
findsOneWidget
);
expect
(
find
.
text
(
'Tile 17'
),
findsOneWidget
);
expect
(
find
.
text
(
'Tile 18'
),
findsOneWidget
);
expect
(
find
.
text
(
'Tile 19'
),
findsNothing
);
// Drags back to beginning and newly added item is visible.
await
tester
.
drag
(
find
.
text
(
'Tile 16'
),
const
Offset
(
0.0
,
1000.0
));
await
tester
.
pumpAndSettle
();
expect
(
controller
.
offset
,
0.0
);
expect
(
find
.
text
(
'Tile -1'
),
findsOneWidget
);
expect
(
find
.
text
(
'Tile 0'
),
findsOneWidget
);
expect
(
find
.
text
(
'Tile 1'
),
findsOneWidget
);
expect
(
find
.
text
(
'Tile 2'
),
findsOneWidget
);
expect
(
find
.
text
(
'Tile 3'
),
findsNothing
);
});
testWidgets
(
'SliverList should recalculate inaccurate layout offset case 2'
,
(
WidgetTester
tester
)
async
{
// Regression test for https://github.com/flutter/flutter/issues/42142.
final
List
<
int
>
items
=
List
<
int
>.
generate
(
20
,
(
int
i
)
=>
i
);
final
ScrollController
controller
=
ScrollController
();
await
tester
.
pumpWidget
(
_buildSliverList
(
items:
List
<
int
>.
from
(
items
),
controller:
controller
,
itemHeight:
50
,
viewportHeight:
200
,
)
);
await
tester
.
pumpAndSettle
();
await
tester
.
drag
(
find
.
text
(
'Tile 2'
),
const
Offset
(
0.0
,
-
1000.0
));
await
tester
.
pumpAndSettle
();
// Viewport should be scrolled to the end of list.
expect
(
controller
.
offset
,
800.0
);
expect
(
find
.
text
(
'Tile 15'
),
findsNothing
);
expect
(
find
.
text
(
'Tile 16'
),
findsOneWidget
);
expect
(
find
.
text
(
'Tile 17'
),
findsOneWidget
);
expect
(
find
.
text
(
'Tile 18'
),
findsOneWidget
);
expect
(
find
.
text
(
'Tile 19'
),
findsOneWidget
);
// Reorders item to the front. This should make item 19 to be first child
// with layout offset = null.
final
int
swap
=
items
[
19
];
items
[
19
]
=
items
[
3
];
items
[
3
]
=
swap
;
await
tester
.
pumpWidget
(
_buildSliverList
(
items:
List
<
int
>.
from
(
items
),
controller:
controller
,
itemHeight:
50
,
viewportHeight:
200
,
)
);
await
tester
.
pump
();
// We need second pump to ensure the scheduled animation gets run.
await
tester
.
pumpAndSettle
();
// Scroll offset should stay the same
expect
(
controller
.
offset
,
800.0
);
expect
(
find
.
text
(
'Tile 14'
),
findsNothing
);
expect
(
find
.
text
(
'Tile 15'
),
findsNothing
);
expect
(
find
.
text
(
'Tile 16'
),
findsOneWidget
);
expect
(
find
.
text
(
'Tile 17'
),
findsOneWidget
);
expect
(
find
.
text
(
'Tile 18'
),
findsOneWidget
);
expect
(
find
.
text
(
'Tile 3'
),
findsOneWidget
);
});
}
Widget
_buildSliverListRenderWidgetChild
(
List
<
String
>
items
)
{
...
...
@@ -328,11 +216,6 @@ Widget _buildSliverList({
child:
Text
(
'Tile
${items[i]}
'
),
);
},
findChildIndexCallback:
(
Key
key
)
{
final
ValueKey
<
int
>
valueKey
=
key
as
ValueKey
<
int
>;
final
int
index
=
items
.
indexOf
(
valueKey
.
value
);
return
index
==
-
1
?
null
:
index
;
},
childCount:
items
.
length
,
),
),
...
...
packages/flutter/test/widgets/slivers_test.dart
View file @
3998549d
...
...
@@ -50,8 +50,7 @@ Future<void> testSliverFixedExtentList(WidgetTester tester, List<String> items)
findChildIndexCallback:
(
Key
key
)
{
final
ValueKey
<
String
>
valueKey
=
key
as
ValueKey
<
String
>;
final
String
data
=
valueKey
.
value
;
final
int
index
=
items
.
indexOf
(
data
);
return
index
==
-
1
?
null
:
index
;
return
items
.
indexOf
(
data
);
},
),
),
...
...
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