Search code examples
flutterdartprogress-barflutter-alertdialog

How to implement progressindicator within a alertdialog in flutter?


I am new to flutter and I am trying to learn the platform. So, here I am trying to display information from jsonplaceholder onto a alertdialog while is activated when a button is pressed in main.dart(I haven't included the code here). While the data loads I want to the alert dialog to appear and show a circularprogressindicator and after the data loads up the progress indicator is replaced by the 3 containers.

    import 'dart:math';
    import 'dart:convert';
    import 'package:flutter/material.dart';
    import 'package:http/http.dart' as http;
    showAlertDialog(BuildContext context)async
    {
      Map res=await fetchData();
      Color bc=(res["id"]%2==0)?(const Color.fromARGB(255, 44, 255, 2)):(const Color.fromARGB(255,255,0,    0));
     AlertDialog alert=AlertDialog
     (
       title: const Text("TextFromNet"),
       content:Column
       (
         crossAxisAlignment: CrossAxisAlignment.start,
         mainAxisSize: MainAxisSize.min,
         children:
         [
         Container
         (
          //text from res and color bc
        ),
        const SizedBox(height:15),
        Container
        (
          //text from res and color bc
        ),
        const SizedBox(height:15),
        Container
        (
          //text from res and color bc
        ),
       ]
      )
     );
    showDialog
    (
      context:context,
      builder:(BuildContext context){return alert;},
     );

    return const CircularProgressIndicator();
     }
    fetchData()async
    {
      final response=await http.get(Uri.parse('https://jsonplaceholder.typicode.com/albums/${Random().nextInt(100)}'));
     if(response.statusCode==200) {return json.decode(response.body);}
     else {throw Exception('Failed to Fetch');}
    }

Currently the alertdialog appears after about 1seconds of pressing the button, I want a circularprogressindicator to be shown in this time inside the alertdialog with th title of "TextFromInternet". I tried searching for some way but i couldn't figure out a clear path. I am guessing I have to do something realted to the state of the alertdialog but I am not sure. Please help. I have removed code from the containers to make the code shorter.


Solution

  • Since you're new to Flutter, i tried to make it simplest as possible, you just have to adapt it to your situation.

    If we're awaiting for some value to load our screen, it's clever to use the FutureBuilder, since it's made for it:

    The showDialog method:

    Future<void> showCustomDialog() async {
      return await showDialog(
        context: context,
        barrierDismissible: false,
        // barrierDismissible: true or false, if you want to your dialog be closed in case your user clicks outside of it.
        builder: (context) {
          return AlertDialog(
            shape:
                RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
            backgroundColor: const Color.fromRGBO(0, 0, 0, 1), //Your Theme.
            title: const Text(
              'Your title',
              style: TextStyle(color: Colors.white),
            ),
            content: SizedBox(
              //It's not a bad idea to set your Dialog to a fixed sized.
              height: 250,
              width: 250,
              child: FutureBuilder(
                builder: (context, snapshot) {
                  if (snapshot.hasData) {
                    return Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        mainAxisSize: MainAxisSize.min,
                        children: [
                          //Here you put your final widgets
                          Text(
                            snapshot.data!,
                            style: const TextStyle(color: Colors.white),
                          ),
                        ]);
                  } else {
                    return Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: const [
                        SizedBox(
                          //Here's the loading indicator
                          width: 55,
                          height: 55,
                          child: CircularProgressIndicator(
                            color: Colors.white,
                          ),
                        ),
                      ],
                    );
                  }
                },
                future: fetchData(),
              ),
            ),
            actions: [
              //Actions are optional, you can insert TextButtons like this
              TextButton(
                style: ButtonStyle(
                    overlayColor:
                      MaterialStateColor.resolveWith((states) => Colors.blue),
                    shape: MaterialStateProperty.all<RoundedRectangleBorder>(
                        RoundedRectangleBorder(
                          borderRadius: BorderRadius.circular(12.0),
                          side: const BorderSide(color: Colors.blue)))),
                onPressed: () => Navigator.of(context).pop(true),
                child: const Text(
                  'Close',
                  style: TextStyle(
                    color: Colors.white,
                  ),
                ),
              ),
            ],
          );
        },
      );
     }
    

    the fetchData method, which brings our data.

    Future<String> fetchData() async {
        String stringReturn = ''; // You can start your variables as null and then handle if no data is found.
      await Future.delayed(const Duration(milliseconds: 4000)).then((value) {
        stringReturn = 'String returned from future fetchData()';
      });
      return stringReturn;
    }
    

    now, just call it from a button, like this: (in my case, it's in a Scaffold:)

    floatingActionButton: FloatingActionButton(
        onPressed: showCustomDialog,
        tooltip: 'ShowDialog',
        child: const Icon(Icons.add),
      ), 
    

    If you need more assistance, check this: https://www.youtube.com/watch?v=zEdw_1B7JHY (FutureBuilder - Widget of the week)

    https://api.flutter.dev/flutter/widgets/FutureBuilder-class.html

    https://medium.flutterdevs.com/explore-futurebuilder-in-flutter-9744203b2b8c (Medium articles usually has good information too!)