我有一个带有两个文本字段“ UserName”,“ Password”和一个“ Login”按钮的登录表单。点击登录按钮时,我正在调用API。我想在此api调用中显示一个CircularProgressIndicator
。进度对话框应显示在登录表单的中央和顶部。
我已经尝试过FutureBuilder
,但是它隐藏了仅显示CircularProgressIndicator
的登录表单。我希望屏幕的所有内容都显示在CircularProgressIndicator
的后面。
完整代码:
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':'poras@techaheadcorp.com', '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: "abc@example.com",
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();
}
}
}
答案 0 :(得分:4)
答案 1 :(得分:4)
要在progressdialog
正在登录屏幕上获取数据时单击按钮上显示api
。
尝试
声明此方法以显示进度对话框
showLoaderDialog(BuildContext context){
AlertDialog alert=AlertDialog(
content: new Row(
children: [
CircularProgressIndicator(),
Container(margin: EdgeInsets.only(left: 7),child:Text("Loading..." )),
],),
);
showDialog(barrierDismissible: false,
context:context,
builder:(BuildContext context){
return alert;
},
);
}
用法
调用api时,在按钮上单击,像这样调用此方法
onPressed: () {
showLoaderDialog(context);
//api here },
并且在获取响应时,将像这样的对话框关闭
Navigator.pop(context);
答案 2 :(得分:0)
您可以尝试下面的代码段
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,
);
}
}
使用
body: ProgressHUD(
child: screen,
inAsyncCall: _isLoading,
opacity: 0.0,
),
如果要显示进度,只需将 _isloading 的状态更改为true。
答案 3 :(得分:0)
在 Flutter 中,使用 ProgressIndicator
小部件。通过控制何时通过布尔标志呈现进度,以编程方式显示进度。告诉 Flutter 在你的长时间运行的任务开始前更新它的状态,并在它结束后隐藏它。
在下面的示例中,构建函数被分成三个不同的函数。如果 showLoadingDialog()
为 true
(当 widgets.length == 0
时),则渲染 ProgressIndicator
。否则,使用从网络调用返回的数据呈现 ListView
。
完整示例
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
void main() {
runApp(SampleApp());
}
class SampleApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Sample App',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: SampleAppPage(),
);
}
}
class SampleAppPage extends StatefulWidget {
SampleAppPage({Key key}) : super(key: key);
@override
_SampleAppPageState createState() => _SampleAppPageState();
}
class _SampleAppPageState extends State<SampleAppPage> {
List widgets = [];
@override
void initState() {
super.initState();
loadData();
}
showLoadingDialog() {
return widgets.length == 0;
}
getBody() {
if (showLoadingDialog()) {
return getProgressDialog();
} else {
return getListView();
}
}
getProgressDialog() {
return Center(child: CircularProgressIndicator());
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Sample App"),
),
body: getBody());
}
ListView getListView() => ListView.builder(
itemCount: widgets.length,
itemBuilder: (BuildContext context, int position) {
return getRow(position);
});
Widget getRow(int i) {
return Padding(
padding: EdgeInsets.all(10.0),
child: Text("Row ${widgets[i]["title"]}"),
);
}
loadData() async {
String dataURL = "https://jsonplaceholder.typicode.com/posts";
http.Response response = await http.get(dataURL);
setState(() {
widgets = jsonDecode(response.body);
});
}
}