-
-
Notifications
You must be signed in to change notification settings - Fork 47
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[How to use] Update shrinkWrap state of ChatScrollObserver after initially fetching list data #92
Comments
Please provide a reproducible example. Why do you need to keep the scroll position when the list goes from no data to data? In addition, it should be noted that the prerequisite for the function of keeping the scroll position is that there must be an item in the list that can be used as a reference. |
Here is the repo with example: https://github.com/nikita488/scrollview_observer_test |
I haven't reproduced the problem you mentioned, maybe you can record a video demonstration.
I see you have set And I noticed that the initial list data has made the list exceed one screen, but You can make the following adjustments (I am not familiar with the use of bloc, you can adjust it more reasonably). class _MainAppState extends State<MainApp> {
...
@override
void initState() {
...
super.initState();
+ context.read<MessageListCubit>().chatObserver = chatObserver;
}
...
} class MessageListCubit extends Cubit<MessageListState> {
...
+ ChatScrollObserver? chatObserver;
Future<void> loadMessages() async {
...
+ chatObserver?.standby();
+ // or call
+ // chatObserver?.observeSwitchShrinkWrap();
emit(state.copyWith(
status: MessageListStatus.success,
items: _items.values.toList(growable: false),
lastMessageId: 0));
}
...
} |
2024-09-06_09-10-02.mp4Here is the video demonstration. When i scroll up (much higher than fixedPositionOffset) and press Add button for the first time, my list jumps, and then after i click Add button more, it stays in place as expected. Adding standy() or observeSwitchShrinkWrap() to Cubit seems to work fine, but what is better to use in this case? When I call standy method, it has changeCount setted to 1 by default, is it fine in this case? Also, should I move my ListViewObserver inside BlocBuilder widget, so that it gets rebuild everytime ListView rebuilds too? |
Which one to use depends on your purpose. flutter_scrollview_observer/lib/src/utils/src/chat/chat_scroll_observer.dart Lines 97 to 121 in 091db3b
Optional, but if you haven’t moved ListViewObserver inside BlocBuilder widget, you’ll need to call |
Gotcha. I changed my code a bit to show loading indicator on initial build, and on success build a ListView, and now the jumping on initial list build problem is back again. I updated my repo, here I build loading indicator: https://github.com/nikita488/scrollview_observer_test/blob/master/lib/main.dart#L80 Can this be fixed? |
Since your ListView does not always appear, it is recommended that you modify it as follows. class _MainAppState extends State<MainApp> {
...
late final ChatScrollObserver chatObserver;
+ BuildContext? listViewCtx;
@override
void initState() {
...
}
...
Expanded(
child: ListViewObserver(
controller: observerController,
+ sliverListContexts: () {
+ return [
+ if (listViewCtx != null) listViewCtx!,
+ ];
+ },
child: BlocBuilder<MessageListCubit, MessageListState>(
buildWhen: (previous, current) => current.status.isSuccess,
builder: (context, state) {
final items = state.items;
if (state.status == MessageListStatus.initial) {
return const Center(child: CircularProgressIndicator());
} else {
print('Rebuild List: ${chatObserver.isShrinkWrap}');
Widget resultWidget = ListView.builder(
controller: scrollController,
reverse: true,
physics: ChatObserverClampingScrollPhysics(
observer: chatObserver),
shrinkWrap: chatObserver.isShrinkWrap,
itemCount: items.length,
itemBuilder: (context, index) {
+ if (listViewCtx != context) {
+ listViewCtx = context;
+ observerController.reattach();
+ print('NEEDS REATTACH');
+ // Waiting for reattach to complete
+ WidgetsBinding.instance
+ .addPostFrameCallback((timeStamp) {
+ chatObserver.observeSwitchShrinkWrap();
+ });
+ }
- if (scrollController.hasClients &&
- (observerController.sliverContexts.isEmpty ||
- observerController.sliverContexts.first !=
- context)) {
- observerController.reattach();
- print('NEEDS REATTACH');
- }
final itemIndex = index;
final reversedIndex = items.length - itemIndex - 1;
final item = items[reversedIndex];
return ListTile(
title: Text(item.text),
leading: const Icon(Icons.message));
});
return resultWidget;
}
}),
),
),
... |
Thank you very much for your help and explanation, works like a charm now! Also thank you for your hard work on this package, will use it more in the near future. |
Platforms
Android, Web
Description
I want to have a list of items that will keep it's scroll position everytime new item is added or old item is removed.
Initially i don't have list items, so when i open page with this list it fetch data via REST method and wait for response to get initial items list.
But it seems that ChatScrollObserver observeSwitchShrinkWrap tries to observe it when creating ChatScrollObserver object in the initState method, which observes it at the end of the frame, but initial list data might be not loaded at this point.
In this case when i use standby method and add item to list later, it didn't initially keep the scroll position (made a slight jump), but then it switches shrinkWrap state and after that scroll position is keeped when adding more items to list.
How to handle this?
My code
No response
Try do it
No response
The text was updated successfully, but these errors were encountered: