【问题标题】:How to work with progress indicator in flutter?如何在颤振中使用进度指示器?
【发布时间】:2023-04-11 02:30:01
【问题描述】:

我是 Flutter 的新手,想知道在我的布局中添加 CircularProgressIndicator 的更好方法。例如,我的登录视图。这个视图有用户名、密码和登录按钮。我确实想创建一个覆盖布局(使用Opacity),在加载时显示进度指示器,就像我在 NativeScript 中使用的那样,但我对如何做以及如果它是更好的方法有点困惑。例如,在 NativeScript 上,我在主布局中添加了 IndicatorActivity 并将 busy 设置为 true 或 false,因此在加载时它会覆盖所有视图组件。

编辑:

我能够达到这个结果:

    void main() {
      runApp(new MyApp());
    }

    class MyApp extends StatelessWidget {
      // This widget is the root of your application.
      @override
      Widget build(BuildContext context) {
        return new MaterialApp(
          title: 'Flutter Demo',
          theme: new ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: new MyHomePage(title: 'Flutter Demo Home Page'),
        );
      }
    }

    class MyHomePage extends StatefulWidget {
      MyHomePage({Key key, this.title}) : super(key: key);

      final String title;

      @override
      _MyHomePageState createState() => new _MyHomePageState();
    }

    class _MyHomePageState extends State<MyHomePage> {
      bool _loading = false;

      void _onLoading() {
        setState(() {
          _loading = true;
          new Future.delayed(new Duration(seconds: 3), _login);
        });
      }


      Future _login() async{
        setState((){
          _loading = false;
        });
      }

      @override
      Widget build(BuildContext context) {


          var body = new Column(
              children: <Widget>[
                new Container(
                  height: 40.0,
                  padding: const EdgeInsets.all(10.0),
                  margin: const EdgeInsets.fromLTRB(15.0, 150.0, 15.0, 0.0),
                  decoration: new BoxDecoration(
                    color: Colors.white,
                  ),
                  child: new TextField(
                    decoration: new InputDecoration.collapsed(hintText: "username"),
                  ),
                ),
                new Container(
                  height: 40.0,
                  padding: const EdgeInsets.all(10.0),
                  margin: const EdgeInsets.all(15.0),
                  decoration: new BoxDecoration(
                    color: Colors.white,
                  ),
                  child: new TextField(
                    decoration: new InputDecoration.collapsed(hintText: "password"),
                  ),
                ),
              ],
            );


          var bodyProgress = new Container(
            child: new Stack(
              children: <Widget>[
                body,
                new Container(
                  alignment: AlignmentDirectional.center,
                  decoration: new BoxDecoration(
                    color: Colors.white70,
                  ),
                  child: new Container(
                    decoration: new BoxDecoration(
                      color: Colors.blue[200],
                      borderRadius: new BorderRadius.circular(10.0)
                    ),
                    width: 300.0,
                    height: 200.0,
                    alignment: AlignmentDirectional.center,
                    child: new Column(
                      crossAxisAlignment: CrossAxisAlignment.center,
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: <Widget>[
                        new Center(
                          child: new SizedBox(
                            height: 50.0,
                            width: 50.0,
                            child: new CircularProgressIndicator(
                              value: null,
                              strokeWidth: 7.0,
                            ),
                          ),
                        ),
                        new Container(
                          margin: const EdgeInsets.only(top: 25.0),
                          child: new Center(
                            child: new Text(
                              "loading.. wait...",
                              style: new TextStyle(
                                color: Colors.white
                              ),
                            ),
                          ),
                        ),
                      ],
                    ),
                  ),
                ),
              ],
            ),
          );

          return new Scaffold(
            appBar: new AppBar(
              title: new Text(widget.title),
            ),
            body: new Container(
              decoration: new BoxDecoration(
                color: Colors.blue[200]
              ),
              child: _loading ? bodyProgress : body
            ),
            floatingActionButton: new FloatingActionButton(
              onPressed: _onLoading,
              tooltip: 'Loading',
              child: new Icon(Icons.check),
            ),
          );
      }
    }

