How to Work With Progress Indicator In Flutter ?

· 8 min read
How to Work With Progress Indicator In Flutter
How to Work With Progress Indicator In Flutter

CircularProgressIndicator Widget is a widget that displays the progress in a circular shape. So in this article How to Work With Progress Indicator In Flutter?

How to Work With Progress Indicator In Flutter?

There are a few ways to deal with Asynchronous actions.

A simple way to do this is by using a modal that will block the user input, thus preventing any unwanted actions. Consider a method like below:

void _onLoading() {
  showDialog(
    context: context,
    barrierDismissible: false,
    builder: (BuildContext context) {
      return Dialog(
        child: new Row(
          mainAxisSize: MainAxisSize.min,
          children: [
            new CircularProgressIndicator(),
            new Text("Loading"),
          ],
        ),
      );
    },
  );
  new Future.delayed(new Duration(seconds: 3), () {
    Navigator.pop(context); //pop dialog
    _login();
  });
}

The most ideal way to do it is using FutureBuilder and a stateful widget. Which is what you started. The trick is that, instead of having a boolean loading = false in your state, you can directly use a Future<MyUser>, user

And then pass it as an argument to FutureBuilder, which will give you some info such as “hasData” or the instance of MyUser when completed.

Consider the below code snippet.

@immutable
class MyUser {
  final String name;

  MyUser(this.name);
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      home: new MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  Future<MyUser> user;

  void _logIn() {
    setState(() {
      user = new Future.delayed(const Duration(seconds: 3), () {
        return new MyUser("Toto");
      });
    });
  }

  Widget _buildForm(AsyncSnapshot<MyUser> snapshot) {
    var floatBtn = new RaisedButton(
      onPressed:
          snapshot.connectionState == ConnectionState.none ? _logIn : null,
      child: new Icon(Icons.save),
    );
    var action =
        snapshot.connectionState != ConnectionState.none && !snapshot.hasData
            ? new Stack(
                alignment: FractionalOffset.center,
                children: <Widget>[
                  floatBtn,
                  new CircularProgressIndicator(
                    backgroundColor: Colors.red,
                  ),
                ],
              )
            : floatBtn;

    return new ListView(
      padding: const EdgeInsets.all(15.0),
        children: <Widget>[
          new ListTile(
            title: new TextField(),
          ),
          new ListTile(
            title: new TextField(obscureText: true),
          ),
          new Center(child: action)
        ],
    );
  }

  @override
  Widget build(BuildContext context) {
    return new FutureBuilder(
      future: user,
      builder: (context, AsyncSnapshot<MyUser> snapshot) {
        if (snapshot.hasData) {
          return new Scaffold(
            appBar: new AppBar(
              title: new Text("Hello ${snapshot.data.name}"),
            ),
          );
        } else {
          return new Scaffold(
            appBar: new AppBar(
              title: new Text("Connection"),
            ),
            body: _buildForm(snapshot),
          );
        }
      },
    );
  }
}

Another way is to set CircularProgressIndicator in a SnackBar Widget.

