在 Flutter 的登录屏幕中显示循环进度对话框,如何在 Flutter 中实现进度对话框?
Posted
技术标签:
【中文标题】在 Flutter 的登录屏幕中显示循环进度对话框,如何在 Flutter 中实现进度对话框?【英文标题】:Show Circular Progress Dialog in Login Screen in Flutter, how to implement progress dialog in flutter? 【发布时间】:2018-12-27 03:41:51 【问题描述】:我有一个登录表单,其中包含两个文本字段“用户名”、“密码”和一个“登录”按钮。点击登录按钮,我正在调用 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();
【问题讨论】:
你看过***.com/questions/47065098/…吗? 像this 这样的事情怎么样?而不是颤动的图像,你可以有循环进度指示 【参考方案1】:在api
在登录屏幕上获取数据时,在按钮单击时显示progressdialog
。
试试这个
声明此方法以显示进度对话框
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);
【讨论】:
不错的简单例子! 很好的例子,如果我们需要让这个 showDialogBox 免受用户返回按钮的影响,那么如果用户按下返回按钮,它不会在 showDialogBox 完成之前删除它? @MadhavMishra barrierDismissible: true 请使用这个并检查。谢谢【参考方案2】:这个演示(带有源代码)应该非常接近你想要做的事情
它包括在异步调用之前和之后触发表单验证器。
https://pub.dartlang.org/packages/modal_progress_hud
【讨论】:
【参考方案3】:你可以试试下面的sn-p代码
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。
【讨论】:
在 ios 设备进度视图中显示与 android 相同。如何使其特定于平台?【参考方案4】:你想在哪里调用这个函数
progressDialogue(BuildContext context)
//set up the AlertDialog
AlertDialog alert=AlertDialog(
backgroundColor: Colors.transparent,
elevation: 0,
content: Container(
child: Center(
child: CircularProgressIndicator(),
),
),
);
showDialog(
//prevent outside touch
barrierDismissible: false,
context:context,
builder: (BuildContext context)
//prevent Back button press
return WillPopScope(
onWillPop: (),
child: alert);
,
);
**对于解雇调用这个**
Navigator.pop(context);
【讨论】:
【参考方案5】:创建类似bool _isLoading = false;
的东西
当按下登录按钮时
onPressed: ()
setState(()
_isLoading = true;
);
同时,使用 Stack 插入 CircularProgressIndicator
Stack(children: <Widget>[
_isLoading ? CircularProgressIndicator() : Container(), //only show CircularProgressIndicator when loading
//your login body here
【讨论】:
【参考方案6】:在 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);
);
【讨论】:
以上是关于在 Flutter 的登录屏幕中显示循环进度对话框,如何在 Flutter 中实现进度对话框?的主要内容,如果未能解决你的问题,请参考以下文章