我还在适应状态的想法。使用颤振时,此代码在预期范围内吗?

谢谢!

【问题讨论】:

  • 如何在对话框显示时禁用背压?

标签: flutter dart progress-indicator


【解决方案1】:

在 Flutter 中,有几种处理异步动作的方法。

一种懒惰的方法是使用模式。这将阻止用户输入,从而防止任何不需要的操作。 这将需要对您的代码进行很少的更改。只需将您的 _onLoading 修改为以下内容:

void _onLoading() {
  showDialog(
    context: context,
    barrierDismissible: false,
    builder: (BuildContext context) {
      return Dialog(
        child: new Row(
          mainAxisSize: MainAxisSize.min,
          children: [
            new CircularProgressIndicator(),
            new Text("Loading"),
          ],
        ),
      );
    },
  );
  new Future.delayed(new Duration(seconds: 3), () {
    Navigator.pop(context); //pop dialog
    _login();
  });
}

最理想的方法是使用FutureBuilder 和一个有状态的小部件。这是你开始的。 诀窍是,您可以直接使用Future&lt;MyUser&gt; user,而不是在您的状态中使用boolean loading = false

然后将其作为参数传递给FutureBuilder,它会在完成时为您提供一些信息,例如“hasData”或MyUser 的实例。

这会导致这样的事情:

@immutable
class MyUser {
  final String name;

  MyUser(this.name);
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Flutter Demo',
      home: new MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  Future<MyUser> user;

  void _logIn() {
    setState(() {
      user = new Future.delayed(const Duration(seconds: 3), () {
        return new MyUser("Toto");
      });
    });
  }

  Widget _buildForm(AsyncSnapshot<MyUser> snapshot) {
    var floatBtn = new RaisedButton(
      onPressed:
          snapshot.connectionState == ConnectionState.none ? _logIn : null,
      child: new Icon(Icons.save),
    );
    var action =
        snapshot.connectionState != ConnectionState.none && !snapshot.hasData
            ? new Stack(
                alignment: FractionalOffset.center,
                children: <Widget>[
                  floatBtn,
                  new CircularProgressIndicator(
                    backgroundColor: Colors.red,
                  ),
                ],
              )
            : floatBtn;

    return new ListView(
      padding: const EdgeInsets.all(15.0),
        children: <Widget>[
          new ListTile(
            title: new TextField(),
          ),
          new ListTile(
            title: new TextField(obscureText: true),
          ),
          new Center(child: action)
        ],
    );
  }

  @override
  Widget build(BuildContext context) {
    return new FutureBuilder(
      future: user,
      builder: (context, AsyncSnapshot<MyUser> snapshot) {
        if (snapshot.hasData) {
          return new Scaffold(
            appBar: new AppBar(
              title: new Text("Hello ${snapshot.data.name}"),
            ),
          );
        } else {
          return new Scaffold(
            appBar: new AppBar(
              title: new Text("Connection"),
            ),
            body: _buildForm(snapshot),
          );
        }
      },
    );
  }
}

【讨论】:

  • 很酷,这两个示例在登录和其他情况下都很有用。带有对话框的处理程序进度看起来比我的版本更好,FutureBuilder 也比我的解决方案更优雅。感谢您的帮助!
  • 一个题外话.. 对于每个 TextField 我需要一个唯一的 TextEditingController?
  • @RicardoBocchi 是的
  • 我不认为对话框将与实际示例一起使用,在返回 _login() 后如何重定向用户令人困惑。你的第二个例子虽然看起来更方便。烤得很好。
  • 嗯,对话框是功能性的,只需要对他的原始代码进行很少的修改。例如,他可以使用Navigator.pushNamed("/home") 来关闭对话框。
【解决方案2】:

对我来说,一种巧妙的方法是在登录过程发生时在底部显示SnackBar,这是我的意思的一个例子:

这里是如何设置SnackBar

为你的Scaffold定义一个全局键

final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();

将其添加到您的 Scaffold key 属性中

return new Scaffold(
      key: _scaffoldKey,
.......

我的登录按钮onPressed回调:

onPressed: () {
                  _scaffoldKey.currentState.showSnackBar(
                      new SnackBar(duration: new Duration(seconds: 4), content:
                      new Row(
                        children: <Widget>[
                          new CircularProgressIndicator(),
                          new Text("  Signing-In...")
                        ],
                      ),
                      ));
                  _handleSignIn()
                      .whenComplete(() =>
                      Navigator.of(context).pushNamed("/Home")
                  );
                }

这真的取决于你想如何构建你的布局,我不确定你的想法。

编辑

你可能想要这样,我使用了一个堆栈来实现这个结果,只是根据onPressed显示或隐藏我的指标

class TestSignInView extends StatefulWidget {
  @override
  _TestSignInViewState createState() => new _TestSignInViewState();
}


class _TestSignInViewState extends State<TestSignInView> {
  bool _load = false;
  @override
  Widget build(BuildContext context) {
    Widget loadingIndicator =_load? new Container(
      color: Colors.grey[300],
      width: 70.0,
      height: 70.0,
      child: new Padding(padding: const EdgeInsets.all(5.0),child: new Center(child: new CircularProgressIndicator())),
    ):new Container();
    return new Scaffold(
      backgroundColor: Colors.white,
      body:  new Stack(children: <Widget>[new Padding(
        padding: const EdgeInsets.symmetric(vertical: 50.0, horizontal: 20.0),
        child: new ListView(

          children: <Widget>[
            new Column(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.center
              ,children: <Widget>[
            new TextField(),
            new TextField(),

            new FlatButton(color:Colors.blue,child: new Text('Sign In'),
                onPressed: () {
              setState((){
                _load=true;
              });

                  //Navigator.of(context).push(new MaterialPageRoute(builder: (_)=>new HomeTest()));
                }
            ),

            ],),],
        ),),
        new Align(child: loadingIndicator,alignment: FractionalOffset.center,),

      ],));
  }

}

【讨论】:

  • 嗨,这就是我想做的,但我没有得到我需要的布局。堆栈就是答案。关于StatefulWidget,进度状态改变时构建所有视图是否正确?
  • 嘿,我不明白你的问题?
  • 在我的代码中,当_loading 更改时,所有视图都将重建。是这样吗?
  • 使用模态可能更容易,同时也更直观。您可以在开始或请求时推送加载对话框,并在完成时弹出它。它还具有防止进一步用户输入的优点。
  • 好吧,让我烤点东西。
【解决方案3】:

创建一个布尔值isLoading 并将其设置为false。在三元运算符的帮助下,当用户单击登录按钮时,将isLoading 的状态设置为true。您将获得圆形加载指示器代替登录按钮

 isLoading ? new PrimaryButton(
                      key: new Key('login'),
                      text: 'Login',
                      height: 44.0,
                      onPressed: setState((){isLoading = true;}))
                  : Center(
                      child: CircularProgressIndicator(),
                    ),

您可以在单击登录之前查看屏幕截图

点击登录后

同时您可以运行登录过程和登录用户。如果用户凭据错误,那么您将再次将setStateisLoading 更改为false,这样加载指示器将变得不可见并且用户可以看到登录按钮。 顺便说一句,代码中使用的primaryButton是我的自定义按钮。您可以在button 中对OnPressed 执行相同操作。

【讨论】:

  • 这其实很聪明!无需处理双击等。谢谢。
  • 如何处理这种情况下的双击?
  • 我从来没有遇到过这种情况来处理双击,因为单击它会变为加载指示器。根据我对您评论的理解,我认为我们可以用手势检测器包装自定义按钮,然后您可以在那里双击。
  • 三元运算符在哪里使用?您的示例看起来很聪明,但不知道如何实现它。
  • 在您希望有(登录)按钮的构建方法中使用上述代码 sn-p。当用户单击该按钮时, bool(isLoading) 变为 true 并显示循环加载指示器而不是按钮。
【解决方案4】:

1.没有插件

    class IndiSampleState extends State<ProgHudPage> {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
        appBar: new AppBar(
          title: new Text('Demo'),
        ),
        body: Center(
          child: RaisedButton(
            color: Colors.blueAccent,
            child: Text('Login'),
            onPressed: () async {
              showDialog(
                  context: context,
                  builder: (BuildContext context) {
                    return Center(child: CircularProgressIndicator(),);
                  });
              await loginAction();
              Navigator.pop(context);
            },
          ),
        ));
  }

  Future<bool> loginAction() async {
    //replace the below line of code with your login request
    await new Future.delayed(const Duration(seconds: 2));
    return true;
  }
}

