Wie arbeite ich mit der Fortschrittsanzeige im Flattern?

86

Ich bin ein Neuling im Flattern und wollte wissen, wie CircularProgressIndicatorich mein Layout besser hinzufügen kann . Zum Beispiel meine Login-Ansicht. Diese Ansicht hat Benutzername, Passwort und Login-Button. Ich wollte ein Overlay-Layout (mit Opacity) erstellen , das beim Laden eine Fortschrittsanzeige anzeigt, wie ich sie in NativeScript verwende, aber ich bin wenig verwirrt darüber, wie und auch, wenn es der bessere Weg ist. In NativeScript füge ich beispielsweise IndicatorActivity im Hauptlayout hinzu und setze beschäftigt auf wahr oder falsch, damit beim Laden alle Ansichtskomponenten überlagert werden.

Bearbeiten:

Ich konnte dieses Ergebnis erreichen:

    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),
            ),
          );
      }
    }

App-Bildschirm Ergebnis

Ich passe mich immer noch der Idee von Staaten an. Dieser Code liegt innerhalb der erwarteten bei der Arbeit mit Flattern?

Vielen Dank!

Ricardo Bocchi
quelle
1
Wie deaktiviere ich Backpressed, während der Dialog angezeigt wird?
Schneller Lerner

Antworten:

77

Beim Flattern gibt es einige Möglichkeiten, mit asynchronen Aktionen umzugehen.

Ein fauler Weg, dies zu tun, kann die Verwendung eines Modals sein. Dadurch wird die Benutzereingabe blockiert und unerwünschte Aktionen verhindert. Dies würde nur sehr geringe Änderungen an Ihrem Code erfordern. Ändern Sie einfach Ihre _onLoadingzu so etwas:

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();
  });
}

Der idealste Weg, dies zu tun, ist die Verwendung FutureBuildereines zustandsbehafteten Widgets. Welches ist, was Sie begonnen haben. Der Trick ist, dass Sie anstelle von a boolean loading = falsein Ihrem Bundesstaat direkt a verwenden könnenFuture<MyUser> user

Und übergeben Sie es dann als Argument an FutureBuilder, wodurch Sie einige Informationen wie "hasData" oder die Instanz von "Fertig" erhalten MyUser.

Dies würde zu so etwas führen:

@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),
          );
        }
      },
    );
  }
}
Rémi Rousselet
quelle
1
Cool, beide Beispiele sind nützlich für die Anmeldung und andere Situationen. Der Fortschritt des Handlers mit dem Dialog sieht besser aus als meine Version und FutureBuilder. Es ist auch eleganter als meine Lösung. danke für die Hilfe!
Ricardo Bocchi
Eine Frage außerhalb des Themas. Zu jedem TextField benötige ich einen eindeutigen TextEditingController?
Ricardo Bocchi
@ RicardoBocchi Ja
Aziza
Ich glaube nicht, dass der Dialog mit dem tatsächlichen Beispiel funktioniert. Es ist verwirrend, wie der Benutzer nach der Rückgabe von _login () umgeleitet wird. Ihr zweites Beispiel scheint jedoch viel bequemer zu sein. Gut gebacken.
Aziza
1
Nun, der Dialog ist funktionsfähig und erfordert nur sehr geringe Änderungen an seinem ursprünglichen Code. Er könnte zum Beispiel dem Dialog folgen und mit a schließen Navigator.pushNamed("/home").
Rémi Rousselet
38

Für mich besteht eine gute Möglichkeit darin, SnackBarwährend des Anmeldevorgangs unten ein zu zeigen. Dies ist ein Beispiel für das, was ich meine:

Geben Sie hier die Bildbeschreibung ein

Hier erfahren Sie, wie Sie das einrichten SnackBar.

Definieren Sie einen globalen Schlüssel für Ihre Scaffold

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

Fügen Sie es Ihrem Scaffold keyAttribut hinzu

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

onPressedRückruf meiner Anmeldeschaltfläche :

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")
                  );
                }

Es hängt wirklich davon ab, wie Sie Ihr Layout erstellen möchten, und ich bin mir nicht sicher, was Sie vorhaben.

Bearbeiten

Sie möchten es wahrscheinlich so, ich habe einen Stapel verwendet, um dieses Ergebnis zu erzielen und nur meinen Indikator basierend auf anzuzeigen oder auszublenden onPressed

