Creating Animation Chatting App using Flutter!
Harshit Dawar
Senior Consultant Development@Infogain | RHCA | CKA | 8x RedHat, 7x Azure, 7x Databricks Certified | Technical Architect | Databricks & Linux Foundation Official Instructor | AWS CB | Terraform & Vault Certified
The current trend in developing mobile applications is moving towards the use of Flutter because it has the support of Mobile development as well as website development, it also supports hot reload. In addition to that, it is developed by Google, which obviously makes it a trustable solution.
This app will contain 5 different files, one of them is the main file for calling the different routes to the other files, another file is the home file to show the Register & Login buttons, another file is for registration file which is used to register a user for the chat account using Firebase, another one is for login using Firebase & the final one is for Streaming Chat, which will load all the messages on the mobile display on the fly.
There are few dependencies for this project which has to be included in the pubspec.yml file, for the complete project code, its link has been provided at the end of this article. There is one pre-requisite for this article, & that is you should know how to connect flutter application to Firebase.
Code for the Main file:
import 'package:ChatApp/StreamingChat.dart'; import 'package:ChatApp/home.dart'; import 'package:ChatApp/login.dart'; import 'package:ChatApp/register.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:flutter/material.dart'; void main() { WidgetsFlutterBinding.ensureInitialized(); Firebase.initializeApp(); runApp(MaterialApp( debugShowCheckedModeBanner: false, initialRoute: "/", routes: { "/": (context) => MyHome(), "/register": (context) => MyReg(), "/login": (context) => MyLogin(), "/streamingchat": (context) => StreamingChat(), }, ));
}
Code for the Home file:
import 'package:flutter/material.dart'; class MyHome extends StatefulWidget { @override _MyHomeState createState() => _MyHomeState(); } class _MyHomeState extends State<MyHome> { @override Widget build(BuildContext context) { return Container( child: MaterialApp( debugShowCheckedModeBanner: false, home: Scaffold( appBar: AppBar( title: Text( "Chat App", style: TextStyle( fontSize: 25, fontStyle: FontStyle.italic, fontWeight: FontWeight.bold, ), ), ), body: Container( width: double.infinity, alignment: Alignment.center, child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ Material( color: Colors.lightGreenAccent, borderRadius: BorderRadius.circular(20), elevation: 15, child: MaterialButton( minWidth: 250, child: Text( "Register", style: TextStyle( fontSize: 25, fontStyle: FontStyle.italic, fontWeight: FontWeight.bold, color: Colors.deepOrange, ), ), onPressed: () { Navigator.pushNamed(context, "/register"); }), ), SizedBox( height: 25, ), Material( color: Colors.lightGreenAccent, borderRadius: BorderRadius.circular(20), elevation: 15, child: MaterialButton( minWidth: 250, child: Text( "Login", style: TextStyle( fontSize: 25, fontStyle: FontStyle.italic, fontWeight: FontWeight.bold, color: Colors.deepOrange, ), ), onPressed: () { Navigator.pushNamed(context, "/login"); }), ), SizedBox( height: 15, ), ], ), ), ), ), ); }
}
Code for the Registration file:
import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/material.dart'; class MyReg extends StatefulWidget { @override _MyRegState createState() => _MyRegState(); } class _MyRegState extends State<MyReg> { var authenticate = FirebaseAuth.instance; String email; String password; @override Widget build(BuildContext context) { return Container( child: MaterialApp( debugShowCheckedModeBanner: false, home: Scaffold( appBar: AppBar( title: Text( "Registration Page", style: TextStyle( fontSize: 25, fontStyle: FontStyle.italic, fontWeight: FontWeight.bold, ), ), ), body: Center( child: Container( width: 300, child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Material( //color: Colors.pinkAccent[100], //borderRadius: BorderRadius.circular(20), //elevation: 15, child: TextField( // Assigning the Email Address Keyboard Type keyboardType: TextInputType.emailAddress, decoration: InputDecoration( hintText: "Enter Email ID", border: OutlineInputBorder( borderRadius: BorderRadius.circular(30), )), onChanged: (value) { email = value; }, )), SizedBox( height: 25, ), Material( //color: Colors.pinkAccent[100], //borderRadius: BorderRadius.circular(20), //elevation: 15, child: TextField( // Assigning the Email Address Keyboard Type keyboardType: TextInputType.multiline, obscureText: true, decoration: InputDecoration( hintText: "Password", border: OutlineInputBorder( borderRadius: BorderRadius.circular(30), )), onChanged: (value) { password = value; }, )), SizedBox( height: 25, ), Material( color: Colors.lightGreenAccent, borderRadius: BorderRadius.circular(20), elevation: 15, child: MaterialButton( minWidth: 250, child: Text( "Submit", style: TextStyle( fontSize: 25, fontStyle: FontStyle.italic, fontWeight: FontWeight.bold, color: Colors.deepOrange, ), ), onPressed: () async { try { // Remember to add .trim() function in EMail Address to get rid of the error of "Email Address Badly Formatted"! var user = await authenticate.createUserWithEmailAndPassword( email: email.trim(), password: password, ); print(email); print(password); //print(user); if (user.additionalUserInfo.isNewUser == true) { Navigator.pushNamed(context, "/chat"); } } catch (e) { print(e); } }, ), ), ], ), ), ), ), ), ); }
}
Code for the Login file:
import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/material.dart'; import 'package:modal_progress_hud/modal_progress_hud.dart'; class MyLogin extends StatefulWidget { @override _MyLoginState createState() => _MyLoginState(); } class _MyLoginState extends State<MyLogin> with SingleTickerProviderStateMixin { var animation; AnimationController _controller; @override void initState() { super.initState(); _controller = AnimationController( vsync: this, duration: Duration(seconds: 1), ); animation = CurvedAnimation(parent: _controller, curve: Curves.easeIn) ..addListener(() { setState(() { print(animation.value); }); }); print(animation); _controller.forward(); print(animation); } @override void dispose() { super.dispose(); _controller.dispose(); } var authentication = FirebaseAuth.instance; String email, password; bool showProgressSpinner = false; @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, home: Scaffold( appBar: AppBar( title: Text( "Login Page", style: TextStyle( fontSize: 25, fontStyle: FontStyle.italic, fontWeight: FontWeight.bold, ), ), ), body: ModalProgressHUD( inAsyncCall: showProgressSpinner, child: Center( child: Container( width: 300, child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ GestureDetector( onTap: () => _controller.forward(from: 0.0), child: Container( color: Colors.amber, width: MediaQuery.of(context).size.width * 0.9, height: MediaQuery.of(context).size.height * 0.05, child: Text( "Welcome to my Chat App", style: TextStyle( fontSize: 25, fontWeight: FontWeight.bold, fontStyle: FontStyle.italic, ), ), ), ), SizedBox( height: 55, ), Material( //color: Colors.pinkAccent[100], //borderRadius: BorderRadius.circular(20), //elevation: 15, child: TextField( // Assigning the Email Address Keyboard Type keyboardType: TextInputType.emailAddress, decoration: InputDecoration( prefixIcon: Icon(Icons.email), hintText: "Enter Email ID", border: OutlineInputBorder( borderRadius: BorderRadius.circular(30), )), onChanged: (value) { email = value; }, )), SizedBox( height: 25, ), Material( //color: Colors.pinkAccent[100], //borderRadius: BorderRadius.circular(20), //elevation: 15, child: TextField( // Assigning the Email Address Keyboard Type keyboardType: TextInputType.multiline, obscureText: true, decoration: InputDecoration( prefixIcon: Icon(Icons.lock), hintText: "Password", border: OutlineInputBorder( borderRadius: BorderRadius.circular(30), )), onChanged: (value) { password = value; }, )), SizedBox( height: 25, ), Material( color: Colors.lightGreenAccent, borderRadius: BorderRadius.circular(20), elevation: 15, child: MaterialButton( minWidth: 250, child: Text( "Login", style: TextStyle( fontSize: 25, fontStyle: FontStyle.italic, fontWeight: FontWeight.bold, color: Colors.deepOrange, ), ), onPressed: () async { try { setState(() { showProgressSpinner = true; }); // Remember to add .trim() function in EMail Address to get rid of the error of "Email Address Badly Formatted"! var user = await authentication.signInWithEmailAndPassword( email: email.trim(), password: password, ); print(email); print(password); //print(user); if (user != null) { Navigator.pushNamed(context, "/streamingchat"); setState(() { showProgressSpinner = false; }); } else { setState(() { showProgressSpinner = false; }); } } catch (e) { print(e); } }, ), ), SizedBox( height: 25, ), Material( color: Colors.lightGreenAccent, borderRadius: BorderRadius.circular(20), elevation: 15, child: MaterialButton( minWidth: 250, child: Text( "Create an Account?", style: TextStyle( fontSize: 25, fontStyle: FontStyle.italic, fontWeight: FontWeight.bold, color: Colors.deepOrange, ), ), onPressed: () => Navigator.pushNamed(context, "/"), ), ), ], ), ), ), ), ), ); }
}
Code for the Streaming Chat file:
import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/material.dart'; class StreamingChat extends StatefulWidget { @override _StreamingChatState createState() => _StreamingChatState(); } class _StreamingChatState extends State<StreamingChat> with SingleTickerProviderStateMixin { String message; var fs = FirebaseFirestore.instance; var authenticate = FirebaseAuth.instance; var messageTextContoller = TextEditingController(); var showProgressSpinner = false; var animation; AnimationController _controller; @override void initState() { super.initState(); _controller = AnimationController( vsync: this, duration: Duration(seconds: 1), ); animation = CurvedAnimation(parent: _controller, curve: Curves.easeIn) ..addListener(() { setState(() { print(animation.value); }); }); print(animation); _controller.forward(); print(animation); } @override void dispose() { super.dispose(); _controller.dispose(); } @override Widget build(BuildContext context) { var mobileWidth = MediaQuery.of(context).size.width; var mobileHeight = MediaQuery.of(context).size.height; var user = authenticate.currentUser.email; return Scaffold( appBar: AppBar( title: Text( "Streaming Chat Page", style: TextStyle( fontSize: 25, fontStyle: FontStyle.italic, fontWeight: FontWeight.bold, ), ), ), body: Container( // For Container Alignment alignment: Alignment.center, child: Column( // For Column Widgets Alignment mainAxisAlignment: MainAxisAlignment.start, children: [ StreamBuilder<QuerySnapshot>( builder: (context, snapshot) { //print("Loading New Messgaes!"); if (snapshot.data == null) { return CircularProgressIndicator(); } var m = snapshot.data.docs; List<Widget> z = []; for (var doc in m) { z.add( Text( "${doc.data()['Sender']} : ${doc.data()['Message']}", ), ); } // Using LitsView to show the messages Properly! return Container( height: mobileHeight * 0.3, width: mobileWidth * 0.9, child: ListView.builder( scrollDirection: Axis.vertical, itemCount: z.length, itemBuilder: (BuildContext context, int index) { return new ListTile( title: z[index], ); }), ); /*return Container( child: Column( children: z, ));*/ }, stream: fs.collection("chatMessages").snapshots(), ), SizedBox( height: 15, ), Container( width: mobileWidth * 0.95, child: TextField( onChanged: (value) { message = value; }, controller: messageTextContoller, decoration: InputDecoration( hintText: "Enter the Message Here", border: OutlineInputBorder( borderRadius: BorderRadius.circular(25), )), ), ), SizedBox( height: 25, ), GestureDetector( onDoubleTap: () { _controller.forward(from: 0.0); }, child: Container( child: RaisedButton( color: Colors.lightGreenAccent, child: Text( "Send Message", style: TextStyle( fontWeight: FontWeight.bold, fontSize: 20, fontStyle: FontStyle.italic, color: Colors.red, ), ), onPressed: () async { messageTextContoller.clear(); await fs.collection("chatMessages").add({ "Message": message, "Sender": user, }); }, ), ), ), SizedBox( height: 5, ), GestureDetector( onTap: () => _controller.forward(from: 0.0), child: RaisedButton( color: Colors.lightGreenAccent, child: Text( "LogOut", style: TextStyle( fontWeight: FontWeight.bold, fontSize: 20, fontStyle: FontStyle.italic, color: Colors.red, ), ), onPressed: () async { await authenticate.signOut(); Navigator.pushNamed(context, "/"); }, ), ), ], ), ), ); }
}
This is all the code for the application to develop, to check out the complete project, please visit my GitHub repo by clicking here.