J'ai un formulaire de connexion avec deux champs de texte 'Nom d'utilisateur', 'Mot de passe' & un bouton 'Connexion'. Sur le robinet du bouton de connexion, j'appelle une API. Je veux montrer une CircularProgressIndicator
lors de cet appel d'api. La boîte de dialogue de progression doit apparaître dans le centre et en haut du formulaire de connexion. J'ai essayé FutureBuilder
mais il masque le formulaire de connexion qui affiche CircularProgressIndicator
uniquement. Je veux que tout le contenu de l'écran soit affiché derrière la CircularProgressIndicator
.
Code complet:
import 'package:flutter/material.Dart';
import 'package:the_don_flutter/userModel.Dart';
import 'package:validate/validate.Dart';
import 'package:http/http.Dart' as http;
import 'Dart:async';
import 'Dart:convert';
import 'Dart:io';
import 'signup.Dart';
class Login extends StatefulWidget{
@override
State<Login> createState() {
// TODO: implement createState
return LoginFormState();
}
}
class LoginFormState extends State<Login>{
final GlobalKey<FormState> formKey = new GlobalKey<FormState>();
String _passwordValidation(String value){
if(value.isEmpty){
return "Field Can't be empty.";
}else if(value.length < 6)
return "Password must be of six characters long.";
return null;
}
String _checkValidEmail(String value){
try{
Validate.isEmail(value);
}catch(e){
return "Email is not valid.";
}
return null;
}
Future<User> _loginUser() async{
var response = await http.post("https://example/public/api/login", headers: {}, body: {'username':'[email protected]', 'password':'123456'})
.catchError((error) => print("Error $error"));
print("response of login ${response.body}");
return User.fromJson(json.decode(response.body));
}
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
body: Container(
padding: EdgeInsets.only(left: 20.0, top: 100.0, right: 20.0),
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/images/bg_green.jpg"),
fit: BoxFit.fill)),
child: Column(
children: <Widget>[
Form(
key: formKey,
child: Column(children: <Widget>[
Padding(padding: EdgeInsets.only(bottom: 20.0),
child: TextFormField(
validator: _checkValidEmail,
decoration: InputDecoration(
hintText: "[email protected]",
labelText: "User Name",
hintStyle: TextStyle(color: Colors.white)),
style: TextStyle(color: Colors.white),
autofocus: true,),),
TextFormField(
obscureText: true,
validator: _passwordValidation,
decoration: InputDecoration(
hintText: "password",
labelText: "Password",
hintStyle: TextStyle(color: Colors.white)),
style: TextStyle(color: Colors.white),
autofocus: true,)
],),),
Padding(padding: EdgeInsets.only(top: 20.0),
child: Row(mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Text("Forgot Password?", textAlign: TextAlign.start, style: TextStyle(color: Colors.white,),),
],),),
Padding(padding: EdgeInsets.only(top: 20.0),
child: GestureDetector(
onTap: _submitForm,
child: Row(mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Text("LOGIN", textAlign: TextAlign.start, style: TextStyle(color: Colors.white, fontSize: 40.0),),
Icon(Icons.chevron_right, size: 40.0, color: Colors.white,),
],),), ),
Expanded(
child: Padding(padding: EdgeInsets.only(bottom: 20.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
Text("Don't have an account?", textAlign: TextAlign.start, style: TextStyle(color: Colors.white,),),
Container(
margin: EdgeInsets.only(left: 8.0),
child: GestureDetector(
onTap: (){Navigator.Push(context, MaterialPageRoute(builder: (context) => Signup()));},
child: Text("REGISTER NOW!", textAlign: TextAlign.start, style: TextStyle(color: Colors.black,),),
)),
],
),))
],
),
),
);
}
_submitForm() {
if(formKey.currentState.validate()){
print("Go to Home page");
_loginUser();
}
}
}
Cette démo (avec le code source) devrait être très proche de ce que vous essayez de faire.
Cela inclut le déclenchement des validateurs de formulaire avant et après l'appel asynchrone.
Vous pouvez essayer l'extrait de code ci-dessous pour cela
class ProgressHUD extends StatelessWidget {
final Widget child;
final bool inAsyncCall;
final double opacity;
final Color color;
final Animation<Color> valueColor;
ProgressHUD({
Key key,
@required this.child,
@required this.inAsyncCall,
this.opacity = 0.3,
this.color = Colors.grey,
this.valueColor,
}) : super(key: key);
@override
Widget build(BuildContext context) {
List<Widget> widgetList = new List<Widget>();
widgetList.add(child);
if (inAsyncCall) {
final modal = new Stack(
children: [
new Opacity(
opacity: opacity,
child: ModalBarrier(dismissible: false, color: color),
),
new Center(
child: new CircularProgressIndicator(
valueColor: valueColor,
),
),
],
);
widgetList.add(modal);
}
return Stack(
children: widgetList,
);
}
}
Utilise le
body: ProgressHUD(
child: screen,
inAsyncCall: _isLoading,
opacity: 0.0,
),
changez simplement l’état de _isloading true si vous souhaitez afficher la progression.