2。带插件

检查这个插件progress_hud

在 pubspec.yaml 文件中添加依赖

dev_dependencies:
  progress_hud: 

导入包

import 'package:progress_hud/progress_hud.dart';

下面给出了显示和隐藏指标的示例代码

class ProgHudPage extends StatefulWidget {
  @override
  _ProgHudPageState createState() => _ProgHudPageState();
}

class _ProgHudPageState extends State<ProgHudPage> {
  ProgressHUD _progressHUD;
  @override
  void initState() {
    _progressHUD = new ProgressHUD(
      backgroundColor: Colors.black12,
      color: Colors.white,
      containerColor: Colors.blue,
      borderRadius: 5.0,
      loading: false,
      text: 'Loading...',
    );
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
        appBar: new AppBar(
          title: new Text('ProgressHUD Demo'),
        ),
        body: new Stack(
          children: <Widget>[
            _progressHUD,
            new Positioned(
                child: RaisedButton(
                  color: Colors.blueAccent,
                  child: Text('Login'),
                  onPressed: () async{
                    _progressHUD.state.show();
                    await loginAction();
                    _progressHUD.state.dismiss();
                  },
                ),
                bottom: 30.0,
                right: 10.0)
          ],
        ));
  }

  Future<bool> loginAction()async{
    //replace the below line of code with your login request
    await new Future.delayed(const Duration(seconds: 2));
    return true;
  }
}

【讨论】:

  • 不要投反对票,有些人不想处理 UI 的细节,我就是其中之一,所以这个插件就派上用场了
  • api 中的进度条足够公平,添加依赖项会增加构建大小。已经颤振构建过度了。
  • 您真的应该将其添加为开发依赖项吗?
  • @MohammadMeshkani 使用 Navigator.pop(context);在导航到下一个屏幕之前
【解决方案5】:

第 1 步:创建对话框

   showAlertDialog(BuildContext context){
      AlertDialog alert=AlertDialog(
        content: new Row(
            children: [
               CircularProgressIndicator(),
               Container(margin: EdgeInsets.only(left: 5),child:Text("Loading" )),
            ],),
      );
      showDialog(barrierDismissible: false,
        context:context,
        builder:(BuildContext context){
          return alert;
        },
      );
    }

第 2 步:调用它

showAlertDialog(context);
await firebaseAuth.signInWithEmailAndPassword(email: email, password: password);
Navigator.pop(context);

对话框和登录表单示例

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
class DynamicLayout extends StatefulWidget{
  @override
  State<StatefulWidget> createState() {
    // TODO: implement createState
    return new MyWidget();
    }
  }
