Search code examples
flutteruser-interfaceloadingflutter-getx

Loading bar with getx state management


I have a project which uses getx state management and in the register section When a user clicks the register button I want to show a loading bar on top of all widgets that blocks out the user interaction with the text fields,

I will give my getx controller and UI below

getx controller

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/foundation.dart';
import 'package:get/get.dart';
import 'package:helping_hand/UI/Map/Mappage.dart';
import 'package:helping_hand/drawers/bottomnavbar.dart';

import '../Utils/Auth.dart';

class AuthenticationController extends GetxController{

late String errormessage;

  Future<void> createUserWithEmailAndPassword(Map<String,String> userData) async {
    loadingbar();
    try {
      await Auth().createUserwithEmailAndPassword(email:userData['e-mail']!, password:userData['password']!);
      Get.to(()=>Nav());
    } on FirebaseAuthException catch (e) {
         errormessage = e.message!;
         if (kDebugMode) {
           print(e);
         }
    }
    loadingbaroff();
  }

  //cloud firestore using firestore
  final CollectionReference citizen = FirebaseFirestore.instance.collection('citizen');

  Future<void>addUser(Map<String,String> userData)async{
    loadingbar();
    try{
      await citizen.doc(userData['e-mail']).set({
        "first_name":userData['first_name'],"last_name":userData['last_name'],"public_name":userData['public_name'],
        "password":userData['password'],"mobile_num":userData['mobile_num'],
        "emergency_num":userData['emergency_num'],"e-mail":userData['e-mail'],
        "postal_code":userData['postal_code'],"birth_year":userData['birth_year'],
        "user_role":userData['user_role'],
      });
      }catch(err){
        if (kDebugMode) {
          print(err);
        }
      }
      loadingbaroff();
    }


Future<void> signInWithEmailAndPassword(String email,String password) async {
    loadingbar();
  try {
    await Auth().signInwithEmailAndPassword(email: email, password:password);
    Get.to(()=>Nav());
  } on FirebaseAuthException catch (e) {
      var errormessage2 = e.message!;
      if (kDebugMode) {
        print(e);
      }
  }
  loadingbaroff();
}

bool isloading = false;

  void loadingbar() {
    isloading = true;
    update();
  }

  void loadingbaroff() {
  isloading = false;
  update();
  }

}

Register page:

import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:get/get_core/src/get_main.dart';
import 'package:helping_hand/StateManagement/AuthenticationController.dart';
import 'package:helping_hand/UI/Authentication/LoginUser.dart';

import '../../Constants/Constants.dart';
import '../../Utils/Auth.dart';
import '../../drawers/bottomnavbar.dart';
import '../Bottom Navigation/My status.dart';

class RegisterUser extends StatelessWidget {
   RegisterUser({Key? key}) : super(key: key);

  final TextEditingController _controller_email = TextEditingController();
  final TextEditingController _controller_password = TextEditingController();
  final TextEditingController _controller_firstname = TextEditingController();
  final TextEditingController _controller_lastname = TextEditingController();
  final TextEditingController _controller_publicname = TextEditingController();
  final TextEditingController _controller_passwordconfirm = TextEditingController();
  final TextEditingController _controllerphone_number = TextEditingController();
  final TextEditingController _controller_emergencynumber = TextEditingController();
  final TextEditingController _controller_postalcode = TextEditingController();
  final TextEditingController _controller_birthyear = TextEditingController();
  final TextEditingController _controller_countrycode = TextEditingController();

   List<String> status = ['Citizen','Private Responder','Provider','Government'];

   TextEditingController selectpartycontroller = TextEditingController();

  final GlobalKey<FormState> _formkey = GlobalKey<FormState>();

