首页 > 解决方案 > 如何将 ModalProgressHUD 包含到另一个容器中?

问题描述

我正在使用https://pub.dev/packages/modal_progress_hud_nsn等待来自服务器的响应(它给了我们ModalProgressHUD)。一切都是正确的,当我单击按钮时,会显示进度指示器,我们无法单击屏幕上的任何内容,这样可以防止使用相同的数据单击相同的按钮。

在登录屏幕中,如果有人没有激活帐户,底部的新容器会显示新按钮,用于重新发送确认邮件。问题是,当我们单击此新按钮并重新发送时,会显示指示器,但在此新容器“下方”,因此我可以无休止地单击此按钮并发出新请求。你能告诉我如何防止它,这样这个指标才能正常工作吗?

代码(我删掉了一些不必要的代码):

import 'dart:convert';
import 'dart:io';

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:modal_progress_hud/modal_progress_hud.dart';
import 'package:renthings/constants/AppConstants.dart';
import 'package:renthings/constants/ErrorMessagesConstants.dart';

class LoginPage extends StatefulWidget {
  final String email;

  const LoginPage({Key? key, required this.email}) : super(key: key);

  @override
  _LoginPage createState() => _LoginPage();
}

class _LoginPage extends State<LoginPage> {
  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
  final emailController = TextEditingController();
  final passwordController = TextEditingController();
  bool _isInAsyncCall = false;
  var _passwordVisible = false;

  @override
  void dispose() {
    emailController.dispose();
    passwordController.dispose();
    super.dispose();
  }

  @override
  void initState() {
    super.initState();
    emailController.text = widget.email;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text("Zaloguj się"), centerTitle: true),
      body: ModalProgressHUD(
        progressIndicator: RefreshProgressIndicator(),
        inAsyncCall: _isInAsyncCall,
        child: SingleChildScrollView(
          child: Container(
            padding: EdgeInsets.all(20.0),
            width: MediaQuery.of(context).size.width,
            height: MediaQuery.of(context).size.height,
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.center,
              children: [
                FlutterLogo(size: 130),
                SizedBox(
                  height: 28.0,
                ),
                Text(
                  'Zaloguj się przy użyciu e-maila oraz hasła',
                  style: TextStyle(
                    fontSize: 23,
                  ),
                  textAlign: TextAlign.center,
                ),
                SizedBox(
                  height: 26.0,
                ),
                Form(
                  key: _formKey,
                  child: Column(
                    children: <Widget>[
                      TextFormField(
                        enabled: false,
                        controller: emailController,
                        decoration: InputDecoration(
                          border: OutlineInputBorder(),
                          hintText: 'Adres e-mail',
                          fillColor: Color(0xffffffff),
                          filled: true,
                          prefixIcon: Icon(Icons.mail),
                        ),
                      ),
                      SizedBox(
                        height: 10.0,
                      ),
                      TextFormField(
                        controller: passwordController,
                        obscureText: !_passwordVisible,
                        decoration: InputDecoration(
                          errorMaxLines: 2,
                          border: OutlineInputBorder(),
                          hintText: 'Hasło',
                          fillColor: Color(0xffffffff),
                          filled: true,
                          prefixIcon: Icon(Icons.password),
                          suffixIcon: IconButton(
                            icon: Icon(
                              _passwordVisible
                                  ? Icons.visibility
                                  : Icons.visibility_off,
                              color: Theme.of(context).primaryColorDark,
                            ),
                            onPressed: () {
                              setState(() {
                                _passwordVisible = !_passwordVisible;
                              });
                            },
                          ),
                        ),
                        validator: (value) {
                          if (value == null || value.isEmpty) {
                            return ErrorMessages.NO_PASSWORD_MESSAGE;
                          }
                        },
                      ),
                      SizedBox(
                        height: 25.0,
                      ),
                      ConstrainedBox(
                        constraints:
                            BoxConstraints.tightFor(width: 240, height: 60),
                        child: ElevatedButton(
                          onPressed: () {
                            if (_formKey.currentState!.validate()) {
                              _tryToLogin();
                            }
                          },
                          child: Text('Zaloguj się',
                              style: TextStyle(
                                fontSize: 30,
                                color: Color(0xffffffff),
                              ),
                              textAlign: TextAlign.center),
                          style: ButtonStyle(
                            backgroundColor: MaterialStateProperty.all<Color>(
                              Color(0xFF2F45C6),
                            ),
                            shape: MaterialStateProperty.all<
                                RoundedRectangleBorder>(
                              RoundedRectangleBorder(
                                borderRadius: BorderRadius.circular(25.0),
                              ),
                            ),
                          ),
                        ),
                      ),
                      SizedBox(
                        height: 25.0,
                      ),
                      TextButton(
                        style: TextButton.styleFrom(
                          textStyle: const TextStyle(fontSize: 23),
                        ),
                        onPressed: () {},
                        child: const Text('Zapomniałeś hasła?'),
                      ),
                    ],
                  ),
                )
              ],
            ),
          ),
        ),
      ),
      backgroundColor: const Color(0xFEF9F9FC),
    );
  }

  setLoading(bool state) => setState(() => _isInAsyncCall = state);

  Future<void> _tryToLogin() async {
    final body = {
      'email': emailController.text.trim(), //
      'password': passwordController.text, //
    };
    final jsonString = json.encode(body);
    final uri =
        Uri.http(AppConstants.BASE_URL, AppConstants.USER_ACTIVE_ENDPOINT);
    final headers = {HttpHeaders.contentTypeHeader: 'application/json'};
    setLoading(true);
    final response = await http.post(uri, headers: headers, body: jsonString);
    setLoading(false);
    showNotActivatedAccountErrorPopup(context);
  }

  void showNotActivatedAccountErrorPopup(BuildContext context) {
    showModalBottomSheet(
      backgroundColor: Colors.transparent,
      context: context,
      builder: (BuildContext bc) {
        return Container(
          decoration: BoxDecoration(
            borderRadius: BorderRadius.only(
              topRight: Radius.circular(40.0),
              topLeft: Radius.circular(40.0),
            ),
            color: const Color(0xFEF9F9FC),
            boxShadow: [
              BoxShadow(color: const Color(0xFF2F45C6), spreadRadius: 3),
            ],
          ),
          height: MediaQuery.of(context).size.height * .27,
          child: Padding(
            padding: const EdgeInsets.all(10.0),
            child: Column(
              children: <Widget>[
                Text(
                  "Błąd!",
                  style: TextStyle(
                    fontSize: 30,
                    color: Color(0xffff0000),
                  ),
                  textAlign: TextAlign.center,
                ),
                SizedBox(
                  height: 10.0,
                ),
                Text(
                  "Twój mail nie został jeszcze potwierdzony!",
                  style: TextStyle(
                    fontSize: 18,
                    color: Color(0xff000000),
                  ),
                  textAlign: TextAlign.center,
                ),
                SizedBox(
                  height: 15.0,
                ),
                ConstrainedBox(
                  constraints: BoxConstraints.tightFor(width: 160, height: 40),
                  child: ElevatedButton(
                    child: Text('Rozumiem!',
                        style: TextStyle(
                          fontSize: 16,
                          color: Color(0xffffffff),
                        ),
                        textAlign: TextAlign.center),
                    style: ButtonStyle(
                      backgroundColor: MaterialStateProperty.all<Color>(
                        Color(0xFF2F45C6),
                      ),
                      shape: MaterialStateProperty.all<RoundedRectangleBorder>(
                        RoundedRectangleBorder(
                          borderRadius: BorderRadius.circular(25.0),
                        ),
                      ),
                    ),
                    onPressed: () {
                      Navigator.of(context).pop();
                    },
                  ),
                ),
                SizedBox(height: 10),
                TextButton(
                  style: TextButton.styleFrom(
                    textStyle: const TextStyle(fontSize: 17),
                  ),
                  onPressed: () async {
                    http.Response response = await _resendConfirmationMail();
                    if (response.statusCode == 200) {
                      showDialog(
                          context: context,
                          builder: (context) {
                            Future.delayed(Duration(seconds: 3), () {
                              Navigator.of(context).pop(true);
                            });
                            return AlertDialog(
                              title: Text('Wysłano link potwierdzający!'),
                            );
                          });
                    }
                  },
                  child: const Text('Wyślij ponownie e-mail z potwierdzeniem'),
                ),
              ],
            ),
          ),
        );
      },
    );
  }

  Future<http.Response> _resendConfirmationMail() async {
    final queryParameters = {'mail': emailController.text};
    final uri = Uri.http(AppConstants.BASE_URL,
        AppConstants.RESEND_CONFIRMATION_ENDPOINT, queryParameters);
    final headers = {HttpHeaders.contentTypeHeader: 'application/json'};
    setLoading(true);
    final response = await http.get(uri, headers: headers);
    setLoading(false);
    return response;
  }
}

SetLoading 方法用于改变_isInAsyncCall指示是否需要进度指示器的状态。 是单击容器上的_resendConfirmationMailnew按钮后调用的方法。new感谢您的帮助。

标签: flutterdartprogress-bar

解决方案


推荐阅读