Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flutter ListView jumps to top on each setState() call

I have a ListView of customers where the user is able to check/uncheck each customer to mark them as a 'favourite'. However, each time a ListItem is tapped, the ListView jumps back to the top of the screen.

How do I prevent this from happening? I only want the Checkbox to refresh, not the entire screen, and to prevent the screen from jumping to the top each time.

@override
Widget build(BuildContext context) {
  customers = getAllCustomers();

  return Scaffold(
     appBar: _getAppBar(),
     body: customers != null
          ? FutureBuilder(
              future: getFavouriteCustomers(), // contains IDs of favourite customers
              builder: (context, snapshot) {
                if (snapshot.connectionState == ConnectionState.done) {
                  if (snapshot.hasData) {
                    List<String> favouriteCustomersList = snapshot.data;

                    return ListView.builder(
                        itemCount: customers?.length ?? 0,
                        itemBuilder: (BuildContext context, int index) {
                          customer c = customers?.elementAt(index);

                          if (favouriteCustomersList.contains(c.id)) {
                            c.isSelected = true;
                          }

                          return ListTile(
                            title: Text(c.name),
                            trailing: Checkbox(
                                value: c.isFavourite,
                                onChanged: (newValue) {}),
                            onTap: () {
                              if (c.isSelected) {
                                setState(() {
                                  c.setFavourite(false);
                                });
                              } else {
                                setState(() {
                                  c.setFavourite(true);
                                }
                              }
                            },
                          );
                        });
                  }
                } else {
                  return CircularProgressIndicator();
                }
              })
          : Center(
              child: CircularProgressIndicator(),
            );
);

}

like image 484
user2181948 Avatar asked May 15 '19 21:05

user2181948


People also ask

How do you prevent flutter apps from scrolling to top after calling Setstate?

This answer suggests using a custom ScrollController with keepScrollOffset set to true , however this is the default value and setting it explicitly to true therefore does not change anything.

How do I display list dynamic flutter?

We can use ListView. builder(..) in Stateless Widgets if we want to display dynamic (different) contents every time the widget is loaded within an application. With Stateful widgets, it can change the contents of the screen dynamically.

How do I scroll to a specific item in ListView flutter?

All you have to do is set Global Keys for your widgets and call Scrollable. ensureVisible on the key of your widget you want to scroll to. For this to work your ListView should be a finite List of objects.

What is the difference between a ListView and a SingleChildScrollView?

By using ListView, only the items that are visible are mounted and painted. On the other hand, by using SingleChildScrollView+Column, the entire item list is mounted+painted, even if only a few items are visible.


1 Answers

  1. Ensure you are doing this in a StatefulWidget.

  2. Create a ScrollController as field in the state class (not the widget class):

  _controller = ScrollController(keepScrollOffset: true);

This way the controller will be preserved in the state and not recreated on rebuilds.

  1. Pass it to the builder as
  controller: _controller,
  1. Remember to dispose the controller when the state is destroyed:
  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }
  1. As Benno mentioned, ensure that all the way up the widget tree there are no widgets with keys being recreated on rebuilds: How to prevent Flutter app from scrolling to top after calling setState?
like image 88
Alexey Inkin Avatar answered Sep 24 '22 17:09

Alexey Inkin