Solución:
Ok, primero tienes que cambiar un poco tu código.
Cambiar de Stateless
para Stateful
para administrar el estado de su widget y poner una variable global llamada isLoading
. Puedes jugar con esa variable, establece isLoading
cierto cuando presiona el botón y isLoading
falso después de que se complete.
Agregue una validación dentro de su build
método para mostrar un progreso circular cuando isLoading
es verdadero, de lo contrario, muestre sus campos.
Muestra de código aquí:
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),
),
),
],
),
),
),
),
],
),
),
],
)));
}
}
Esta pregunta es un poco antigua, pero registraré una opción más aquí solo para referencias de futuros. Crearemos tres clases. Uno llamado ModalRoundedProgressBar que se encargará de mostrar y ocultar un CircularProgressBarIndicator, una clase ModalRoundedProgressBarState para crear el diseño del widget y al final una clase de control llamada ProgressBarHandler que nos permitirá mostrar y ocultar el ProgressBar circular cuando y donde queramos. El código tiene algunos comentarios.
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;
}
Ahora solo necesita implementar este widget en su widget de pantalla. Escribiré un ejemplo sencillo de implementación.
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();
}
Con este enfoque, tiene un componente reutilizable y no necesita volver a crear todo el diseño de la pantalla solo para mostrar u ocultar una barra de progreso redondeada.
Espero que esto pueda ayudar a alguien.