@@ -61,8 +61,10 @@ void main() {
61
61
updateData ({
62
62
int index = 0 ,
63
63
}) {
64
- final appendStr = 'updateData' * 10 ;
65
- key.currentState? .dataList[index] += appendStr;
64
+ key.currentState? .updateData (
65
+ index: index,
66
+ needSetState: true ,
67
+ );
66
68
}
67
69
68
70
observerController.jumpTo (index: firstDisplayingChildIndex);
@@ -165,6 +167,100 @@ void main() {
165
167
scrollController.dispose ();
166
168
});
167
169
170
+ testWidgets (
171
+ 'Keeping position with ChatScrollObserverHandleMode.specified when item changes by itself' ,
172
+ (tester) async {
173
+ GlobalKey <ChatListViewState > key = GlobalKey ();
174
+ final scrollController = ScrollController ();
175
+ final observerController = ListObserverController (
176
+ controller: scrollController,
177
+ );
178
+ final chatScrollObserver = ChatScrollObserver (observerController)
179
+ ..fixedPositionOffset = - 1 ;
180
+ const observeItemSelfIndex = 0 ;
181
+
182
+ Widget widget = ChatListView (
183
+ key: key,
184
+ scrollController: scrollController,
185
+ observerController: observerController,
186
+ chatScrollObserver: chatScrollObserver,
187
+ itemBuilder: (context, index) {
188
+ final dataList = key.currentState? .dataList ?? [];
189
+ return Text (
190
+ dataList[index],
191
+ maxLines: 999 ,
192
+ );
193
+ },
194
+ dataList: ['initData' * 500 ],
195
+ );
196
+ await tester.pumpWidget (widget);
197
+
198
+ void updateData ({
199
+ int index = 0 ,
200
+ }) {
201
+ key.currentState? .updateData (
202
+ index: index,
203
+ needSetState: true ,
204
+ );
205
+ }
206
+
207
+ await tester.pumpAndSettle ();
208
+ var result = await observerController.dispatchOnceObserve (
209
+ isDependObserveCallback: false ,
210
+ isForce: true ,
211
+ );
212
+ expectSync (
213
+ result.observeResult? .firstChild? .index ?? 0 ,
214
+ observeItemSelfIndex,
215
+ );
216
+ expectSync (
217
+ result.observeResult? .firstChild? .mainAxisSize,
218
+ greaterThanOrEqualTo (
219
+ result.observeResult? .viewport.paintBounds.height ?? 0 ,
220
+ ),
221
+ );
222
+ final previousTrailingMarginToViewport =
223
+ result.observeResult? .firstChild? .trailingMarginToViewport;
224
+
225
+ // itemIndex
226
+ await chatScrollObserver.standby (
227
+ mode: ChatScrollObserverHandleMode .specified,
228
+ refIndexType: ChatScrollObserverRefIndexType .itemIndex,
229
+ refItemIndex: observeItemSelfIndex,
230
+ refItemIndexAfterUpdate: observeItemSelfIndex,
231
+ customAdjustPositionDelta: (model) {
232
+ return model.newPosition.extentAfter - model.oldPosition.extentAfter;
233
+ },
234
+ );
235
+
236
+ updateData ();
237
+ await tester.pumpAndSettle ();
238
+ result = await observerController.dispatchOnceObserve (
239
+ isDependObserveCallback: false ,
240
+ isForce: true ,
241
+ );
242
+
243
+ expect (chatScrollObserver.refItemIndex, observeItemSelfIndex);
244
+ expect (
245
+ chatScrollObserver.refItemIndexAfterUpdate,
246
+ observeItemSelfIndex,
247
+ );
248
+ result = await observerController.dispatchOnceObserve (
249
+ isDependObserveCallback: false ,
250
+ isForce: true ,
251
+ );
252
+ expectSync (
253
+ result.observeResult? .firstChild? .index,
254
+ observeItemSelfIndex,
255
+ );
256
+ expectSync (
257
+ result.observeResult? .firstChild? .trailingMarginToViewport,
258
+ previousTrailingMarginToViewport,
259
+ );
260
+
261
+ scrollController.dispose ();
262
+ });
263
+
168
264
testWidgets ('Keeping position with customAdjustPositionDelta' ,
169
265
(tester) async {
170
266
GlobalKey <ChatListViewState > key = GlobalKey ();
@@ -388,22 +484,34 @@ class ChatListView extends StatefulWidget {
388
484
required this .chatScrollObserver,
389
485
this .onReceiveScrollNotification,
390
486
this .itemBuilder,
487
+ this .dataList,
391
488
}) : super (key: key);
392
489
393
490
final ScrollController scrollController;
394
491
final ListObserverController observerController;
395
492
final ChatScrollObserver chatScrollObserver;
396
493
final Function ()? onReceiveScrollNotification;
397
494
final NullableIndexedWidgetBuilder ? itemBuilder;
495
+ final List <String >? dataList;
398
496
399
497
@override
400
498
State <ChatListView > createState () => ChatListViewState ();
401
499
}
402
500
403
501
class ChatListViewState extends State <ChatListView > {
404
- List <String > dataList =
502
+ late List <String > dataList = widget.dataList ??
405
503
List .generate (100 , (index) => index.toString ()).toList ();
406
504
505
+ void initData ({
506
+ required List <String > dataList,
507
+ bool needSetState = true ,
508
+ }) {
509
+ this .dataList = dataList;
510
+ if (needSetState) {
511
+ setState (() {});
512
+ }
513
+ }
514
+
407
515
void updateData ({
408
516
int index = 0 ,
409
517
String ? appendStr,
0 commit comments