Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

flutter future builder get Widget by index

I have gridView.builder and have elevatedButton in my grid, when i press my button, button click event showing for all my grid tiles:

How can i show this loader effect only on the button that is pressed

enter image description here

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

 void _onSubmit() {
    if (Constants.USER_TOKEN != null && Constants.USER_TOKEN != '') {
      print('NO');
    } else {
      showDialog<void>(
        context: context,
        builder: (BuildContext dialogContext) {
          return SimpleDialog(
            shape: RoundedRectangleBorder(
                borderRadius: BorderRadius.circular(18.0)),
            title: Text(
              'Пройдите регистрацию, чтобы добавлять в корзину',
              textAlign: TextAlign.center,
            ),
            children: <Widget>[
              TextButton(
                child: Text('Пройти регистрацию'),
                onPressed: () {
                  Navigator.of(dialogContext).pop(); // Dismiss alert dialog
                  Navigator.of(context).pushAndRemoveUntil(
                      MaterialPageRoute(
                          builder: (context) => MainScreen(currentIndex: 3)),
                      (route) => false);
                },
                style: ButtonStyle(alignment: Alignment.center),
              ),
            ],
          );
        },
      );
    }
    setState(() => _isLoading = true);
    Future.delayed(
      const Duration(seconds: 2),
      () => setState(() => _isLoading = false),
    );
  }
ElevatedButton.icon(
                      icon: _isLoading
                          ? Container(
                              width: 24,
                              height: 24,
                              padding: const EdgeInsets.all(2.0),
                              child: const CircularProgressIndicator(
                                color: Colors.white,
                                strokeWidth: 3,
                              ),
                            )
                          : const Icon(Icons.shopping_basket),
                      onPressed: () => _onSubmit(),

>Solution :

You need to define new variable like this:

int selectedIndex = -1;

then pass the item index to your item and use it Like this:

ElevatedButton.icon(
          icon: _isLoading && selectedIndex == index //<-- add this
              ? Container(
                  width: 24,
                  height: 24,
                  padding: const EdgeInsets.all(2.0),
                  child: const CircularProgressIndicator(
                    color: Colors.white,
                    strokeWidth: 3,
                  ),
                )
              : const Icon(Icons.shopping_basket),
          onPressed: () {
              selectedIndex = index;//<-- add this
              _onSubmit();
          },
     )

also remember to reset the selectedIndex after loading finish:

selectedIndex = -1;

Thanks to @Ivo, if you want to have more than one loading at the same time you need this approach:

first define the list of bool like this:

List<bool> itemLoading = [];

when your items list get ready fill this list with default value like this:

itemLoading = List.generate(yourItemsList.length, (_) => false);

then you need update this list in your Item like this:

ElevatedButton.icon(
      icon: itemLoading[index] //<-- add this
          ? Container(
              width: 24,
              height: 24,
              padding: const EdgeInsets.all(2.0),
              child: const CircularProgressIndicator(
                color: Colors.white,
                strokeWidth: 3,
              ),
            )
          : const Icon(Icons.shopping_basket),
      onPressed: () {
          itemLoading[index] = true;//<-- add this
          _onSubmit(index);
      },
 )

then in your _onSubmit do this:

void _onSubmit(int index) {
    if (Constants.USER_TOKEN != null && Constants.USER_TOKEN != '') {
      print('NO');
    } else {
      showDialog<void>(
        context: context,
        builder: (BuildContext dialogContext) {
          return SimpleDialog(
            shape: RoundedRectangleBorder(
                borderRadius: BorderRadius.circular(18.0)),
            title: Text(
              'Пройдите регистрацию, чтобы добавлять в корзину',
              textAlign: TextAlign.center,
            ),
            children: <Widget>[
              TextButton(
                child: Text('Пройти регистрацию'),
                onPressed: () {
                  Navigator.of(dialogContext).pop(); // Dismiss alert dialog
                  Navigator.of(context).pushAndRemoveUntil(
                      MaterialPageRoute(
                          builder: (context) => MainScreen(currentIndex: 3)),
                      (route) => false);
                },
                style: ButtonStyle(alignment: Alignment.center),
              ),
            ],
          );
        },
      );
    }
    Future.delayed(
      const Duration(seconds: 2),
      () => setState(() => itemLoading[index] = false),
    );
  }
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading