Roxx
Roxx

Reputation: 3996

Show CircularProgressIndicator in front in Flutter

I want to display a circular bar like loading in front of other widgets. Below is the code which i am currently using. It shows the Circular loading but its between other widget.

It should be on top. Based on the suggestion I tried using Stack but it is still showing in between the widget. What am I doing wrong here?

class LoginPage extends StatefulWidget {
  @override
  _LoginPageState createState() => _LoginPageState();

}

class _LoginPageState extends State<LoginPage> {

 bool visible = true ; //Testing purpose it is true. Actually it is false.    
@override

Widget build(BuildContext context) {

return Scaffold(
  key: _scaffoldKey,
  body: Stack(
        children: <Widget>[
          new Container(
            decoration: BoxDecoration(
          gradient: LinearGradient(
              begin: Alignment.topRight,
              end: FractionalOffset.bottomCenter,//Alignment.bottomLeft,

              colors: [Colors.green[900], Colors.lightBlueAccent]),
        ),

          ),SingleChildScrollView(
            child: new Form(
              key: _formKey,
              autovalidate: _autoValidate,
    child: Center(
    child: Column(
      children: <Widget>[
        Row(
                  children: <Widget>[
                    VerticalText(),
                    TextLogin(),                    
                  ],
                ),


        Divider(),          

        Container(
        width: 280,

        ),
        Container(
        width: 280,
        child: TextFormField(
          style: TextStyle(
            color: Colors.white,
          ),
            decoration: InputDecoration(
            border: InputBorder.none,
            hintText: 'Enter Email',
            fillColor: Colors.lightBlueAccent,
            labelText: 'Email',
            labelStyle: TextStyle(
              color: Colors.white70,
              fontSize: 20,
            ),
            ),
            controller: emailController,
            autocorrect: true,
            validator: validateEmail,
            onSaved: (String val) {
              _email = val;
          },
          )
        ),

        Container(
        width: 280,
        child: TextFormField(
             style: TextStyle(
            color: Colors.white,
          ),
            decoration: InputDecoration(
            border: InputBorder.none,
            hintText: 'Enter Password',
            fillColor: Colors.lightBlueAccent,
            labelText: 'Password',
            labelStyle: TextStyle(
              color: Colors.white70,
              fontSize: 20,
            ),
            ),
            controller: passwordController,
            autocorrect: true,
            obscureText: true,
            validator: validatePassword,
              onSaved: (String val) {
                _password = val;
          },
          )
        ),

        RaisedButton(
          onPressed: _validateInputs,
          color: Colors.green,
          textColor: Colors.white,
          padding: EdgeInsets.fromLTRB(10, 10, 10, 10),
          child: Text('Login'),
        ),


        Visibility(
          child: Center(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.center,
            children: <Widget>[
              SizedBox(
                child: CircularProgressIndicator(
                  strokeWidth: 4.0,
                  valueColor : AlwaysStoppedAnimation(Colors.white),
                ),
                height: 200.0,
                width: 200.0,
              ),

            ],
          ),
        ),
          visible: visible, 
      ),
      ],
    ),
  )
            )
  )
        ],
),
);
}

I have seen similar questions in SO but still getting hard time to resolve it.

How to work with progress indicator in flutter?

flutter how to get a circular progress indicator working

Flutter : create an overlay progress bar

How to display CircularProgressIndicator on top of all widget in a centre of the screen

Upvotes: 8

Views: 19137

Answers (5)

Daniyal Dolare
Daniyal Dolare

Reputation: 441

As above most of them gave answer to make separate reusable function. So here is mine if you want to fetch some data and display circular progress indicator while data is being fetched.

///Function to get data from a future and display a dialog with circlular progress indicator while data is fetched.
getFutureData(BuildContext context, var future) async {
  var data;
  await showDialog(
    context: context,
    barrierDismissible: false,
    builder: (context) => Center(
      child: FutureBuilder(
        future: future,
        builder: (context, snapshot) {
          if (snapshot.hasData) {
            data = snapshot.data;
            Navigator.pop(context);
          }
          return CircularProgressIndicator();
        },
      ),
    ),
  );
  return data;
}

Upvotes: 1