Geben Sie hier die Bildbeschreibung ein

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,),

      ],));
  }

}
Aziza
quelle
Hallo, das wollte ich tun, aber ich bekam nicht das Layout, das ich brauchte. Stapel ist die Antwort. Ist es bei StatefulWidget korrekt, alle Ansichten zu erstellen, wenn sich der Fortschrittsstatus ändert?
Ricardo Bocchi
Hey, ich verstehe deine Frage nicht?
Aziza
In meinem Code werden beim _loadingÄndern alle Ansichten neu erstellt. Ist das so?
Ricardo Bocchi
1
Die Verwendung eines Modals ist wahrscheinlich viel einfacher und gleichzeitig intuitiver. Sie können einfach zu Beginn oder auf Anfrage einen Ladedialog drücken und ihn nach Abschluss öffnen. Es hat auch den Vorteil, weitere Benutzereingaben zu verhindern.
Rémi Rousselet
2
Okey, lass mich etwas backen.
Rémi Rousselet
34

Erstellen Sie einen Bool isLoadingund setzen Sie ihn auf false. Wenn der Benutzer mit Hilfe des ternären Operators auf die Anmeldeschaltfläche klickt, setzen Sie den Status isLoadingauf true. Anstelle der Anmeldeschaltfläche erhalten Sie eine kreisförmige Ladeanzeige

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

Sie können Screenshots sehen, wie es aussieht, bevor Sie auf die Anmeldung klicken Geben Sie hier die Bildbeschreibung ein

Nach dem Anmelden wird geklickt Geben Sie hier die Bildbeschreibung ein

In der Zwischenzeit können Sie den Anmeldevorgang und den Anmeldebenutzer ausführen. Wenn Benutzerdaten falsch sind dann wieder werden Sie setStatevon isLoadingzu false, so dass sich die Ladeanzeige unsichtbar und Login werden Schaltfläche Benutzer sichtbar. Der im Code verwendete PrimaryButton ist übrigens meine benutzerdefinierte Schaltfläche. Sie können dasselbe mit OnPressedin tun button.

Harsha Pulikollu
quelle
Das ist eigentlich ziemlich schlau! Kein Doppelklick usw. erforderlich. Danke.
Benobab
Wie gehe ich mit Doppelklick im Flattern wie in diesem Szenario um?
Ich habe diese Situation nie mit Doppelklopfen zu tun gehabt, da sie sich beim Einzelklopfen in eine Ladeanzeige ändert. Nach meinem Verständnis Ihres Kommentars können wir die benutzerdefinierte Schaltfläche mit einem Gesten-Detektor umschließen, und dann können Sie dort doppelt tippen.
Harsha Pulikollu
Wo soll der ternäre Operator verwendet werden? Ihr Beispiel sieht gut aus, ist sich aber nicht sicher, wie es implementiert werden soll.
Bikram Pahi
Verwenden Sie das oben genannte Code-Snippet in der Erstellungsmethode, in der Sie eine (Anmelde-) Schaltfläche haben möchten. Wenn der Benutzer auf diese Schaltfläche klickt, wird der Bool (isLoading) wahr und zeigt anstelle der Schaltfläche die kreisförmige Ladeanzeige an.
Harsha Pulikollu
20

1. Ohne Plugin

    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. Mit Plugin

Überprüfen Sie dieses Plugin progress_hud

Fügen Sie die Abhängigkeit in die Datei pubspec.yaml ein

dev_dependencies:
  progress_hud: 

Importieren Sie das Paket

import 'package:progress_hud/progress_hud.dart';

Im Folgenden finden Sie einen Beispielcode zum Ein- und Ausblenden des Indikators

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;
  }
}
Shyju M.
quelle
12
Stimmen Sie nicht ab, einige Leute wollen nicht mit den Details der Benutzeroberfläche umgehen und sind einer von ihnen, daher ist dieses Plugin praktisch
Vladtn
3
Der Fortschrittsbalken in der API ist fair genug, um durch Hinzufügen von Abhängigkeiten die Build-Größe zu erhöhen. bereits flattern ist zu groß.
prashant0205
Sollten Sie dies wirklich als Dev-Abhängigkeit hinzufügen?
George
Überprüfen Sie mit dem neuesten Beispiel pub.dartlang.org/packages/progress_hud#-example-tab-
Shyju M
1
@MohammadMeshkani benutze Navigator.pop (Kontext); bevor Sie zum nächsten Bildschirm
navigieren
13