  @override
  Widget build(BuildContext context) {
    AuthenticationController authcontroller  = Get.put(AuthenticationController());
    return Scaffold(
      backgroundColor: Colors.redAccent,
      appBar: AppBar(elevation: 0,backgroundColor: Colors.transparent,centerTitle: true,
        title: const Text('Helping hands',style: TextStyle(fontSize:25,color: Colors.white),),),
      body: Container(
        height:MediaQuery.of(context).size.height,
        width: MediaQuery.of(context).size.width,
        margin: const EdgeInsets.all(16),
        child: SingleChildScrollView(
          child: Form(
            key: _formkey,
            child: Column(
              children: [
                const NeumorphicContainer(marginbottom: 10,child:CircleAvatar(backgroundColor: Colors.redAccent,radius:50,backgroundImage: AssetImage('assets/undraw/profilepicture.png'),)),
                const Text('Lets Get you Started ',style: TextStyle(fontSize:25,color: Colors.white),),
                const SizedBox(height: 30,),
                UserTextInput(controller: _controller_firstname,hinttext: 'firstname *',),
                UserTextInput(controller: _controller_lastname,hinttext:'lastname *',),
                UserTextInput(controller: _controller_publicname,hinttext: 'public Name *',),
                UserTextInput(controller: _controller_password,hinttext: 'password 8-character minimum *',obscuretext: true,),
                UserTextInput(controller: _controller_passwordconfirm,hinttext: 'confirm password *',obscuretext: true,),
                Row(children: [
                  Expanded(
                    flex: 1,
                      child: UserTextInput(controller: _controller_countrycode,hinttext: '+91',)),
                  Expanded(
                    flex: 3,
                      child: UserTextInput(controller: _controllerphone_number,hinttext: 'mobile phone number (10 digits)',)),
                ],),
                UserTextInput(controller: _controller_emergencynumber,hinttext: 'Local government emergency number *',),
                UserTextInput(controller: _controller_email,hinttext: 'e-mail *',),
                UserTextInput(controller: _controller_postalcode,hinttext: 'postal code',),
                UserTextInput(controller: _controller_birthyear,hinttext: 'birth year',),
                Listpicker(status: status, selectpartycontroller: selectpartycontroller),
                const SizedBox(height: 16,),
                NeumorphicContainer(
                  marginbottom: 24,
                  child: ElevatedButton(
                    onPressed: ()  {
                      final FormState? form = _formkey.currentState;
                      try{
                        if(form!.validate() && selectpartycontroller.text.isNotEmpty){
                          toMap();
                          Get.to(()=>Nav());
                        }else{
                          Get.snackbar('Fill','Fill form details',
                              icon: const Icon(Icons.error_outline,color: Colors.redAccent,),backgroundColor: Colors.white,
                              colorText: Colors.redAccent);
                        }
                      }catch(e){
                        if (kDebugMode) {
                          print(e);
                        }
                      }
                    },
                    style: ElevatedButton.styleFrom(backgroundColor: Colors.redAccent),
                    child: const Text('Register', style: TextStyle(color: Colors.white),
                    ),
                  ),
                ),
                Container(
                  margin: const EdgeInsets.only(top: 20,bottom: 40),
                  child: InkWell(
                      onTap: ()  {
                        Get.to(()=>LoginUser());
                      },
                      child: const Text(
                          'Already Registered ?? Click to Login',
                          style: TextStyle(color: Colors.white))),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }


void toMap(){
  Map<String,String> userData = ({
    "first_name":_controller_firstname.text.toString(),"last_name":_controller_lastname.text.toString(),"public_name":_controller_publicname.text.toString(),
    "password":_controller_password.text.toString(),"mobile_num":_controllerphone_number.text.toString(),
    "emergency_num":_controller_emergencynumber.text.toString(),"e-mail":_controller_email.text.toString(),
    "postal_code":_controller_postalcode.text.toString(),"birth_year":_controller_birthyear.text.toString(),
    "user_role":selectpartycontroller.text.toString(),
  });

  Userbox.write('userdata',userData);
  if (kDebugMode) {
   var userinfo =  Userbox.read('userdata');
   print(userinfo['e-mail']);
   print('this is data stored :::: ${Userbox.read('userlogindata')}');
   print('this is user data ::::${Userbox.read('userdata')}');
  }
  }

}



class UserTextInput extends StatelessWidget {
  final TextEditingController controller;
  final String? hinttext;
  final bool? obscuretext;
  const UserTextInput({
    Key? key, required this.controller, this.hinttext, this.obscuretext,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Container(
      margin: const EdgeInsets.only(bottom:16),
      padding: const EdgeInsets.all(8),
      child: TextFormField(
          autovalidateMode: AutovalidateMode.onUserInteraction,
          obscureText: obscuretext!=null?true:false,
          controller: controller,
          validator: (value){
            if(value == null||value.isEmpty){
              return 'please enter the details';
            }
            return null;
          },
          decoration:  InputDecoration(
            hintStyle: const TextStyle(color:Colors.white),
            hintText: hinttext,
            enabledBorder: OutlineInputBorder(
              borderRadius: BorderRadius.circular(16.0),
              borderSide: const BorderSide(
                color: Colors.red,
                width: 2.0,
              ),
            ),
            focusedBorder: OutlineInputBorder(
              borderRadius: BorderRadius.circular(16.0),
              borderSide: const BorderSide(
                color: Colors.white,
              ),
            ),
          )),
    );
  }
}

notice that I am not calling any function from the controller(because I can't figure out how to implement this loading bar on top of all widgets)is there any widgets in flutter that does the job?


Solution

  • You need to create a custom loading in top of all widgets using a Stack as parent of all. Something like this:

      @override
      Widget build(BuildContext context) {
        AuthenticationController authcontroller =
            Get.put(AuthenticationController());
        return Scaffold(
            backgroundColor: Colors.redAccent,
            appBar: AppBar(
              elevation: 0,
              backgroundColor: Colors.transparent,
              centerTitle: true,
              title: const Text(
                'Helping hands',
                style: TextStyle(fontSize: 25, color: Colors.white),
              ),
            ),
            body: Stack(children: [
              //all your last widget form (Container(...
              Obx(
                () {
                  if (authcontroller.isloading.value == true) {
                    return Container(
                      color: Colors.white.withOpacity(0.5),
                      child: const Center(
                        child: CircularProgressIndicator(),
                      ),
                    );
                  } else {
                    return const SizedBox.shrink();
                  }
                },
              )
            ]));
      }
    

    But you need to declare isloading like this:

    RxBool isloading = false.obs;