@@ -67,38 +67,38 @@ void main() {
67
67
68
68
for (final reverse in [true , false ]) {
69
69
for (final reverseHeader in [true , false ]) {
70
- for (final allowOverflow in [true , false ]) {
71
- final name = 'sticky headers: '
72
- 'scroll ${reverse ? 'up' : 'down' }, '
73
- 'header at ${reverseHeader ? 'bottom' : 'top' }, '
74
- 'headers ${allowOverflow ? 'overflow' : 'bounded' }' ;
75
- testWidgets (name, (tester) =>
76
- _checkSequence (tester,
77
- Axis .vertical,
78
- reverse: reverse,
79
- reverseHeader: reverseHeader,
80
- allowOverflow: allowOverflow,
81
- ));
82
- }
83
- }
84
- }
85
-
86
- for (final reverse in [true , false ]) {
87
- for (final reverseHeader in [true , false ]) {
88
- for (final allowOverflow in [true , false ]) {
89
- for (final textDirection in TextDirection .values) {
70
+ for (final growthDirection in GrowthDirection .values) {
71
+ for (final allowOverflow in [true , false ]) {
90
72
final name = 'sticky headers: '
91
- '${ textDirection . name . toUpperCase ()} '
92
- 'scroll ${ reverse ? 'backward ' : 'forward ' }, '
93
- 'header at ${ reverseHeader ? 'end' : 'start' } , '
73
+ 'scroll ${ reverse ? 'up' : 'down' }, '
74
+ 'header at ${ reverseHeader ? 'bottom ' : 'top ' }, '
75
+ '$ growthDirection , '
94
76
'headers ${allowOverflow ? 'overflow' : 'bounded' }' ;
95
77
testWidgets (name, (tester) =>
96
78
_checkSequence (tester,
97
- Axis .horizontal, textDirection : textDirection ,
79
+ Axis .vertical ,
98
80
reverse: reverse,
99
81
reverseHeader: reverseHeader,
82
+ growthDirection: growthDirection,
100
83
allowOverflow: allowOverflow,
101
84
));
85
+
86
+ for (final textDirection in TextDirection .values) {
87
+ final name = 'sticky headers: '
88
+ '${textDirection .name .toUpperCase ()} '
89
+ 'scroll ${reverse ? 'backward' : 'forward' }, '
90
+ 'header at ${reverseHeader ? 'end' : 'start' }, '
91
+ '$growthDirection , '
92
+ 'headers ${allowOverflow ? 'overflow' : 'bounded' }' ;
93
+ testWidgets (name, (tester) =>
94
+ _checkSequence (tester,
95
+ Axis .horizontal, textDirection: textDirection,
96
+ reverse: reverse,
97
+ reverseHeader: reverseHeader,
98
+ growthDirection: growthDirection,
99
+ allowOverflow: allowOverflow,
100
+ ));
101
+ }
102
102
}
103
103
}
104
104
}
@@ -111,28 +111,43 @@ Future<void> _checkSequence(
111
111
TextDirection ? textDirection,
112
112
bool reverse = false ,
113
113
bool reverseHeader = false ,
114
+ GrowthDirection growthDirection = GrowthDirection .forward,
114
115
required bool allowOverflow,
115
116
}) async {
116
117
assert (textDirection != null || axis == Axis .vertical);
117
118
final headerAtCoordinateEnd = switch (axis) {
118
119
Axis .horizontal => reverseHeader ^ (textDirection == TextDirection .rtl),
119
120
Axis .vertical => reverseHeader,
120
121
};
122
+ final reverseGrowth = (growthDirection == GrowthDirection .reverse);
121
123
122
124
final controller = ScrollController ();
125
+ const listKey = ValueKey ("list" );
126
+ const emptyKey = ValueKey ("empty" );
123
127
await tester.pumpWidget (Directionality (
124
128
textDirection: textDirection ?? TextDirection .rtl,
125
- child: StickyHeaderListView (
129
+ child: CustomScrollView (
126
130
controller: controller,
127
131
scrollDirection: axis,
128
132
reverse: reverse,
129
- reverseHeader: reverseHeader,
130
- children: List .generate (100 , (i) => StickyHeaderItem (
131
- allowOverflow: allowOverflow,
132
- header: _Header (i, height: 20 ),
133
- child: _Item (i, height: 100 ))))));
134
-
135
- final overallSize = tester.getSize (find.byType (StickyHeaderListView ));
133
+ anchor: reverseGrowth ? 1.0 : 0.0 ,
134
+ center: reverseGrowth ? emptyKey : listKey,
135
+ slivers: [
136
+ SliverStickyHeaderList (
137
+ key: listKey,
138
+ headerPlacement: (reverseHeader ^ reverse)
139
+ ? HeaderPlacement .scrollingEnd : HeaderPlacement .scrollingStart,
140
+ delegate: SliverChildListDelegate (
141
+ List .generate (100 , (i) => StickyHeaderItem (
142
+ allowOverflow: allowOverflow,
143
+ header: _Header (i, height: 20 ),
144
+ child: _Item (i, height: 100 ))))),
145
+ const SliverPadding (
146
+ key: emptyKey,
147
+ padding: EdgeInsets .zero),
148
+ ])));
149
+
150
+ final overallSize = tester.getSize (find.byType (CustomScrollView ));
136
151
final extent = overallSize.onAxis (axis);
137
152
assert (extent % 100 == 0 );
138
153
@@ -143,7 +158,7 @@ Future<void> _checkSequence(
143
158
(extent / 2 - inset) * (headerAtCoordinateEnd ? 1 : - 1 ));
144
159
}
145
160
146
- final first = ! (reverse ^ reverseHeader);
161
+ final first = ! (reverse ^ reverseHeader ^ reverseGrowth );
147
162
148
163
final itemFinder = first ? find.byType (_Item ).first : find.byType (_Item ).last;
149
164
@@ -155,10 +170,11 @@ Future<void> _checkSequence(
155
170
156
171
Future <void > checkState () async {
157
172
// Check the header comes from the expected item.
158
- final scrollOffset = controller.position.pixels;
173
+ final scrollOffset = controller.position.pixels * (reverseGrowth ? - 1 : 1 ) ;
159
174
final expectedHeaderIndex = first
160
175
? (scrollOffset / 100 ).floor ()
161
176
: (extent ~ / 100 - 1 ) + (scrollOffset / 100 ).ceil ();
177
+ // print("$scrollOffset, $extent, $expectedHeaderIndex");
162
178
check (tester.widget <_Item >(itemFinder).index).equals (expectedHeaderIndex);
163
179
check (_headerIndex (tester)).equals (expectedHeaderIndex);
164
180
@@ -180,7 +196,7 @@ Future<void> _checkSequence(
180
196
}
181
197
182
198
Future <void > jumpAndCheck (double position) async {
183
- controller.jumpTo (position);
199
+ controller.jumpTo (position * (reverseGrowth ? - 1 : 1 ) );
184
200
await tester.pump ();
185
201
await checkState ();
186
202
}
0 commit comments