How to use CircularProgressIndicator in flutter
Ok, first you have to change your code a little.
Change from Stateless
to Stateful
to manage the state of your widget and put a global variable named isLoading
.
You can play with that variable, set isLoading
true when you press the button and isLoading
false after it complete.
Add a validation inside your build
method to display a circularprogresss when isLoading
is in true otherwise display your fields.
Code sample here:
class ForgotPasswordScreen extends StatefulWidget {
@override
ForgotPasswordScreenState createState() {
return new ForgotPasswordScreenState();
}
}
class ForgotPasswordScreenState extends State<ForgotPasswordScreen> {
final emailController = new TextEditingController();
final authHandler = new Auth();
bool isLoading = false;
@override
Widget build(BuildContext context) {
return new Scaffold(
body: Container(
height: MediaQuery.of(context).size.height,
decoration: BoxDecoration(
color: Colors.white,
),
child: isLoading
? Center(
child: CircularProgressIndicator(),
)
: new Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Row(
children: <Widget>[
new Expanded(
child: new Padding(
padding: const EdgeInsets.only(left: 40.0),
child: new Text(
"EMAIL",
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.redAccent,
fontSize: 15.0,
),
),
),
),
],
),
new Container(
width: MediaQuery.of(context).size.width,
margin: const EdgeInsets.only(
left: 40.0, right: 40.0, top: 10.0),
alignment: Alignment.center,
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
color: Colors.redAccent,
width: 0.5,
style: BorderStyle.solid),
),
),
padding: const EdgeInsets.only(left: 0.0, right: 10.0),
child: new Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
new Expanded(
child: TextField(
controller: emailController,
textAlign: TextAlign.left,
decoration: InputDecoration(
border: InputBorder.none,
hintText: 'PLEASE ENTER YOUR EMAIL',
hintStyle: TextStyle(color: Colors.grey),
),
),
),
],
),
),
Divider(
height: 24.0,
),
new Container(
width: MediaQuery.of(context).size.width,
margin: const EdgeInsets.only(
left: 30.0, right: 30.0, top: 20.0),
alignment: Alignment.center,
child: new Row(
children: <Widget>[
new Expanded(
child: new FlatButton(
shape: new RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(30.0),
),
color: Colors.redAccent,
onPressed: () {
setState(() {
isLoading = true;
});
authHandler
.sendPasswordResetEmail(
emailController.text)
.then((void nothing) {
print("done");
setState(() {
isLoading = false;
});
}).catchError((e) => print(e));
},
child: new Container(
padding: const EdgeInsets.symmetric(
vertical: 20.0,
horizontal: 20.0,
),
child: new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Expanded(
child: Text(
"FORGOT PASSWORD",
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold),
),
),
],
),
),
),
),
],
),
),
],
)));
}
}
This question is a little bit old but i will register one more option here just for futures references. We will create three classes. One called ModalRoundedProgressBar that will responsible for show and hide a CircularProgressBarIndicator, a ModalRoundedProgressBarState class to create widget layout and by the end a handle class called ProgressBarHandler that will allow us show and hide the circular ProgressBar when and where we desired. The code has some comments
class ModalRoundedProgressBar extends StatefulWidget {
final double _opacity;
final String _textMessage; // optional message to show
final Function _handlerCallback; // callback that will give a handler object to change widget state.
ModalRoundedProgressBar({
@required Function handleCallback(ProgressBarHandler handler),
String message = "", // some text to show if needed...
double opacity = 0.7, // opacity default value
}) : _textMessage = message,
_opacity = opacity,
_handlerCallback = handleCallback;
@override
State createState() => _ModalRoundedProgressBarState();
}
//StateClass ...
class _ModalRoundedProgressBarState extends State<ModalRoundedProgressBar> {
bool _isShowing = false; // member that control if a rounded progressBar will be showing or not
@override
void initState() {
super.initState();
/* Here we create a handle object that will be sent for a widget that creates a ModalRounded ProgressBar.*/
ProgressBarHandler handler = ProgressBarHandler();
handler.show = this.show; // handler show member holds a show() method
handler.dismiss = this.dismiss; // handler dismiss member holds a dismiss method
widget._handlerCallback(handler); //callback to send handler object
}
@override
Widget build(BuildContext context) {
//return a simple stack if we don't wanna show a roundedProgressBar...
if (!_isShowing) return Stack();
// here we return a layout structre that show a roundedProgressBar with a simple text message
return Material(
color: Colors.transparent,
child: Stack(
children: <Widget>[
Opacity(
opacity: widget._opacity,
//ModalBarried used to make a modal effect on screen
child: ModalBarrier(
dismissible: false,
color: Colors.black54,
),
),
Center(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
CircularProgressIndicator(),
Text(widget._textMessage),
],
),
),
],
),
);
}
// method do change state and show our CircularProgressBar
void show() {
setState(() => _isShowing = true);
}
// method to change state and hide our CIrcularProgressBar
void dismiss() {
setState(() => _isShowing = false);
}
}
// handler class
class ProgressBarHandler {
Function show; //show is the name of member..can be what you want...
Function dismiss;
}
Now you just need implement this widget in your Screen widget. I will write a simple example of implementation.
class YourScreen extends StatelessWidget{
//handler that we will use to show and hide widget
ProgressBarHandler _handler;
@override
Widget build(BuildContext context){
var scaffold = Scaffold(
appBar: AppBar(title: Text("Title"),),
body: _buildYourBodyLayout(),
);
var progressBar = ModalRoundedProgressBar(
//getting the handler
handleCallback: (handler) { _handler = handler;},
);
return Stack(
children: <Widget>[
scaffold,
progressBar,
],
);
}
// some code.... when you need to show a progress you will call: _handler.show();
//when you want hide the progress bar call: _handler.dismiss();
}
With this approach you have a reusable Component and you don't need recreate all screen layout just to show or hide a rounded progress bar.
I hope this can help somebody.