showAlertDialog(BuildContext context){
  AlertDialog alert=AlertDialog(
    content: new Row(
        children: [
           CircularProgressIndicator(),
           Container(margin: EdgeInsets.only(left: 5),child:Text("Loading" )),
        ],),
  );
  showDialog(barrierDismissible: false,
    context:context,
    builder:(BuildContext context){
      return alert;
    },
  );
}

  class MyWidget extends State<DynamicLayout>{
  Color color = Colors.indigoAccent;
  String title='app';
  GlobalKey<FormState> globalKey=GlobalKey<FormState>();
  String email,password;
  login() async{
   var currentState= globalKey.currentState;
   if(currentState.validate()){
        currentState.save();
        FirebaseAuth firebaseAuth=FirebaseAuth.instance;
        try {
          showAlertDialog(context);
          AuthResult authResult=await firebaseAuth.signInWithEmailAndPassword(
              email: email, password: password);
          FirebaseUser user=authResult.user;
          Navigator.pop(context);
        }catch(e){
          print(e);
        }
   }else{

   }
  }
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
        appBar:AppBar(
        title: Text("$title"),
        ) ,
          body: Container(child: Form(
            key: globalKey,
            child: Container(
              padding: EdgeInsets.all(10),
              child: Column(children: <Widget>[
              TextFormField(decoration: InputDecoration(icon: Icon(Icons.email),labelText: 'Email'),
              // ignore: missing_return
              validator:(val){
                if(val.isEmpty)
                  return 'Please Enter Your Email';
              },
              onSaved:(val){
                email=val;
              },
              ),
                TextFormField(decoration: InputDecoration(icon: Icon(Icons.lock),labelText: 'Password'),
             obscureText: true,
                  // ignore: missing_return
                  validator:(val){
                    if(val.isEmpty)
                      return 'Please Enter Your Password';
                  },
                  onSaved:(val){
                    password=val;
                  },
              ),
                RaisedButton(color: Colors.lightBlue,textColor: Colors.white,child: Text('Login'),
                  onPressed:login),
            ],)
              ,),)
         ),
    );
  }
}

【讨论】:

  • 请在您的答案中添加更多上下文。
【解决方案6】:

我建议使用这个插件flutter_easyloading

flutter_easyloading 是一款干净轻量的 Flutter App 加载小部件,无需上下文即可轻松使用,支持 iOS 和 Android

将此添加到您的包的pubspec.yaml 文件中:

dependencies:
  flutter_easyloading: ^2.0.0

现在在你的 Dart 代码中,你可以使用:

import 'package:flutter_easyloading/flutter_easyloading.dart';

使用首先,在MaterialApp/CupertinoApp中初始化FlutterEasyLoading

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter EasyLoading',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter EasyLoading'),
      builder: EasyLoading.init(),
    );
  }
}

EasyLoading 是一个单例,因此您可以像这样在任何地方自定义加载样式:

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import './custom_animation.dart';

void main() {
  runApp(MyApp());
  configLoading();
}

void configLoading() {
  EasyLoading.instance
    ..displayDuration = const Duration(milliseconds: 2000)
    ..indicatorType = EasyLoadingIndicatorType.fadingCircle
    ..loadingStyle = EasyLoadingStyle.dark
    ..indicatorSize = 45.0
    ..radius = 10.0
    ..progressColor = Colors.yellow
    ..backgroundColor = Colors.green
    ..indicatorColor = Colors.yellow
    ..textColor = Colors.yellow
    ..maskColor = Colors.blue.withOpacity(0.5)
    ..userInteractions = true
    ..customAnimation = CustomAnimation();
}

然后,根据您的要求使用

import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:dio/dio.dart';

class TestPage extends StatefulWidget {
  @override
  _TestPageState createState() => _TestPageState();
}

class _TestPageState extends State<TestPage> {
  @override
  void initState() {
    super.initState();
    // EasyLoading.show();
  }

  @override
  void deactivate() {
    EasyLoading.dismiss();
    super.deactivate();
  }

  void loadData() async {
    try {
      EasyLoading.show();
      Response response = await Dio().get('https://github.com');
      print(response);
      EasyLoading.dismiss();
    } catch (e) {
      EasyLoading.showError(e.toString());
      print(e);
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter EasyLoading'),
      ),
      body: Center(
        child: FlatButton(
          textColor: Colors.blue,
          child: Text('loadData'),
          onPressed: () {
            loadData();
            // await Future.delayed(Duration(seconds: 2));
            // EasyLoading.show(status: 'loading...');
            // await Future.delayed(Duration(seconds: 5));
            // EasyLoading.dismiss();
          },
        ),
      ),
    );
  }
}

