在Flutter中显示循环进度对话框

时间:2018-07-19 05:51:35

标签: dart flutter flutter-layout

我有一个带有两个文本字段“ 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();
    }
  }

}

4 个答案:

答案 0 :(得分:4)

此演示(带有源代码)应该非常接近您的尝试

enter image description here

它包括在异步调用之前和之后触发表单验证器。

https://pub.dartlang.org/packages/modal_progress_hud

答案 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);
    });
  }
}