วิธีการทำงานกับตัวบ่งชี้ความคืบหน้าในการกระพือปีก?


93

ฉันเป็นมือใหม่และอยากรู้ว่าอะไรคือวิธีที่ดีกว่าในการเพิ่มCircularProgressIndicatorเค้าโครงของฉัน ตัวอย่างเช่นมุมมองการเข้าสู่ระบบของฉัน มุมมองนี้มีชื่อผู้ใช้รหัสผ่านและปุ่มล็อกอิน ฉันไม่ต้องการสร้างเลย์เอาต์การวางซ้อน (ด้วยOpacity) ที่เมื่อโหลดแสดงตัวบ่งชี้ความคืบหน้าเหมือนที่ฉันใช้ใน NativeScript แต่ฉันไม่ค่อยสับสนกับวิธีการทำและเช่นกันถ้าเป็นวิธีที่ดีกว่า บน NativeScript ฉันเพิ่ม IndicatorActivity ในเค้าโครงหลักและตั้งค่าไม่ว่างเป็นจริงหรือเท็จดังนั้นจึงซ้อนทับส่วนประกอบมุมมองทั้งหมดเมื่อกำลังโหลด

แก้ไข:

ฉันสามารถบรรลุผลลัพธ์นี้:

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

ผลหน้าจอแอพ

ฉันยังคงปรับตัวให้เข้ากับแนวคิดของรัฐ รหัสนี้อยู่ในความคาดหมายเมื่อทำงานกับกระพือปีก?

ขอบคุณ!


1
วิธีปิดการใช้งาน backpressed ในขณะที่กล่องโต้ตอบกำลังแสดงอยู่?
เรียนด่วน

คำตอบ:


83

ในการกระพือมีสองสามวิธีในการจัดการกับการกระทำแบบอะซิงโครนัส

วิธีที่ขี้เกียจทำได้คือใช้กิริยา ซึ่งจะบล็อกการป้อนข้อมูลของผู้ใช้จึงป้องกันการกระทำที่ไม่ต้องการ สิ่งนี้ต้องการการเปลี่ยนแปลงเล็กน้อยในรหัสของคุณ เพียงแค่ปรับเปลี่ยนของคุณ_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และวิดเจ็ตที่มีสถานะ ซึ่งเป็นสิ่งที่คุณเริ่มต้น เคล็ดลับคือแทนที่จะมีboolean loading = falseสถานะของคุณคุณสามารถใช้ไฟล์Future<MyUser> user

จากนั้นส่งเป็นอาร์กิวเมนต์ไป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),
          );
        }
      },
    );
  }
}

1
เจ๋งทั้งสองตัวอย่างจะเป็นประโยชน์ในการเข้าสู่ระบบและสถานการณ์อื่น ๆ ความคืบหน้าของตัวจัดการพร้อมกล่องโต้ตอบดูดีกว่าเวอร์ชันของฉันและ FutureBuilder มันหรูหรากว่าโซลูชันของฉันด้วย ขอบคุณที่ช่วยเหลือ!
Ricardo Bocchi

คำถามนอกหัวข้อ .. ในแต่ละ TextField ฉันต้องการ TextEditingController ที่ไม่ซ้ำกัน?
Ricardo Bocchi

@RicardoBocchi ใช่
aziza

ฉันไม่คิดว่ากล่องโต้ตอบจะใช้งานได้กับตัวอย่างจริงมันทำให้สับสนว่าจะเปลี่ยนเส้นทางผู้ใช้อย่างไรหลังจากส่งคืน _login () ตัวอย่างที่สองของคุณดูเหมือนจะสะดวกกว่า อบอย่างดี.
aziza

1
กล่องโต้ตอบใช้งานได้และต้องการการปรับเปลี่ยนโค้ดดั้งเดิมของเขาเพียงเล็กน้อย ตัวอย่างเช่นเขาสามารถทำตามกล่องโต้ตอบปิดด้วยไฟล์Navigator.pushNamed("/home").
Rémi Rousselet

40

สำหรับฉันวิธีหนึ่งที่ทำได้อย่างเป็นระเบียบคือการแสดง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")
                  );
                }

ขึ้นอยู่กับว่าคุณต้องการสร้างเลย์เอาต์อย่างไรและฉันไม่แน่ใจว่าคุณคิดอะไรอยู่

แก้ไข

คุณอาจต้องการวิธีนี้ฉันได้ใช้ Stack เพื่อให้ได้ผลลัพธ์นี้และแสดงหรือซ่อนตัวบ่งชี้ของฉันตาม 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,),

      ],));
  }

}

สวัสดีนั่นคือสิ่งที่ฉันอยากทำ แต่ฉันไม่ได้รับเค้าโครงที่ต้องการ Stack คือคำตอบ เกี่ยวกับ StatefulWidget การสร้างมุมมองทั้งหมดถูกต้องหรือไม่เมื่อสถานะความคืบหน้าเปลี่ยนไป
Ricardo Bocchi

เฮ้ฉันไม่เข้าใจคำถามของคุณ?
aziza

ในรหัสของฉันเมื่อมี_loadingการเปลี่ยนแปลงมุมมองทั้งหมดจะถูกสร้างขึ้นใหม่ ขนาดนั้นเลยเหรอ
Ricardo Bocchi

1
การใช้โมดอลน่าจะง่ายกว่าและใช้งานง่ายกว่ามากในเวลาเดียวกัน คุณสามารถกดกล่องโต้ตอบการโหลดที่การร้องขอหรือคำขอของคุณและเปิดขึ้นเมื่อเสร็จสิ้น นอกจากนี้ยังมีข้อดีในการป้องกันการป้อนข้อมูลของผู้ใช้เพิ่มเติม
Rémi Rousselet

2
โอเคให้ฉันอบอะไรสักอย่าง
Rémi Rousselet

39

สร้างบูลและตั้งค่าให้isLoading falseด้วยความช่วยเหลือของผู้ประกอบการ ternary เมื่อผู้ใช้คลิกที่ปุ่มเข้าสู่ระบบรัฐชุดของการisLoading trueคุณจะได้รับสัญลักษณ์แสดงการโหลดแบบวงกลมแทนปุ่มล็อกอิน

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

คุณสามารถดูภาพหน้าจอได้ว่ามีลักษณะอย่างไรก่อนที่จะคลิกเข้าสู่ระบบ ใส่คำอธิบายภาพที่นี่

หลังจากเข้าสู่ระบบแล้วคลิก ใส่คำอธิบายภาพที่นี่

ในเวลานั้นคุณสามารถเรียกใช้กระบวนการเข้าสู่ระบบและผู้ใช้เข้าสู่ระบบ หากผู้ใช้สิทธิไม่ถูกต้องอีกครั้งแล้วคุณจะได้setStateของisLoadingไปfalseเช่นตัวบ่งชี้ในการโหลดที่จะกลายเป็นมองไม่เห็นและเข้าสู่ระบบปุ่มที่มองเห็นให้กับผู้ใช้ ยังไงก็ตาม primaryButton ที่ใช้ในโค้ดคือปุ่มกำหนดเองของฉัน คุณสามารถทำเช่นเดียวกันกับOnPressedในbutton.


ฉลาดจริงๆ! ไม่จำเป็นต้องจัดการดับเบิลคลิกเป็นต้นขอบคุณ
Benobab

วิธีจัดการดับเบิ้ลคลิกอย่างกระพือปีกเช่นนี้?

ฉันไม่เคยมีสถานการณ์นั้นที่จะจัดการกับการแตะสองครั้งได้เลยเมื่อแตะเพียงครั้งเดียวมันจะเปลี่ยนเป็นตัวบ่งชี้การโหลด ตามความเข้าใจของฉันเกี่ยวกับความคิดเห็นของคุณฉันคิดว่าเราสามารถปิดปุ่มที่กำหนดเองด้วยเครื่องตรวจจับท่าทางจากนั้นคุณสามารถใช้การแตะสองครั้งได้ที่นั่น
Harsha pulikollu

จะใช้ตัวดำเนินการ ternary ได้ที่ไหน? ตัวอย่างของคุณดูฉลาด แต่ไม่แน่ใจว่าจะนำไปใช้อย่างไร
Bikram Pahi

ใช้ข้อมูลโค้ดที่กล่าวถึงข้างต้นในวิธีการสร้างที่คุณต้องการมีปุ่ม (เข้าสู่ระบบ) เมื่อผู้ใช้คลิกปุ่มนั้นบูล (isLoading) จะกลายเป็นจริงและแสดงตัวบ่งชี้การโหลดแบบวงกลมแทนปุ่ม
Harsha pulikollu

24

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

12
อย่าลงคะแนนสิ่งนี้บางคนไม่ต้องการจัดการกับรายละเอียดที่สำคัญของ UI และเป็นหนึ่งในนั้นดังนั้นปลั๊กอินนี้จึงมีประโยชน์
Vladtn