Schritt 1: Dialog erstellen

   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;
        },
      );
    }

Schritt 2: Nennen Sie es

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

Beispiel mit Dialog und Anmeldeformular

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),
            ],)
              ,),)
         ),
    );
  }
}

Geben Sie hier die Bildbeschreibung ein

Hamdy Abd El Fattah
quelle
2
Bitte fügen Sie Ihrer Antwort etwas mehr Kontext hinzu.
Tod Waltz
10

Ich habe den folgenden Ansatz gewählt, bei dem ein einfaches Widget für die Anzeige des modalen Fortschritts verwendet wird, das alles umschließt, was Sie während eines asynchronen Aufrufs modal machen möchten.

Das Beispiel im Paket beschreibt auch, wie die Formularüberprüfung behandelt wird, während asynchrone Aufrufe zur Überprüfung des Formulars ausgeführt werden ( Einzelheiten zu diesem Problem finden Sie unter flutter / issue / 9688 ). Ohne das Formular zu verlassen, kann diese asynchrone Formularüberprüfungsmethode beispielsweise verwendet werden, um einen neuen Benutzernamen bei der Anmeldung anhand vorhandener Namen in einer Datenbank zu überprüfen.

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

Hier ist die Demo des mit dem Paket gelieferten Beispiels (mit Quellcode):

asynchrone Formularvalidierung mit modalem Fortschrittsindikator

Das Beispiel könnte an ein anderes Verhalten der modalen Fortschrittsanzeige angepasst werden (z. B. unterschiedliche Animationen, zusätzlicher Text in Modal usw.).

mmccabe
quelle
2

Dies ist meine Lösung mit Stack

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(),
            ),
          ],
        ));
  }
}
Kokemomuke
quelle
2

Ich schlage vor, dieses Plugin flutter_easyloading zu verwenden

flutter_easyloading ist ein sauberes und leichtes Lade-Widget für die Flutter App, das ohne Kontext einfach zu verwenden ist und iOS und Android unterstützt

Fügen Sie dies der pubspec.yamlDatei Ihres Pakets hinzu :

dependencies:
  flutter_easyloading: ^2.0.0

Jetzt können Sie in Ihrem Dart-Code Folgendes verwenden:

import 'package:flutter_easyloading/flutter_easyloading.dart';

Um First zu verwenden, initialisieren Sie FlutterEasyLoadingin MaterialApp/CupertinoApp

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

import './test.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();
}

Verwenden Sie dann gemäß Ihren Anforderungen

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();
          },
        ),
      ),
    );
  }
}

Geben Sie hier die Bildbeschreibung ein

Paresh Mangukiya
quelle
Wo ist die benutzerdefinierte Animationsklasse? Müssen wir es aufnehmen?
Nayas Subramanian
Nein, das brauchen Sie nicht, und wenn Sie möchten, gehen Sie zu: github.com/huangjianke/flutter_easyloading/blob/develop/example/…
Paresh Mangukiya
1

Sie können stattdessen das FutureBuilder-Widget verwenden. Dies erfordert ein Argument, das eine Zukunft sein muss. Anschließend können Sie beim Anmelden einen Snapshot verwenden, der den aktuellen Status des asynchronen Aufrufs darstellt. Sobald dieser beendet ist, wird der Status der asynchronen Funktionsrückgabe aktualisiert und der zukünftige Builder wird sich selbst neu erstellen, sodass Sie nach dem neuen fragen können Zustand.

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

Hier haben Sie ein Beispiel, wie Sie eine Zukunft aufbauen können

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

Sie können dies für die mittlere transparente Fortschrittsanzeige tun

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(),
            )
          ],
        );
      });
}
Cenk YAGMUR
quelle
0
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))),
                          ),
                        ),
                      ),
Max Zubko
quelle
Wie kann ich eine Klasse, die eine Ladeanzeige erstellt, mit meiner Schaltfläche kombinieren, sodass die Anzeige beim Drücken eingeschaltet wird und zur nächsten Seite wechselt?
Max Zubko
0
{
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()));
  }
}
Ashwani Sharma
quelle