Nuqo
Nuqo

Reputation: 4091

Like said, the real meaning of CircularProgressIndicator is to be run while loading a process without letting user interrupt. Create this loading indicator as a reusable .dart file. With this you can use the LoadingIndicator flexible everywhere and overlay the current screen.

You just have to make a .dart file containing:

import 'package:flutter/material.dart';

buildLoading(BuildContext context) {
  return showDialog(
      context: context,
      barrierDismissible: false,
      builder: (BuildContext context) {
        return Center(
          child: CircularProgressIndicator(
            valueColor: AlwaysStoppedAnimation<Color>(Colors.blue),
          ),
        );
      });
}

Then you can use it anywhere using

buildLoading(context);

and dismiss it when loading is done using

Navigator.of(context).pop();

Upvotes: 11

Sanket Vekariya
Sanket Vekariya

Reputation: 2956

The real meaning of circularProgressIndicator is to be run while loading process without letting user interrupt.
To remove interruption by user in between, one should put circularProgressIndicator in a dialog with property barrierDismissible: false.
One should create this loading indicator as reusable widget.
You can craete a method like below and can use it anywhere over the screen without defining in screen. (this does not require stack also.). Dialog will appear on the center of the screen.

buildShowDialog(BuildContext context) {
    return showDialog(
              context: context,
              barrierDismissible: false,
              builder: (BuildContext context) {
                return Center(
                  child: CircularProgressIndicator(),
                );
              });
  }

For Reference: Checkout code below:

void main() => runApp(App());

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Demo(),
    );
  }
}

class Demo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Circle Progress Indicator Demo"),
      ),
      body: Center(
        child: MaterialButton(
          child: Text("Press Me!"),
          onPressed: () => buildShowDialog(context),
        ),
      ),
    );
  }

  buildShowDialog(BuildContext context) {
    return showDialog(
        context: context,
        barrierDismissible: false,
        builder: (BuildContext context) {
          return Center(
            child: CircularProgressIndicator(),
          );
        });
  }
}

Output:
enter image description here

Upvotes: 22

Roxx
Roxx

Reputation: 3996

I removed Visiblity code with this one. Old Code

 Visibility(

          child: Center(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.center,
            children: <Widget>[
              SizedBox(
                child: CircularProgressIndicator(
                  strokeWidth: 4.0,
                  valueColor : AlwaysStoppedAnimation(Colors.white),
                ),
                height: 200.0,
                width: 200.0,
              ),


            ],
          ),
        ),
          visible: visible, 
      ), 

New Code

 visible ? Container(
                        color: Colors.black.withOpacity(0.5),
                        child:  Center(
                        child:SizedBox(// Center(

                          child: CircularProgressIndicator(
                            strokeWidth: 4.0,
                      valueColor : AlwaysStoppedAnimation(Colors.white),
                          ),
                          height: 200.0,
                          width: 200.0,
                        ),
                       ), 
    )
                      : Container()

And most importantly it needs to call in the first Widget.

    return Scaffold(
      key: _scaffoldKey,
      body: Stack(
            children: <Widget>[
/////Some containers,child Widget etc/////////
     visible ? Container(
                            color: Colors.black.withOpacity(0.5),
                            child:  Center(
                            child:SizedBox(// Center(

                              child: CircularProgressIndicator(
                                strokeWidth: 4.0,
                          valueColor : AlwaysStoppedAnimation(Colors.white),
                              ),
                              height: 200.0,
                              width: 200.0,
                            ),
                           ), 
        )
                          : Container()

] //Widget
  ), //Stack
); //Scaffold

I am not sure i explained it properly or not. But Bottom line is it shouldn't be inside the other child widget. It should be placed inside first children: <Widget>[ not inside the nested.

Upvotes: 1

Jaimil Patel
Jaimil Patel

Reputation: 1347

You can use Positioned Widget in Stack Widget for Showing CircularProgressIndicator in front of all widgets like below..
Please put values according to your convenience in all four values bottom,left,right,top...

         Positioned(
                bottom: ,
                left: ,
                right: , 
                top : ,
                child: Container(
                        child : CircularProgressIndicator()
                      )
                    ...
                   )

Upvotes: 3

Related Questions