3
แถบความคืบหน้าใน api มีความยุติธรรมเพียงพอที่จะเพิ่มการอ้างอิงเพิ่มขนาดบิวด์ การสร้างกระพือปีกมากเกินไปแล้ว
prashant0205

คุณควรเพิ่มสิ่งนี้เป็น Dev Dependency หรือไม่?
George

ตรวจสอบกับตัวอย่างล่าสุดpub.dartlang.org/packages/progress_hud#-example-tab-
Shyju M

1
@MohammadMeshkani ใช้ Navigator.pop (บริบท); ก่อนที่จะไปที่หน้าจอถัดไป
Shyju M

17

ขั้นตอนที่ 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);

ตัวอย่างด้วย Dialog และแบบฟอร์มเข้าสู่ระบบ

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

ใส่คำอธิบายภาพที่นี่


2
โปรดเพิ่มบริบทเพิ่มเติมให้กับคำตอบของคุณ
Death Waltz

10

ฉันใช้วิธีการต่อไปนี้ซึ่งใช้วิดเจ็ตตัวบ่งชี้ความคืบหน้าแบบโมดอลแบบง่ายที่ครอบคลุมสิ่งที่คุณต้องการสร้างโมดอลระหว่างการโทรแบบไม่ซิงค์

ตัวอย่างในแพ็กเกจยังกล่าวถึงวิธีจัดการกับการตรวจสอบความถูกต้องของฟอร์มในขณะที่ทำการเรียกแบบ async เพื่อตรวจสอบความถูกต้องของแบบฟอร์ม (ดูflutter / issues / 9688สำหรับรายละเอียดของปัญหานี้) ตัวอย่างเช่นโดยไม่ต้องออกจากฟอร์มวิธีการตรวจสอบฟอร์ม async นี้สามารถใช้เพื่อตรวจสอบความถูกต้องของชื่อผู้ใช้ใหม่กับชื่อที่มีอยู่ในฐานข้อมูลขณะสมัคร

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

นี่คือตัวอย่างของตัวอย่างที่มาพร้อมกับแพ็คเกจ (พร้อมซอร์สโค้ด):

การตรวจสอบแบบฟอร์ม async พร้อมตัวบ่งชี้ความคืบหน้าของโมดอล

ตัวอย่างสามารถปรับให้เข้ากับพฤติกรรมตัวบ่งชี้ความคืบหน้าของโมดอลอื่น ๆ (เช่นภาพเคลื่อนไหวที่แตกต่างกันข้อความเพิ่มเติมในโมดอล ฯลฯ )


2

นี่คือวิธีแก้ปัญหาของฉันด้วยสแต็ก

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

2

คุณสามารถทำได้สำหรับตัวบ่งชี้ความคืบหน้ากึ่งกลาง

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

2

ฉันขอแนะนำให้ใช้ปลั๊กอินนี้flutter_easyloading

flutter_easyloading เป็นวิดเจ็ตการโหลดที่สะอาดและน้ำหนักเบาสำหรับ Flutter App ใช้งานง่ายโดยไม่มีบริบทรองรับ iOS และ Android

เพิ่มสิ่งนี้ลงในpubspec.yamlไฟล์ของแพ็คเกจของคุณ:

dependencies:
  flutter_easyloading: ^2.0.0

ตอนนี้ในรหัส Dart ของคุณคุณสามารถใช้:

import 'package:flutter_easyloading/flutter_easyloading.dart';

ในการใช้ขั้นแรกให้เริ่มต้นFlutterEasyLoadingใน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();
}

จากนั้นใช้ตามความต้องการของคุณ

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

ใส่คำอธิบายภาพที่นี่


คลาสแอนิเมชั่นที่กำหนดเองอยู่ที่ไหน เราจำเป็นต้องรวมไว้ด้วยไหม
Nayas Subramanian

ไม่คุณไม่จำเป็นต้องทำเช่นนั้นและหากต้องการไปที่: github.com/huangjianke/flutter_easyloading/blob/develop/example/…
Paresh Mangukiya

1

คุณสามารถใช้วิดเจ็ต FutureBuilder แทนได้ สิ่งนี้ต้องใช้การโต้แย้งซึ่งต้องเป็นอนาคต จากนั้นคุณสามารถใช้สแน็ปช็อตซึ่งเป็นสถานะในขณะที่ทำการเรียก async เมื่อเข้าสู่ระบบเมื่อสิ้นสุดสถานะของการส่งคืนฟังก์ชัน async จะได้รับการอัปเดตและตัวสร้างในอนาคตจะสร้างตัวเองใหม่เพื่อให้คุณสามารถขอใหม่ได้ สถานะ.

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

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

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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.