Sunday, September 26, 2021

Set up App Loading or Progress indicator using dialog box in Flutter

Ideally, the progress indicator is shown on top of everything, preventing the user from interacting with the UI.
we want is to display a context so that the user knows, what he is actually waiting for. So let’s add some descriptive text and put everything in a container to make it stand out from the rest of the widget.
Full code example below:
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: ApplicationBase(),
    );
  }
}

class ApplicationBase extends StatefulWidget {
  const ApplicationBase({Key? key}) : super(key: key);

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

class _ApplicationBaseState extends State<ApplicationBase> {
  int _counter = 0;

  // flutter thread to load data
  Future loadDataAsync() async {
    return Future.delayed(Duration(seconds: 5), () {
      setState(() {
        _counter++;
      });
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("My Test App"),
      ),
      body: Center(
          child: Text('Count = $_counter')
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          _onPressed(context);
        },
        child: Icon(Icons.add),
      ),
    );
  }

  void _onPressed(BuildContext context) async {
    // showing progress bar at dialog
    DialogBuilder(context).showLoadingIndicator();
    // loading data in thread and using [await] to wait for completion of task
    await loadDataAsync();
    // hiding dialog
    DialogBuilder(context).hideOpenDialog();
  }
}

class DialogBuilder {
  DialogBuilder(this.context);

  final BuildContext context;

  void showLoadingIndicator() {
    showDialog(
      context: context,
      //disable disappear dialog on touch on screen
      barrierDismissible: false,
      builder: (BuildContext context) {
        return WillPopScope(
          //this will prevent close dialog on press back button
          onWillPop: () async => false,
          child: AlertDialog(
            shape: RoundedRectangleBorder(
                borderRadius: BorderRadius.all(Radius.circular(8.0))
            ),
            backgroundColor: Colors.black87,
            content: Container(
                padding: EdgeInsets.all(16),
                color: Colors.black87,
                child: Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      Padding(
                          child: Container(
                              child: CircularProgressIndicator(
                                  strokeWidth: 3
                              ),
                              width: 40,
                              height: 40
                          ),
                          padding: EdgeInsets.only(bottom: 16)
                      ),
                      Padding(
                          child: Text(
                            'Please wait ...',
                            style: TextStyle(
                                color: Colors.white,
                                fontSize: 16
                            ),
                            textAlign: TextAlign.center,
                          ),
                          padding: EdgeInsets.only(bottom: 4)
                      )
                    ]
                ),
            ),
          ),
        );
      },
    );
  }

  void hideOpenDialog() {
    //disappear dialog
    Navigator.of(context).pop();
  }
}
Now, what we have is something like that:

No comments:

Post a Comment