【讨论】:

  • 自定义动画类在哪里?我们需要包含它吗?
  • 不,你不需要那个,如果你想去:github.com/huangjianke/flutter_easyloading/blob/develop/example/…
  • 请在 main.dart 文件中添加此行以添加:builder: EasyLoading.init():---
  • pub get failed (1; 因为tripzy_vendor依赖flutter_easyloading >=3.0.0 需要SDK版本>=2.12.0
  • 良好且易于使用。强烈推荐!
【解决方案7】:

我采用了以下方法,它使用了一个简单的模态进度指示器小部件,该小部件将您想要在异步调用期间创建模态的任何内容包装起来。

包中的示例还解决了如何在进行异步调用以验证表单时处理表单验证(有关此问题的详细信息,请参阅flutter/issues/9688)。例如,无需离开表单,此异步表单验证方法可用于在注册时根据数据库中的现有名称验证新用户名。

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

以下是随包提供的示例演示(附源代码):

示例可以适应其他模态进度指示器行为(如不同的动画、模态中的附加文本等)。

【讨论】:

    【解决方案8】:

    这是我的堆栈解决方案

    import 'package:flutter/material.dart';
    import 'package:shared_preferences/shared_preferences.dart';
    import 'dart:async';
    
    final themeColor = new Color(0xfff5a623);
    final primaryColor = new Color(0xff203152);
    final greyColor = new Color(0xffaeaeae);
    final greyColor2 = new Color(0xffE8E8E8);
    
    class LoadindScreen extends StatefulWidget {
      LoadindScreen({Key key, this.title}) : super(key: key);
      final String title;
      @override
      LoginScreenState createState() => new LoginScreenState();
    }
    
    class LoginScreenState extends State<LoadindScreen> {
      SharedPreferences prefs;
    
      bool isLoading = false;
    
      Future<Null> handleSignIn() async {
        setState(() {
          isLoading = true;
        });
        prefs = await SharedPreferences.getInstance();
        var isLoadingFuture = Future.delayed(const Duration(seconds: 3), () {
          return false;
        });
        isLoadingFuture.then((response) {
          setState(() {
            isLoading = response;
          });
        });
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
            appBar: AppBar(
              title: Text(
                widget.title,
                style: TextStyle(color: primaryColor, fontWeight: FontWeight.bold),
              ),
              centerTitle: true,
            ),
            body: Stack(
              children: <Widget>[
                Center(
                  child: FlatButton(
                      onPressed: handleSignIn,
                      child: Text(
                        'SIGN IN WITH GOOGLE',
                        style: TextStyle(fontSize: 16.0),
                      ),
                      color: Color(0xffdd4b39),
                      highlightColor: Color(0xffff7f7f),
                      splashColor: Colors.transparent,
                      textColor: Colors.white,
                      padding: EdgeInsets.fromLTRB(30.0, 15.0, 30.0, 15.0)),
                ),
    
                // Loading
                Positioned(
                  child: isLoading
                      ? Container(
                          child: Center(
                            child: CircularProgressIndicator(
                              valueColor: AlwaysStoppedAnimation<Color>(themeColor),
                            ),
                          ),
                          color: Colors.white.withOpacity(0.8),
                        )
                      : Container(),
                ),
              ],
            ));
      }
    }
    

    【讨论】:

      【解决方案9】:

      您可以为中心透明进度指示器做到这一点

      Future<Null> _submitDialog(BuildContext context) async {
        return await showDialog<Null>(
            context: context,
            barrierDismissible: false,
            builder: (BuildContext context) {
              return SimpleDialog(
                elevation: 0.0,
                backgroundColor: Colors.transparent,
                children: <Widget>[
                  Center(
                    child: CircularProgressIndicator(),
                  )
                ],
              );
            });
      }
      

      【讨论】:

        【解决方案10】:
        {
        isloading? progressIos:Container()
        
        progressIos(int i) {
            return Container(
                color: i == 1
                    ? AppColors.liteBlack
                    : i == 2 ? AppColors.darkBlack : i == 3 ? AppColors.pinkBtn : '',
                child: Center(child: CupertinoActivityIndicator()));
          }
        }
        

        【讨论】:

          【解决方案11】:

          您可以改用 FutureBuilder 小部件。这需要一个必须是 Future 的参数。然后你可以使用一个快照,它是登录时异步调用当时的状态,一旦它结束,异步函数返回的状态将被更新,未来的构建器将重建自己,这样你就可以请求新的状态。

          FutureBuilder(
            future:  myFutureFunction(),
            builder: (context, AsyncSnapshot<List<item>> snapshot) {
              if (!snapshot.hasData) {
                return Center(
                  child: CircularProgressIndicator(),
                );
              } else {
               //Send the user to the next page.
            },
          );
          

          这里有一个关于如何构建未来的示例

          Future<void> myFutureFunction() async{
           await callToApi();}
          

          【讨论】:

            【解决方案12】:

            在屏幕上居中:

            Column(
                mainAxisAlignment: MainAxisAlignment.center,
                mainAxisSize: MainAxisSize.max,
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                    Row(
                        mainAxisAlignment: MainAxisAlignment.center,
                        mainAxisSize: MainAxisSize.max,
                        children: [CircularProgressIndicator()])
                  ])
            

            【讨论】:

              【解决方案13】:
              class Loader extends StatefulWidget {
                    @override
                    State createState() => LoaderState();
                  }
              
                  class LoaderState extends State<Loader> with SingleTickerProviderStateMixin {
                    AnimationController controller;
                    Animation<double> animation;
              
                    @override
                    void initState() {
                      super.initState();
                      controller = AnimationController(
                          duration: Duration(milliseconds: 1200), vsync: this);
                      animation = CurvedAnimation(parent: controller, curve: Curves.elasticOut);
                      animation.addListener(() {
                        this.setState(() {});
                      });
                      animation.addStatusListener((AnimationStatus status) {});
                      controller.repeat();
                    }
              
                    @override
                    void dispose() {
                      controller.dispose();
                      super.dispose();
                    }
              
                    @override
                    Widget build(BuildContext context) {
                      return Column(
                        mainAxisAlignment: MainAxisAlignment.center,
                        children: <Widget>[
                          Container(
                            color: Colors.blue,
                            height: 3.0,
                            width: animation.value * 100.0,
                          ),
                          Padding(
                            padding: EdgeInsets.only(bottom: 5.0),
                          ),
                          Container(
                            color: Colors.blue[300],
                            height: 3.0,
                            width: animation.value * 75.0,
                          ),
                          Padding(
                            padding: EdgeInsets.only(bottom: 5.0),
                          ),
                          Container(
                            color: Colors.blue,
                            height: 3.0,
                            width: animation.value * 50.0,
                          )
                        ],
                      );
                    }
                  }
              
              
                  Expanded(
                                      child: Padding(
                                        padding:
                                            EdgeInsets.only(left: 20.0, right: 5.0, top:20.0),
                                        child: GestureDetector(
                                          onTap: () {
                                            Navigator.push(
                                                context,
                                                MaterialPageRoute(
                                                    builder: (context) => FirstScreen()));
                                          },
                                          child: Container(
                                              alignment: Alignment.center,
                                              height: 45.0,
                                              decoration: BoxDecoration(
                                                  color: Color(0xFF1976D2),
                                                  borderRadius: BorderRadius.circular(9.0)),
                                              child: Text('Login',
                                                  style: TextStyle(
                                                      fontSize: 20.0, color: Colors.white))),
                                        ),
                                      ),
                                    ),
              

              【讨论】:

              • 如何将一个创建加载指示器的类与我的按钮结合起来,以便当我按下它时,指示器会打开并翻转到下一页?
              猜你喜欢
              • 2023-03-03
              • 2019-03-01
              • 1970-01-01
              • 2018-11-01
              • 1970-01-01
              • 1970-01-01
              • 2018-07-07
              • 1970-01-01
              • 2022-11-01
              相关资源
              最近更新 更多