Here is how to set up the SnackBar.

  • Define a global key for your Scaffold
    final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();

    Add it to your Scaffold key attribute

    return new Scaffold(
          key: _scaffoldKey,
    .......

    On a Button Press CallBack

    onPressed: () {
                      _scaffoldKey.currentState.showSnackBar(
                          new SnackBar(duration: new Duration(seconds: 4), content:
                          new Row(
                            children: <Widget>[
                              new CircularProgressIndicator(),
                              new Text("  Signing-In...")
                            ],
                          ),
                          ));
                      _handleSignIn()
                          .whenComplete(() =>
                          Navigator.of(context).pushNamed("/Home")
                      );
                    }
    CircularProgressIndicator
    CircularProgressIndicator

    Without Plugin

        class IndiSampleState extends State<ProgHudPage> {
      @override
      Widget build(BuildContext context) {
        return new Scaffold(
            appBar: new AppBar(
              title: new Text('Demo'),
            ),
            body: Center(
              child: RaisedButton(
                color: Colors.blueAccent,
                child: Text('Login'),
                onPressed: () async {
                  showDialog(
                      context: context,
                      builder: (BuildContext context) {
                        return Center(child: CircularProgressIndicator(),);
                      });
                  await loginAction();
                  Navigator.pop(context);
                },
              ),
            ));
      }
    
      Future<bool> loginAction() async {
        //replace the below line of code with your login request
        await new Future.delayed(const Duration(seconds: 2));
        return true;
      }
    }

    With Plugin

  • Check this plugin progress_hud 
  • Add the dependency in the pubspec.yaml file
    dev_dependencies:
      progress_hud:

    Import the package

    import 'package:progress_hud/progress_hud.dart';

    Code Snippet will look like below:

    class ProgHudPage extends StatefulWidget {
      @override
      _ProgHudPageState createState() => _ProgHudPageState();
    }
    
    class _ProgHudPageState extends State<ProgHudPage> {
      ProgressHUD _progressHUD;
      @override
      void initState() {
        _progressHUD = new ProgressHUD(
          backgroundColor: Colors.black12,
          color: Colors.white,
          containerColor: Colors.blue,
          borderRadius: 5.0,
          loading: false,
          text: 'Loading...',
        );
        super.initState();
      }
    
      @override
      Widget build(BuildContext context) {
        return new Scaffold(
            appBar: new AppBar(
              title: new Text('ProgressHUD Demo'),
            ),
            body: new Stack(
              children: <Widget>[
                _progressHUD,
                new Positioned(
                    child: RaisedButton(
                      color: Colors.blueAccent,
                      child: Text('Login'),
                      onPressed: () async{
                        _progressHUD.state.show();
                        await loginAction();
                        _progressHUD.state.dismiss();
                      },
                    ),
                    bottom: 30.0,
                    right: 10.0)
              ],
            ));
      }
    
      Future<bool> loginAction()async{
        //replace the below line of code with your login request
        await new Future.delayed(const Duration(seconds: 2));
        return true;
      }
    }

    You can also try with the below methods.

  • Step 1: Create Dialog
    showAlertDialog(BuildContext context){
       AlertDialog alert=AlertDialog(
         content: new Row(
             children: [
                CircularProgressIndicator(),
                Container(margin: EdgeInsets.only(left: 5),child:Text("Loading" )),
             ],),
       );
       showDialog(barrierDismissible: false,
         context:context,
         builder:(BuildContext context){
           return alert;
         },
       );
     }
  • Step 2:Call it
    showAlertDialog(context);
    await firebaseAuth.signInWithEmailAndPassword(email: email, password: password);
    Navigator.pop(context);

    The example will look like below:

    import 'package:flutter/cupertino.dart';
    import 'package:flutter/material.dart';
    import 'package:firebase_auth/firebase_auth.dart';
    class DynamicLayout extends StatefulWidget{
      @override
      State<StatefulWidget> createState() {
        // TODO: implement createState
        return new MyWidget();
        }
      }
    showAlertDialog(BuildContext context){
      AlertDialog alert=AlertDialog(
        content: new Row(
            children: [
               CircularProgressIndicator(),
               Container(margin: EdgeInsets.only(left: 5),child:Text("Loading" )),
            ],),
      );
      showDialog(barrierDismissible: false,
        context:context,
        builder:(BuildContext context){
          return alert;
        },
      );
    }
    
      class MyWidget extends State<DynamicLayout>{
      Color color = Colors.indigoAccent;
      String title='app';
      GlobalKey<FormState> globalKey=GlobalKey<FormState>();
      String email,password;
      login() async{
       var currentState= globalKey.currentState;
       if(currentState.validate()){
            currentState.save();
            FirebaseAuth firebaseAuth=FirebaseAuth.instance;
            try {
              showAlertDialog(context);
              AuthResult authResult=await firebaseAuth.signInWithEmailAndPassword(
                  email: email, password: password);
              FirebaseUser user=authResult.user;
              Navigator.pop(context);
            }catch(e){
              print(e);
            }
       }else{
    
       }
      }
      @override
      Widget build(BuildContext context) {
        return new Scaffold(
            appBar:AppBar(
            title: Text("$title"),
            ) ,
              body: Container(child: Form(
                key: globalKey,
                child: Container(
                  padding: EdgeInsets.all(10),
                  child: Column(children: <Widget>[
                  TextFormField(decoration: InputDecoration(icon: Icon(Icons.email),labelText: 'Email'),
                  // ignore: missing_return
                  validator:(val){
                    if(val.isEmpty)
                      return 'Please Enter Your Email';
                  },
                  onSaved:(val){
                    email=val;
                  },
                  ),
                    TextFormField(decoration: InputDecoration(icon: Icon(Icons.lock),labelText: 'Password'),
                 obscureText: true,
                      // ignore: missing_return
                      validator:(val){
                        if(val.isEmpty)
                          return 'Please Enter Your Password';
                      },
                      onSaved:(val){
                        password=val;
                      },
                  ),
                    RaisedButton(color: Colors.lightBlue,textColor: Colors.white,child: Text('Login'),
                      onPressed:login),
                ],)
                  ,),)
             ),
        );
      }
    }
    

    We will get output like below:

    CircularProgressIndicator in a Modal
    CircularProgressIndicator in a Modal

Conclusion:

In this article, We have learned about How to Work With Progress Indicator In Flutter?

Thanks for being with us on a Flutter Journey.

Thanks for Reading!!!

Do let us know if you need any assistance with Flutter Development?

FlutterAgency.com is our portal Platform dedicated to Flutter Technology and Flutter Developers. The portal is full of cool resources from Flutter like Flutter Widget GuideFlutter ProjectsCode libs and etc.

FlutterAgency.com is one of the most popular online portal dedicated to Flutter Technology and daily thousands of unique visitors come to this portal to enhance their knowledge on Flutter.

Leave a Reply