@@ -61,8 +61,10 @@ void main() {
6161 updateData ({
6262 int index = 0 ,
6363 }) {
64- final appendStr = 'updateData' * 10 ;
65- key.currentState? .dataList[index] += appendStr;
64+ key.currentState? .updateData (
65+ index: index,
66+ needSetState: true ,
67+ );
6668 }
6769
6870 observerController.jumpTo (index: firstDisplayingChildIndex);
@@ -165,6 +167,100 @@ void main() {
165167 scrollController.dispose ();
166168 });
167169
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+
168264 testWidgets ('Keeping position with customAdjustPositionDelta' ,
169265 (tester) async {
170266 GlobalKey <ChatListViewState > key = GlobalKey ();
@@ -388,22 +484,34 @@ class ChatListView extends StatefulWidget {
388484 required this .chatScrollObserver,
389485 this .onReceiveScrollNotification,
390486 this .itemBuilder,
487+ this .dataList,
391488 }) : super (key: key);
392489
393490 final ScrollController scrollController;
394491 final ListObserverController observerController;
395492 final ChatScrollObserver chatScrollObserver;
396493 final Function ()? onReceiveScrollNotification;
397494 final NullableIndexedWidgetBuilder ? itemBuilder;
495+ final List <String >? dataList;
398496
399497 @override
400498 State <ChatListView > createState () => ChatListViewState ();
401499}
402500
403501class ChatListViewState extends State <ChatListView > {
404- List <String > dataList =
502+ late List <String > dataList = widget.dataList ??
405503 List .generate (100 , (index) => index.toString ()).toList ();
406504
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+
407515 void updateData ({
408516 int index = 0 ,
409517 String ? appendStr,
0 commit comments