How to save scroll position of listview while doing setstate in Flutter?

Viewed 1162

I have list of products . While adding them to cart I am doing setstate and updating ui with number of items to the cart. While doing setstate my listview is going to first position. What I want it to be on the same scroll position where I added the item to cart? Any idea how to do this?`

getCart() async {
    Result response = await authService.fetchCart();
    loading = true;
    if (response is SuccessState) {
      if (response.value['status'] == true) {
        List tempCart = [];
        for (var i = 0; i < response.value['data'].length; i++) {
          if (response.value['data'][i]['type'] == 'Products') {
            tempCart = response.value['data'][i]['data'];
          }
        }
        loading = false;
        setState(() {
          cart = tempCart;
        });
      } else {
        loading = false;
      }
    } else {
      loading = false;
      showDialog(
          context: context,
          builder: (context) {
            return AlertDialog(
              title: Center(
                  child: Text('Server error please try after some time!!!')),
              actions: <Widget>[
                Center(
                  child: InkWell(
                    onTap: () {
                      Navigator.pop(context);
                    },
                    child: Container(
                        decoration: BoxDecoration(
                            color: AppColors.primaryColor,
                            borderRadius: BorderRadius.all(
                              Radius.circular(20.0),
                            )),
                        margin:
                            EdgeInsets.symmetric(horizontal: 0, vertical: 20),
                        child: Padding(
                          padding: EdgeInsets.only(
                              left: 40, right: 40, top: 10, bottom: 10),
                          child: Text('Ok',
                              style: TextStyle(
                                  fontWeight: FontWeight.w400,
                                  fontSize: AppStyles.SMALL_TEXTSIZE,
                                  color: Colors.white),
                              textAlign: TextAlign.center),
                        )),
                  ),
                ),
              ],
            );
          });
    }
  }`

      ListView.builder(
                  key: PageStorageKey(_globalCounter),
                  physics: NeverScrollableScrollPhysics(),
                  scrollDirection: Axis.vertical,
                  shrinkWrap: true,
                  itemCount: products.length,
                  itemBuilder: (context, i) {
                    if (products.length > 0 &&
                        i == products.length - 1 &&
                        page < total_pages) {
                      print('index equal to length');
                      loading = true;
                      return _buildProgressIndicator();
                    } else {
                      return GestureDetector(
                          onTap: () {
                            Navigator.of(context).push(
                              MaterialPageRoute(
                                builder: (context) => ProductDetail(
                                    id: products[i]['id'].toString()),
                              ),
                            );
                          },
                          child: Container(
                              decoration: BoxDecoration(
                                border: Border.all(
                                    color: Colors.grey[100], width: 1),
                                borderRadius: BorderRadius.all(
                                  Radius.circular(10.0),
                                ),
                              ),
                              child: Padding(
                                  padding: EdgeInsets.only(
                                      top: 25,
                                      bottom: 10,
                                      left: 0,
                                      right: 0),
                                  child: Row(
                                    children: [
                                      Expanded(
                                          child: Container(
                                              child:
                                              // Image.network(
                                              //     products[i]['image'] !=
                                              //             null
                                              //         ? products[i]
                                              //             ['image']
                                              //         : '')
                                              CachedNetworkImage(
                                                imageUrl: products[i]['image'],
                                                placeholder: (context, url) => Align(
                                                  alignment: Alignment.center,
                                                  child: Loader(),
                                                ),

                                                errorWidget: (context, url, error) => Icon(Icons.error),
                                              ),
                                          )),
                                      Expanded(
                                          flex: 2,
                                          child: Column(
                                            children: [
                                              Padding(
                                                  padding:
                                                      EdgeInsets.only(
                                                          top: 5,
                                                          bottom: 5,
                                                          left: 10,
                                                          right: 5),
                                                  child: Text(
                                                      products[i][
                                                          'generic_name'],
                                                      style: TextStyle(
                                                          fontWeight:
                                                              FontWeight
                                                                  .w500,
                                                          fontSize:
                                                              AppStyles
                                                                  .SMALL_TEXTSIZE))),
                                              Padding(
                                                  padding:
                                                      EdgeInsets.only(
                                                          top: 2,
                                                          bottom: 5,
                                                          left: 10,
                                                          right: 5),
                                                  child: Container(
                                                      width: double
                                                          .infinity,
                                                      child: Wrap(
                                                        children: [
                                                          Text('MRP ',
                                                              style: TextStyle(
                                                                  fontWeight: FontWeight
                                                                      .w500,
                                                                  fontSize: AppStyles
                                                                      .SMALL_TEXTSIZE,
                                                                  color: Colors
                                                                      .deepOrangeAccent,
                                                                  decoration:
                                                                      TextDecoration.lineThrough)),
                                                          Text(
                                                              'Rs. ${products[i]['mrp_amount']} ',
                                                              style: TextStyle(
                                                                  fontWeight: FontWeight
                                                                      .w500,
                                                                  fontSize: AppStyles
                                                                      .SMALL_TEXTSIZE,
                                                                  color: Colors
                                                                      .deepOrangeAccent,
                                                                  decoration:
                                                                      TextDecoration.lineThrough)),
                                                          Text(
                                                              ' Rs. ${products[i]['chemist_amount']}',
                                                              style: TextStyle(
                                                                  fontWeight: FontWeight
                                                                      .w500,
                                                                  fontSize: AppStyles
                                                                      .SMALL_TEXTSIZE,
                                                                  color:
                                                                      Colors.lightGreen))
                                                        ],
                                                      ))),
                                              Padding(
                                                  padding:
                                                      EdgeInsets.only(
                                                          top: 2,
                                                          bottom: 5,
                                                          left: 10,
                                                          right: 5),
                                                  child: Row(
                                                    children: [
                                                      Expanded(
                                                          child:
                                                              Container(
                                                        width: double
                                                            .infinity,
                                                        child: Text(
                                                            ('${products[i]['package']}' !=
                                                                    null)
                                                                ? '${products[i]['package']}'
                                                                : '',
                                                            style: TextStyle(
                                                                fontWeight:
                                                                    FontWeight
                                                                        .w500,
                                                                fontSize:
                                                                    AppStyles
                                                                        .SMALL_TEXTSIZE,
                                                                color: Colors
                                                                    .grey)),
                                                      )),
                                                    ],
                                                  )),
                                              if (products[i] != null &&
                                                  isProductExistInCart(
                                                          products[i]
                                                              ['id']) !=
                                                      null)
                                                Row(
                                                  children: [
                                                    Expanded(
                                                        child: Row(
                                                      children: [
                                                        Expanded(
                                                            flex: 1,
                                                            child: Container(
                                                                width: double.infinity,
                                                                child: RawMaterialButton(
                                                                  onPressed:
                                                                      () {
                                                                    addItemToCart(products[i]['id'],
                                                                        'remove');
                                                                  },
                                                                  elevation:
                                                                      2.0,
                                                                  fillColor:
                                                                      Colors.white,
                                                                  child: Text(
                                                                      '-',
                                                                      style: TextStyle(fontSize: AppStyles.SMALL_TEXTSIZE, fontWeight: FontWeight.bold)),
                                                                  padding:
                                                                      EdgeInsets.all(1.0),
                                                                  shape:
                                                                      CircleBorder(),
                                                                ))),
                                                        Expanded(
                                                            flex: 1,
                                                            child: Container(
                                                                width: double
                                                                    .infinity,
                                                                child: Text(
                                                                    getCartCount(products[i][
                                                                        'id']),
                                                                    textAlign:
                                                                        TextAlign.center,
                                                                    style: TextStyle(fontSize: AppStyles.SMALL_TEXTSIZE, fontWeight: FontWeight.bold)))),
                                                        Expanded(
                                                          flex: 1,
                                                          child:
                                                              RawMaterialButton(
                                                            onPressed:
                                                                () {
                                                              //check Stock qty
                                                              if (isAvailableInStock(
                                                                  products[
                                                                      i])) {
                                                                addItemToCart(
                                                                    products[i]['id'],
                                                                    'add');
                                                                _globalCounter=i;
                                                              } else {
                                                                final snackBar =
                                                                    SnackBar(
                                                                  content: Text("This product is limited with" +
                                                                      products[i]['stock_in'] +
                                                                      " items"),
                                                                  duration:
                                                                      Duration(seconds: 2),
                                                                );
                                                                _scaffoldKey
                                                                    .currentState
                                                                    .showSnackBar(snackBar);
                                                              }
                                                            },
                                                            elevation:
                                                                2.0,
                                                            fillColor:
                                                                Colors
                                                                    .white,
                                                            child: Text(
                                                                '+',
                                                                style: TextStyle(
                                                                    fontSize:
                                                                        AppStyles.SMALL_TEXTSIZE,
                                                                    fontWeight: FontWeight.bold)),
                                                            padding:
                                                                EdgeInsets.all(
                                                                    1.0),
                                                            shape:
                                                                CircleBorder(),
                                                          ),
                                                        ),
                                                        Expanded(
                                                            child:
                                                                Container())
                                                      ],
                                                    )),
                                                  ],
                                                ),
                                              getBuyNowButton(
                                                  products[i])
                                            ],
                                          ))
                                    ],
                                  ))));
                    }
                  },
                )
2 Answers

Can you show some code? it seems that maybe you're updating your whole screen, resseting the scroll widget and its value, maybe by creating your own ScrollController in an StatefulWidget you could solve the problem, but again, show some code first so people can understand better your problem....

UPDATE

It seems that you update the variable _globalCounter when adding an item to cart, and also you use this variable as a key. When the key is different the Widget itself is recreated as anew, losing all inner states (scrolling, etc.)

if (isAvailableInStock(products[i])) {
    addItemToCart(products[i]['id'], 'add');
    _globalCounter=i; ///
}

ListView.builder(key: PageStorageKey(_globalCounter), ...);

I would recommend giving an static key name and not to change it when modifying the list, or at least change ig when you are completely sure the ListView must create a different type of list

ListView.builder(key: PageStorageKey('const name here'), ...);

As a sidenote, you could try to separate the build method with StatelessWidgets so its easier to read and find bugs

you can use this library to go to a specific index at anytime

Related