Google search engine
Home Blog Page 46

Hooks In Flutter

0

Welcome to one of the best ways of managing UI logic, forget all about stateful widgets and the amount of unreadability as you pile hundreds of functions into initState() or call setState() hundred times.
So, that brings us to a question of what hooks are exactly?

Hooks came from React Native, if you want to learn more about them

https://reactjs.org/docs/hooks-intro.html

With them in react you could use state features without writing a class, So what do they do in flutter then?


well, their main use is for readability and clear the clutter in your state classes, they use something called HOOKWIDGET, now with stateful widgets, you can only have one state but with Hookwidget you can have multiple hooks attached to one HookWidget each containing its own logic.

Hooks are kept inside a List and are managed on their own so you don’t need to initialize them or dispose of them(well not the prebuilt ones anyway)

There are prebuilt Hooks and Custom hooks that we can use.To get a better understanding of Hooks lets just jump into code

Without using a HookWidget :

import 'package:flutter/animation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';

void main()=>runApp(MaterialApp(
title: "Hooks",
home: Home(),
debugShowCheckedModeBanner: false,
));

class Home extends StatefulWidget {
@override
_HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> with SingleTickerProviderStateMixin{
AnimationController animationController;
Animation<double> animation;


@override
void initState() {
super.initState();
animationController = AnimationController(vsync: this,duration: Duration(milliseconds: 1000),value: 1)..addListener(() {
if(animationController.status == AnimationStatus.completed) {
animationController.repeat();
}
setState(() {

});
});
}

@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
color: Colors.blueGrey,
child: GestureDetector(
child: FadeTransition(opacity: animationController,child: Center(child: FlutterLogo(size: 300,))),
onTap: animationController.forward,
onDoubleTap: animationController.reverse,
),
),
);
}

@override
void dispose() {
super.dispose();
animationController.dispose();
}
}

we are simply trying to Fade the flutter logo when the user taps on Screen, just create an animation controller and an Animation and call _animationController.forward(), to make it run.

Now the equivalent of this in Hooks would be

import 'package:flutter/animation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';

void main()=>runApp(MaterialApp(
title: "Hooks",
home: Home(),
debugShowCheckedModeBanner: false,
));



class Home extends HookWidget {
@override
Widget build(BuildContext context) {
final hookAnimation = useAnimationController(duration: kThemeAnimationDuration, initialValue: 1);

return Scaffold(
body: GestureDetector(
onTap: () {
hookAnimation.forward();
},
onDoubleTap: () {
hookAnimation.reverse();
},
child: Container(
color: Colors.blueGrey,
child: Center(child: FadeTransition(opacity: hookAnimation,child: ScaleTransition(scale: hookAnimation,child: FlutterLogo(colors: Colors.blue,size: 500,)))),

),
),
);
}
}

see the lack of initState(), or even the dispose()?

So why is it that we need to declare them in stateful widget yet we can freely use useAnimationController() in the HookWidget?

Well, the answer to that question is simple, in HookWidget all the different hooks we create like the useAnimationController they are managed by Hook that is to say that their intialization and dispose is taken care of and we don’t need to get our hands dirty by writing them on our own:

Suppose if I had to create 2 TextEditingControllers in this project as well I would’ve had to dispose them and then the dispose method would’ve been cluttered, now imagine this for a project on a huge scale where multiple people are working on it, imagine you had to put so many functions in the initState or call setState so many times that it takes a while just to read and understand the code and then make changes to a particular part of the program, there is a chance you may even break something trying to fix something else which would consume even more time.

So that is why Hooks are the perfect solution provided to us so that we do not run into this particular problem. Another benefit of using hooks is re-usability, after creating your custom hook you can reuse it as much as you would like.

NOTE: Always create the hooks in build method.

CREATING CUSTOM HOOKS

let’s say you want the animation you just created to show up when you scroll the page?

Simple right you will just create a scroll controller and in initState just define it to do that, but what if you had to do the same thing on like 5 or 6 different screens? nobody would write the same stuff 5–6 times just for it to work, that’s where hook comes in and saves your day. Lemme show you how :

How would you do that in normal Stateful Widget?

class Home extends StatefulWidget {
@override
_HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> with SingleTickerProviderStateMixin{
AnimationController animationController;
Animation<double> animation;
ScrollController scroller;


@override
void initState() {
super.initState();

animationController = AnimationController(vsync: this,duration: Duration(milliseconds: 1000),value: 1);
scroller = ScrollController()..addListener(
() {
if(scroller.position.userScrollDirection ==ScrollDirection.forward) {
animationController.forward();
}
else if(scroller.position.userScrollDirection ==ScrollDirection.reverse) {
animationController.reverse();
}
else {
print("not scrolloing");
}
}
);
}

@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
color: Colors.blueGrey,
child: ListView(
controller: scroller,
children: List.generate(20, (index) {
return Container(
margin: EdgeInsets.all(10),
decoration: BoxDecoration(
border: Border.all(
color: Colors.white,
width: 10
)
),
child: GestureDetector(
child: FadeTransition(opacity: animationController,child: Center(child: FlutterLogo(size: 300,))),
onTap: animationController.forward,
onDoubleTap: animationController.reverse,
),
);
}),
)
),
);
}

@override
void dispose() {
super.dispose();
animationController.dispose();
scroller.dispose();
}


}

So, I have made a simple example of when you scroll the animation plays, and when you scroll in reverse direction the animation also plays in reverse, its simple code but if you have no practice with ScrollController then you might wanna check out :

ScrollController class
Controls a scrollable widget. Scroll controllers are typically stored as member variables in State objects and are…api.flutter.dev

Alright now that you are familiar with ScrollController class we can focus on how to get this done with the help of a CustomHook

While it may sound difficult thing to do its really not,

so i have created another file called customScroll where i have created a class called HookScroll which extends Hook<ScrollController>, now just like in a normal stateful class you need to create an createState().

TIP : Just create a normal stateful class in your project then modify it with the code i m about to paste, will save a lot of time

Now create a _HookScrollState which will HookState which will have 2 generics one of ScrollController and the other of the class it will be the state of HookScroll , So it will go like this

class _HookScrollerState extends HookState<ScrollController,HookScroller> {

Now we will create a normal ScrollController instance, and in initState for a hook called the initHook we will define it

@override
void initHook() {
// TODO: implement initHook
super.initHook();
scroller = ScrollController()..addListener((){
scrollAnimation(hook.controller, scroller);
});
}

the scrollAnimation is a function defined by me but you can just create it inside scrollController’s addListener i just like to keep my functions seperate, here is the code for it

void scrollAnimation(AnimationController controler, ScrollController scrollController) {
if(scrollController.position.userScrollDirection == ScrollDirection.forward) {
controler.forward();
}
else if(scrollController.position.userScrollDirection == ScrollDirection.reverse){
controler.reverse();
}
else {
print("not scrolling rn");
}
}

now after making an initHook just like an initState we are going to need a dispose for the scroll controller

@override
void dispose() {
// TODO: implement dispose
super.dispose();
scroller.dispose();
}

Alright, now we can wire it up so that HookScroll takes an animation controller value which we can access by hook.controller

class HookScroller extends Hook<ScrollController> {
AnimationController controller;
HookScroller(this.controller);
  @override
_HookScrollerState createState() => _HookScrollerState();
}

Now after all that we need a build method so that it can all work together so for that just paste the below code

@override
ScrollController build(BuildContext context) {
return scroller;
}

Body is of type ScrollerController meaning it returns the scroller that we created so that

in the end it would look like this

class HookScroller extends Hook<ScrollController> {
AnimationController controller;
HookScroller(this.controller);
@override
_HookScrollerState createState() => _HookScrollerState();
}

class _HookScrollerState extends HookState<ScrollController,HookScroller> {
ScrollController scroller;

void scrollAnimation(AnimationController controler, ScrollController scrollController) {
if(scrollController.position.userScrollDirection == ScrollDirection.forward) {
controler.forward();
}
else if(scrollController.position.userScrollDirection == ScrollDirection.reverse){
controler.reverse();
}
else {
print("not scrolling rn");
}
}

@override
void initHook() {
// TODO: implement initHook
super.initHook();
scroller = ScrollController()..addListener((){
scrollAnimation(hook.controller, scroller);
});
}

@override
ScrollController build(BuildContext context) {
return scroller;
}

@override
void dispose() {
// TODO: implement dispose
super.dispose();
scroller.dispose();
}
}

With this we can make a scroll work, just one little problem tho if you try to make an instance of it, It will give you an error, why is that?

Well when you call a HookWidget inside a class that extends Hook,it does that by calling Hook.use, so to fix this you can click on useAnimationController() method we created while holding ctrl button on the keyboard to visit this function, as you can see how that function returns a Hook.use with _AnimationControllerHook, so we have do perform the same with our custom Hook.

To do this outside of the classes of our HookScroller and _HookScrollState create a method that will return a ScrollController which will need the value of an animation controller called controller

ScrollController scrollController(AnimationController controller) {
return Hook.use(HookScroller(controller));
}

After creating this the final would customScroll file would look like this :

import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_hooks/flutter_hooks.dart';


class HookScroller extends Hook<ScrollController> {
AnimationController controller;
HookScroller(this.controller);
@override
_HookScrollerState createState() => _HookScrollerState();
}

class _HookScrollerState extends HookState<ScrollController,HookScroller> {
ScrollController scroller;

void scrollAnimation(AnimationController controler, ScrollController scrollController) {
if(scrollController.position.userScrollDirection == ScrollDirection.forward) {
controler.forward();
}
else if(scrollController.position.userScrollDirection == ScrollDirection.reverse){
controler.reverse();
}
else {
print("not scrolling rn");
}
}

@override
void initHook() {
// TODO: implement initHook
super.initHook();
scroller = ScrollController()..addListener((){
scrollAnimation(hook.controller, scroller);
});
}

@override
ScrollController build(BuildContext context) {
return scroller;
}

@override
void dispose() {
// TODO: implement dispose
super.dispose();
scroller.dispose();
}
}

ScrollController scrollController(AnimationController controller) {
return Hook.use(HookScroller(controller));
}

Finally, we can wire it all up together by calling the method we just created in our Home class

class Home extends HookWidget {
@override
Widget build(BuildContext context) {
final hookAnimation = useAnimationController(duration: Duration(milliseconds: 500), initialValue: 0);
final hookScroll = scrollController(hookAnimation);

return Scaffold(
body: GestureDetector(
onTap: () {
hookAnimation.reverse();
},
onDoubleTap: () {
hookAnimation.forward();
},
child: Container(
color: Colors.blueGrey,
child: ListView(
controller: hookScroll,
children: List.generate(20, (index) {
return Container(margin: EdgeInsets.all(20),decoration: BoxDecoration(
border: Border.all(
color: Colors.white,
width: 2,
style: BorderStyle.solid
)
),child: Center(child: FadeTransition(opacity: hookAnimation,child: ScaleTransition(scale: hookAnimation,child: FlutterLogo(colors: Colors.blue,size: 500,)))));
})
)

),
),
);
}

}

See the highlighted above and do the same in your code, or you can copy-paste it, I leave that decision up to you
With this, we are done. now we can have it play our animation every time we scroll

If you wanna say that this is too much boilerplate code compared to what we had in StatefulWidget…. well, I agree, if I just have to make it for one screen alone then I won’t make a hook for it and just work with a stateful widget, but if I have to use that animation in like 3–4 screens nothing would be better than a CustomHook.

If you are facing any problem implementing Hook, contact me i will try to help to the best of my ability

You can find the full code and more amazing stuff at :

flutter-devs/flutter_hooks_demo
Contribute to flutter-devs/flutter_hooks_demo development by creating an account on GitHub.github.com


From Our Parent Company Aeologic

Aeologic Technologies is a leading AI-driven digital transformation company in India, helping businesses unlock growth with AI automation, IoT solutions, and custom web & mobile app development. We also specialize in AIDC solutions and technical manpower augmentation, offering end-to-end support from strategy and design to deployment and optimization.

Trusted across industries like manufacturing, healthcare, logistics, BFSI, and smart cities, Aeologic combines innovation with deep industry expertise to deliver future-ready solutions.

Feel free to connect with us:
And read more articles from FlutterDevs.com

FlutterDevs team of Flutter developers to build high-quality and functionally-rich apps. Hire flutter developer for your cross-platform Flutter mobile app project on an hourly or full-time basis as per your requirement! You can connect with us on Facebook, GitHub, Twitter, and LinkedIn for any flutter related queries.

We welcome feedback and hope that you share what you’re working on using #FlutterDevs. We truly enjoy seeing how you use Flutter to build beautiful, interactive web experiences.

www.flutterdevs.com

Authentication Error Handling in Flutter

0

Introduction

In this blog, we shall discuss about handing authentication exception. When the user signs in or signup he might get some error but if we do not handle those errors the user will not be able to know about the authentication failure. So it is very important to handle those errors and display a message or alert so that the user can change his credentials as per the requirement of the error.


Table of contents:

Validating TextField

Handle platform exception.

Handle Firebase Auth exceptions

Complete auth module


Validating TextField

Email TextField

TextFormField(
key: ValueKey('email'),
autocorrect: false,
textCapitalization: TextCapitalization.none,
enableSuggestions: false,
validator: (value) {
if (value.isEmpty || !value.contains('@')) {
return 'Please enter a valid email address.';
}
return null;
},
keyboardType: TextInputType.emailAddress,
)

: TextFormField provides us validator property to show an error if the email is empty or it does not contain @. You can add as many error messages you want using nested if-else.

Password TextField

TextFormField(
key: ValueKey('password'),
validator: (value) {
if (value.isEmpty || value.length < 7) {
return 'Password must be at least 7 characters long.';
}
return null;
},
obscureText: hidePassword,

)

Handle Platform exception

This handle the error of different platforms such as android and ios

try {
if (isLogin) {
userCredential = await _auth.signInWithEmailAndPassword(
email: email,
password: password,
);
} else if (password == confirmPassword) {
userCredential = await _auth.createUserWithEmailAndPassword(
email: email,
password: password,
);
} else {}
} on PlatformException catch (err) {
authProblems errorType;
if (Platform.isAndroid) {
switch (e.message) {
case 'There is no user record corresponding to this identifier. The user may have been deleted.':
errorType = authProblems.UserNotFound;
break;
case 'The password is invalid or the user does not have a password.':
errorType = authProblems.PasswordNotValid;
break;
case 'A network error (such as timeout, interrupted connection or unreachable host) has occurred.':
errorType = authProblems.NetworkError;
break;
default:
print('Case ${e.message} is not yet implemented');
}
} else if (Platform.isIOS) {
switch (e.code) {
case 'Error 17011':
errorType = authProblems.UserNotFound;
break;
case 'Error 17009':
errorType = authProblems.PasswordNotValid;
break;
case 'Error 17020':
errorType = authProblems.NetworkError;
break;
// ...
default:
print('Case ${e.message} is not yet implemented');
}
}
Scaffold.of(ctx).showSnackBar(
SnackBar(
content: Text($errorType),
backgroundColor: Theme.of(ctx).errorColor,
),
);
}

Handling both platform error using a single code

var errorMessage;
final _auth = FirebaseAuth.instance;

try {
if (isLogin) {
userCredential = await _auth.signInWithEmailAndPassword(
email: email,
password: password,
);
} else if (password == confirmPassword) {
userCredential = await _auth.createUserWithEmailAndPassword(
email: email,
password: password,
);
}

} on PlatformException catch (err) {
var message = 'An error occurred, please check your credentials!';

if (err.message != null) {
message = err.message;
setState(() {
errorMessage = message;
});
print(message);
}
Scaffold.of(ctx).showSnackBar(
SnackBar(
content: Text(message),
backgroundColor: Theme.of(ctx).errorColor,
),
);
}

Here we are directly displaying the error message using a snack bar. If the error message is null then ‘An error occurred, please check your credentials!’ message will be displayed. If an error message is not null then message = err.message; .

Handle Firebase Auth exceptions

catch (error) {
print(error);
setState(() {
errorMessage = error.toString();
});
Scaffold.of(ctx).showSnackBar(
SnackBar(
content: Text(errorMessage),
backgroundColor: Colors.red,
),
);
}

While logging in user can get the following error :

  • [firebase_auth/wrong-password] The password is invalid or the user does not have a password.
  • [firebase_auth/invalid-email] The email address is badly formatted.
  • [firebase_auth/user-not-found] There is no user record corresponding to this identifier. The user may have been deleted.

While Signing up user can get the following error:

  • [firebase_auth/email-already-in-use] The email address is already in use by another account.
  • [firebase_auth/invalid-email] The email address is badly formatted.
  • [firebase_auth/weak-password] Password should be at least 6 characters.
Types of error

Complete auth module (Ready to use)

Complete Dart Code File for Auth Form :

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_vector_icons/flutter_vector_icons.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:laundary_application/widgets/userImagePicker.dart';

class AuthForm extends StatefulWidget {
AuthForm(
this.submitFn,
this.isLoading,
);

final bool isLoading;
final void Function(
String email,
String password,
String confirmPassword,
String userName,
File image,
bool isLogin,
BuildContext ctx,
) submitFn;

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

class _AuthFormState extends State<AuthForm> {
final _formKey = GlobalKey<FormState>();
var _isLogin = true;
var _userEmail = '';
var _userName = '';
var _userPassword = '';
var _confirmPassword = '';
File _userImageFile;
bool hidePassword = true;

void _pickedImage(File image) {
_userImageFile = image;
}

void _trySubmit() {
final isValid = _formKey.currentState.validate();
FocusScope.of(context).unfocus();

if (_userImageFile == null && !_isLogin) {
Scaffold.of(context).showSnackBar(
SnackBar(
content: Text('Please pick an image.'),
backgroundColor: Theme.of(context).errorColor,
),
);
return;
}

if (isValid) {
_formKey.currentState.save();
widget.submitFn(
_userEmail.trim(),
_userPassword.trim(),
_confirmPassword.trim(),
_userName.trim(),
_userImageFile,
_isLogin,
context,
);
}
}

@override
Widget build(BuildContext context) {
double width = MediaQuery.of(context).size.width;
double height = MediaQuery.of(context).size.height;
return Center(
child: SingleChildScrollView(
child: Padding(
padding: EdgeInsets.all(16),
child: Form(
key: _formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
!_isLogin
? SizedBox(
height: 0,
)
: Image.asset(
"assets/appIcon.png",
height: height * 0.2,
),
if (!_isLogin) UserImagePicker(_pickedImage, widget.isLoading),
Container(
width: width,
height: 50,
decoration: BoxDecoration(
border: Border.all(
color: Colors.grey.withOpacity(0.5),
width: 1,
),
borderRadius: BorderRadius.circular(5),
),
child: TextFormField(
key: ValueKey('email'),
autocorrect: false,
textCapitalization: TextCapitalization.none,
enableSuggestions: false,
validator: (value) {
if (value.isEmpty || !value.contains('@')) {
return 'Please enter a valid email address.';
}
return null;
},
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
hintText: 'Email address',
prefixIcon: Icon(Entypo.mail),
border: InputBorder.none),
onSaved: (value) {
_userEmail = value;
},
),
),
SizedBox(height: 12),
if (!_isLogin)
Container(
width: width,
height: 50,
decoration: BoxDecoration(
border: Border.all(
color: Colors.grey.withOpacity(0.5),
width: 1,
),
borderRadius: BorderRadius.circular(5),
),
child: TextFormField(
key: ValueKey('username'),
autocorrect: true,
textCapitalization: TextCapitalization.words,
enableSuggestions: false,
validator: (value) {
if (value.isEmpty || value.length < 4) {
return 'Please enter at least 4 characters';
}
return null;
},
decoration: InputDecoration(
hintText: 'Username',
prefixIcon: Icon(Icons.edit),
border: InputBorder.none,
),
onSaved: (value) {
_userName = value;
},
),
),
SizedBox(height: 12),
Container(
width: width,
height: 50,
decoration: BoxDecoration(
border: Border.all(
color: Colors.grey.withOpacity(0.5),
width: 1,
),
borderRadius: BorderRadius.circular(5),
),
child: TextFormField(
key: ValueKey('password'),
validator: (value) {
if (value.isEmpty || value.length < 7) {
return 'Password must be at least 7 characters long.';
}
return null;
},
decoration: InputDecoration(
suffixIcon: IconButton(
icon: Icon(
hidePassword ? Entypo.eye_with_line : Entypo.eye),
onPressed: () {
setState(() {
hidePassword = !hidePassword;
});
},
),
hintText: 'Password',
border: InputBorder.none,
prefixIcon: Icon(
Icons.vpn_key,
)),
obscureText: hidePassword,
onSaved: (value) {
_userPassword = value;
},
),
),
SizedBox(height: 12),
if (!_isLogin)
Container(
width: width,
height: 50,
decoration: BoxDecoration(
border: Border.all(
color: Colors.grey.withOpacity(0.5),
width: 1,
),
borderRadius: BorderRadius.circular(5),
),
child: TextFormField(
key: ValueKey('password'),
validator: (value) {
if (value.isEmpty || value.length < 7) {
return 'Password must be at least 7 characters long.';
}
return null;
},
decoration: InputDecoration(
hintText: 'Confirm Password',
border: InputBorder.none,
prefixIcon: Icon(
Icons.vpn_key,
)),
obscureText: hidePassword,
onSaved: (value) {
_confirmPassword = value;
},
),
),
SizedBox(height: 12),
widget.isLoading
? CircularProgressIndicator()
: InkWell(
onTap: _trySubmit,
child: Container(
height: 50,
decoration: BoxDecoration(
color: Colors.pinkAccent.withOpacity(0.8),
borderRadius: BorderRadius.circular(5),
),
width: width,
child: Center(
child: Text(
_isLogin ? 'Login' : 'Sign Up',
style: GoogleFonts.lato(
color: Colors.white,
fontSize: 20,
fontWeight: FontWeight.w900,
),
)),
),
),
if (!widget.isLoading)
FlatButton(
child: RichText(
text: TextSpan(children: [
TextSpan(
text: _isLogin
? "Don't have an account? "
: "Already have an account?",
style: GoogleFonts.lato(
color: Colors.black54,
)),
TextSpan(
text: _isLogin ? "Sign Up" : "Log In",
style: GoogleFonts.lato(
color: Colors.red,
fontWeight: FontWeight.w900,
)),
]),
),
onPressed: () {
setState(() {
_isLogin = !_isLogin;
});
},
),
Image.asset(
"assets/demo1.png",
height: height * 0.26,
),
],
),
),
),
),
);
}
}

Let us Have a look at the authentication dart file :

import 'dart:io';

import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/services.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_storage/firebase_storage.dart';
import 'package:laundary_application/widgets/authForm.dart';

class AuthScreen extends StatefulWidget {
@override
_AuthScreenState createState() => _AuthScreenState();
}

class _AuthScreenState extends State<AuthScreen> {
final _auth = FirebaseAuth.instance;
var _isLoading = false;
var errorMessage;

void _submitAuthForm(
String email,
String password,
String confirmPassword,
String username,
File image,
bool isLogin,
BuildContext ctx,
) async {
UserCredential userCredential;

try {
setState(() {
_isLoading = true;
});
if (isLogin) {
userCredential = await _auth.signInWithEmailAndPassword(
email: email,
password: password,
);
} else if (password == confirmPassword) {
userCredential = await _auth.createUserWithEmailAndPassword(
email: email,
password: password,
);

final ref = FirebaseStorage.instance
.ref()
.child('user_image')
.child(userCredential.user.uid + '.jpg');

await ref.putFile(image).onComplete;

final url = await ref.getDownloadURL();

await FirebaseFirestore.instance
.collection('users')
.doc(userCredential.user.uid)
.set({
'username': username,
'email': email,
'image_url': url,
});
} else {
setState(() {
_isLoading = false;
errorMessage = "password does not match";
Scaffold.of(ctx).showSnackBar(
SnackBar(
content: Text(errorMessage),
backgroundColor: Colors.red,
),
);
});
}
} on PlatformException catch (err) {
var message = 'An error occurred, please check your credentials!';

if (err.message != null) {
message = err.message;
setState(() {
errorMessage = message;
});
print(message);
}
Scaffold.of(ctx).showSnackBar(
SnackBar(
content: Text(message),
backgroundColor: Theme.of(ctx).errorColor,
),
);
setState(() {
_isLoading = false;
});
} catch (error) {
print(error);
setState(() {
errorMessage = error.toString();
});
Scaffold.of(ctx).showSnackBar(
SnackBar(
content: Text(errorMessage),
backgroundColor: Colors.red,
),
);
setState(() {
_isLoading = false;
});
}
}

@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: AuthForm(
_submitAuthForm,
_isLoading,
),
),
);
}
}

If you find anything that could be improved please let me know, I would love to improve.💙

If this article has helped you a bit and found interesting please clap!👏


From Our Parent Company Aeologic

Aeologic Technologies is a leading AI-driven digital transformation company in India, helping businesses unlock growth with AI automation, IoT solutions, and custom web & mobile app development. We also specialize in AIDC solutions and technical manpower augmentation, offering end-to-end support from strategy and design to deployment and optimization.

Trusted across industries like manufacturing, healthcare, logistics, BFSI, and smart cities, Aeologic combines innovation with deep industry expertise to deliver future-ready solutions.

Feel free to connect with us:
And read more articles from FlutterDevs.com

FlutterDevs team of Flutter developers to build high-quality and functionally-rich apps. Hire flutter developer for your cross-platform Flutter mobile app project on an hourly or full-time basis as per your requirement! You can connect with us on Facebook, GitHub, Twitter, and LinkedIn for any flutter related queries.

We welcome feedback and hope that you share what you’re working on using #FlutterDevs. We truly enjoy seeing how you use Flutter to build beautiful, interactive web experiences!.


Explore ValueListenableBuilder in Flutter

0

Introduction

In this blog, we shall explore how to use the ValueListenableBuilder widget. It is an amazing widget. It builds the widget every time the valueListenable value changes. Its values remain synced with there listeners i.e. whenever the values change the ValueListenable listen to it. It updates the UI without using setState() or any other state management technique.


Properties:

  1. valueListenable:
  2. builder:
  3. child:

These are the three properties of ValueListenableBuilder. bulder build widget depending upon the valueListenable value. valueListenable is an instance of ValueNotifier . child property is optional, it can be null if valueListenable value entirely depends upon the builder widget.

Example:

  • Creating a AppValueNotifier class.
class AppValueNotifiier{}
  • ValueNotifier
class AppValueNotifiier{
ValueNotifier valueNotifier = ValueNotifier(0);
}
  • Creating an increment function
class AppValueNotifier{
ValueNotifier valueNotifier = ValueNotifier(0);
  void incrementNotifier() {
valueNotifier.value++;
}
}
  • Creating an object of AppValueNotifier
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  AppValueNotifier appValueNotifier = AppValueNotifier();

@override
Widget build(BuildContext context) {
return Container();
}
}
  • Initializing ValueListenableBuilder
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
AppValueNotifier appValueNotifier = AppValueNotifier();

@override
Widget build(BuildContext context) {
return ValueListenableBuilder(
valueListenable: appValueNotifier.valueNotifier,
builder: (context, value, child) {
return Text(value.toString());
},
);
}
}
  • Using increment function
Scaffold(
body: ValueListenableBuilder(
valueListenable: appValueNotifier.valueNotifier,
builder: (context, value, child) {
return Text(value.toString());
},
),
floatingActionButton: FloatingActionButton(
onPressed: () {
appValueNotifier.incrementNotifier();
},
),
);

Using multiple ValueListenableBuilder, listening more than one value:

  • To use multiple ValueListenableBuilder , we will create the following ValueNotifier:
ValueNotifier incrementValueNotifier = ValueNotifier(10);
ValueNotifier decrementValueNotifier = ValueNotifier(0);
ValueNotifier colorValueNotifier = ValueNotifier(false);
ValueNotifier subtractValueNotifier = ValueNotifier(0);
  • Creating multiple function to perform various action:
void decrementNotifier() {
decrementValueNotifier.value = decrementValueNotifier.value - 3;
}

void colorNotifier() {
colorValueNotifier.value = !colorValueNotifier.value;
}

void operation() {
subtractValueNotifier.value =
incrementValueNotifier.value + decrementValueNotifier.value;
}

void incrementNotifier() {
incrementValueNotifier.value++;
}

We have created two valueNotifier for increment and decrement, one for color, and one for subtraction operation. We will change the color of the container, the increment and decrement counters, and the substation of both the counters.

  • Nested ValueListenableBuilder
ValueListenableBuilder(
valueListenable: appValueNotifier.incrementValueNotifier,
builder: (context, increment, _) => ValueListenableBuilder(
valueListenable: appValueNotifier.decrementValueNotifier,
builder: (context, decrement, _) => ValueListenableBuilder(
valueListenable: appValueNotifier.colorValueNotifier,
builder: (context, color, _) => ValueListenableBuilder(
valueListenable:
appValueNotifier.subtractValueNotifier,
builder: (context, subtract, _) => Container(
width: 100,
height: 30,
color: color ? Colors.red : Colors.orangeAccent,
child: Center(
child:
Text("$increment $decrement = $subtract"),
)))))))
  • Changing floatingActionButton
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
appValueNotifier.incrementNotifier();
appValueNotifier.decrementNotifier();
appValueNotifier.colorNotifier();
appValueNotifier.operation();
}),
  • disposing all value notifier

We must dispose valueNotifier as ValueNotifier is a disposable value. Also, prevent app memory loss.

@override
void dispose() {
appValueNotifier.subtractValueNotifier.dispose();
appValueNotifier.incrementValueNotifier.dispose();
appValueNotifier.decrementValueNotifier.dispose();
appValueNotifier.colorValueNotifier.dispose();
super.dispose();
}

Better real app example to use ValueListenableBuilder:

Building a Secured Flutter Application
Learn to Disable Screen Capturing & Video Recording And Enabling Fingerprint Authentication every timemedium.com


Thanks for reading this article ❤

If I got something wrong? Let me know in the comments. I would love to improve.

Clap 👏 If this article helps you.

If we got something wrong? Let me know in the comments. we would love to improve.


From Our Parent Company Aeologic

Aeologic Technologies is a leading AI-driven digital transformation company in India, helping businesses unlock growth with AI automation, IoT solutions, and custom web & mobile app development. We also specialize in AIDC solutions and technical manpower augmentation, offering end-to-end support from strategy and design to deployment and optimization.

Trusted across industries like manufacturing, healthcare, logistics, BFSI, and smart cities, Aeologic combines innovation with deep industry expertise to deliver future-ready solutions.

FlutterDevs team of Flutter developers to build high-quality and functionally-rich apps. Hire flutter developer for your cross-platform Flutter mobile app project on an hourly or full-time basis as per your requirement! You can connect with us on Facebook, GitHub, Twitter, and LinkedIn for any flutter related queries.

We welcome feedback and hope that you share what you’re working on using #FlutterDevs. We truly enjoy seeing how you use Flutter to build beautiful, interactive web experiences!.

Collections in Dart

0

Introduction

Dart supports four types of collection with full-featured API. List, Set, Queue, Map are the four types of collection in Dart programming language. List, Set, Queue are iterable while Maps are not. Iterable collections can be changed i.e. their items can be modified, add, remove, can be accessed sequentially. The map doesn’t extend iterable.


Iterable

Iterable is an extract class, it can’t de instantiate directly.

An Iterable of string and int

void main() {
Iterable<int> var1 = [1,2,3,4];
Iterable<String> var2 = ['a','b','c','d'];
}

The difference with List and Iterable is that that element in the list can be accessed with their index value using [] operator while in Iterable value can’t be accessed using [] operator.

void main() {
Iterable<int> var1 = [1,2,3,4];
Iterable<String> var2 = ['a','b','c','d'];
print(var1[1]);
}

If we run the above program. We get the operator error.

Error compiling to JavaScript:
main.dart:4:13:
Error: The operator '[]' isn't defined for the class 'Iterable<int>'.
- 'Iterable' is from 'dart:core'.
print(var1[1]);
^
Error: Compilation failed.

Correct program:

void main() {
Iterable<int> var1 = [1,2,3,4];
Iterable<String> var2 = ['a','b','c','d'];
print(var1.elementAt(1));
}

Output: 2

Using for loop to print element of iterable

void main() {
Iterable<int> var1 = [1, 2, 3, 4];
for (var element in var1) {
print(element);
}
}

Performing few operations:

void main() {
Iterable<int> var1 = [1, 2, 3, 4];
print(var1.first);
print(var1.last);
print(var1.length);
print(var1.contains(1));
print(var1.skip(1));
print(var1.single);

}

OutPut:

1
4
4
true
(2, 3, 4)
Uncaught Error: Bad state: Too many elements

firstreturn the first element, last return the last element, length return the length of iterable, contains(1) return the element at position 1, skip(1) skip the element at position 1, single return the element if iterable has only one element. Throw this error if it has more than one element or empty Uncaught Error: Bad state: Too many elements .

List

A list is an array of elements arranged in an ordered sequence.

There are two types of List:

  1. Fixed-Length List
  2. Growable List

Fixed-Length List is a list that can’t be changed once initialized whereas the Growable list is dynamic in nature.

Fixed-length List

  • Creating a Fixed-length List
void main() {
List<String> list = List(5);
}

The indexing value start with 0 and end with listOfLength-1 . So for the list index values will be 0 to 4 .

  • Here the list is empty, so let’s assign the value for each index:
void main() {
List<String> list = List(5);
list[0] = 'a';
list[1] = 'b';
list[2] = 'c';
list[3] = 'd';
list[4] = 'e';
}
  • Printing the values:
print(list[1]);
  • Updating the value:
void main() {
List<String> list = List(5);
list[0] = 'a';
list[1] = 'b';
list[2] = 'c';
list[3] = 'd';
list[4] = 'e';
list[0] = 'm';
print(list[0]);
}

Output:m .

Growable List

  • Growable List example:
void main() {
List<String> list = List();
}
  • Inserting elements in List:
void main() {
List<String> list = List();
list.add('a');
list.add('b');
list.add('c');
}
  • Updating element:
void main() {
List<String> list = List();
list.add('a');
list.add('b');
list.add('c');
list[1]= 'm';
}

Set

A set is an unordered collection of values. We can’t get the values by their index values as they are unordered. Values in set are unique i.e. they can’t be repeated.

  • Creating a Set using a constructor:
void main() {
Set<int> set = Set();
}
  • Creating a Set using List
void main() {
List<int> list = [1, 2, 3, 4];
Set<int> set = Set.from(list);
}
  • Inserting elements in Set
void main() {
List<int> list = [1, 2, 3, 4];
Set<int> set = Set.from(list);
set.add(5);
set.add(6);
}

Maps

Maps is an unordered pair of key and values. The keys of the map must unique, values can be the same. Map is also called dictionary or hash .The size of a map is not fixed, we can add, delete edit the values of the map. The size of the map depends upon the number of elements in the map. The values in the map can only be accessed through the key name, not by the index values.

  • Creating a map using constructor:
void main() {
Map<String, int> map = Map();
}

Here we have created a map named map whose key type is String and value type is int .

  • Adding a value and printing the map:
void main() {
Map<String, int> map = Map();
map['number'] = 1;
print(map);
}

Output:{number: 1}

Accessing value by its key : print(map[‘number’]); .

Printing all keys and values of the map:

void main() {
Map<String, int> map = Map();
map['number1'] = 1;
map['number2'] = 2;
map['number3'] = 3;
for (String keys in map.keys) {
print(keys);
}
for (int values in map.values) {
print(values);
}
}

Output:

number1
number2
number3
1
2
3

Printing Key-Value pair:

map.forEach((key, value) {
print("$key:$value");
});

OutPut:

number1:1
number2:2
number3:3

Thanks for reading this article ❤

If I got something wrong? Let me know in the comments. I would love to improve.

Clap 👏 If this article helps you.

If we got something wrong? Let me know in the comments. we would love to improve.


From Our Parent Company Aeologic

Aeologic Technologies is a leading AI-driven digital transformation company in India, helping businesses unlock growth with AI automation, IoT solutions, and custom web & mobile app development. We also specialize in AIDC solutions and technical manpower augmentation, offering end-to-end support from strategy and design to deployment and optimization.

Trusted across industries like manufacturing, healthcare, logistics, BFSI, and smart cities, Aeologic combines innovation with deep industry expertise to deliver future-ready solutions.

FlutterDevs team of Flutter developers to build high-quality and functionally-rich apps. Hire flutter developer for your cross-platform Flutter mobile app project on an hourly or full-time basis as per your requirement! You can connect with us on Facebook, GitHub, Twitter, and LinkedIn for any flutter related queries.

We welcome feedback and hope that you share what you’re working on using #FlutterDevs. We truly enjoy seeing how you use Flutter to build beautiful, interactive web experiences!.

Important Dart Concepts In Flutter

0

In this blog, we shall learn about various Null-aware operators, where to use const keyword, async, and await. Dart is a powerful language that provides us, various special operators, keyword. Operators are the special characters that are used to perform various operations on the operants. There are four null-aware operators that are used to handle the null values. const keyword is used to reduce the rebuild of const object every time.


Null- aware Operators

Operators that deals with values that might be null during runtime are called Null-aware Operators.

  • ?. operator

This operator is used when you call a method on an object if that object is not null.

Eg. If we have a String value , we want to return null if it is null and if not then value.toLowerCase() , then we can use value?.toLowerCase() .

It is equivalent to value ==null?null:value.toLowerCase() .

  • ??= operators

It is called a null-aware assignment.

void main() {
String string;
//if (string == null) string = 'Hi!';
string ??= 'Hi!';
print(string);
}
  • ?? operators : It is a null operator.
void main() {
String string = "Hi!";
print(string ?? string??2);
}

Output: Hi!

void main() {
String string;
print(string ?? string??2);
}

Output: 2

In the first program, the output is Hi! while in the second program the output is 2 . As we can see in the first program the value of the string is not null that is why it has returned the left part of the statement string ?? string??2 . While in the second program string is null hence it has returned the right part of the statement i.e. 2

  • … operator

This operator is amazing. It adds a list that is not null with the other list of the same type.

void main() {
List<int> list = [1,2,3];
List<int> list1 = [4,5,6];
List<int> finalList = [0,...list,...list1];
print(finalList);
}

Output:[0, 1, 2, 3, 4, 5, 6] .

Use of const keyword

const keyword in dart is highly effective to use as

  • It increases the performance of our app.
  • Reduce CPU load.
  • Allocate only one memory space.

Using const keyword while construction an objectconst Text("Hi!"), while creating a collection const [3,4,2,5] .

If we use const like this, it will work absolutely fine.

void main() {
const int value = 2;
const int _value = 3;
const int result = value + _value;
print(result);
}

But if we use const DateTime.now() , this will not work as it changes and it needs to be rebuilt every time the user opens the app. We will get the following error.

The constructor being called isn’t a const constructor. Try removing ‘const’ from the constructor invocation.

  • : A const constructor can’t be assigned for a class.
  • : If you repeat the const object in the same class it will reuse the same object created for the first time.
  • : The const objects are frozen and completely Immutable.
  • : Const variables are implicitly final i.e. Compile-time constant.

What is async and await ?

These two keywords are highly useful for updating our UI while processing our data. Example if we use authentication in our app then while signing up, signing in, logout there is a small-time delay while performing these operation, so it would be nice if we can display a loading spinner while these operation gets executed.

For this purpose, we can use async and await keyword in our authentication code and we can build our logic for displaying our logic.

While creating a function for authentication make that function asynchronous by using the async keywordauth()async{} . await is used to show up the Circular Progress Indicator until the Code Execution is Completed.

auth()async{
//set the loading spinner state var signIn = await authentication();
//reset the state of loading spinner
}

Thanks for reading this article ❤

If I got something wrong? Let me know in the comments. I would love to improve.

Clap 👏 If this article helps you.

If we got something wrong? Let me know in the comments. we would love to improve.


From Our Parent Company Aeologic

Aeologic Technologies is a leading AI-driven digital transformation company in India, helping businesses unlock growth with AI automation, IoT solutions, and custom web & mobile app development. We also specialize in AIDC solutions and technical manpower augmentation, offering end-to-end support from strategy and design to deployment and optimization.

Trusted across industries like manufacturing, healthcare, logistics, BFSI, and smart cities, Aeologic combines innovation with deep industry expertise to deliver future-ready solutions.

FlutterDevs team of Flutter developers to build high-quality and functionally-rich apps. Hire flutter developer for your cross-platform Flutter mobile app project on an hourly or full-time basis as per your requirement! You can connect with us on Facebook, GitHub, Twitter, and LinkedIn for any flutter related queries.

We welcome feedback and hope that you share what you’re working on using #FlutterDevs. We truly enjoy seeing how you use Flutter to build beautiful, interactive web experiences!.

Introduction to Animation in Flutter

0

Introduction To Topic :

Implementing animation into your app might be the best idea to make your app more smooth, polished, slick, and nice. In flutter using animation is quite simple.

In general, flutter provides us two types of animation — Tween animation and Physics-based animation. Tween animation is used if we want to animate a widget with a fixed start and finish. While Physics-based animation relies on the user interaction.


Table of content :

Tweens

Animation curves

Ticker Providers

AnimationController


Tweens

Tween is an object that takes a start value and an end value. Value can be anything like color, opacity. We can use Tween to change the color of appBar from blue to pink or any other colors. The change in color is handled by the Animation library. The Tween value lies between 0.0 to 1.0.

Tween( begin: 0.0, end: 1.0, );

Animation curves

Animation curves are used to define to flow rate of animation. It fixes the path of animation, allows the animation to speed up or slow down at a specific point. Flutter provides us Curves class. The default curve is linear. Curves class is packed with a variety of curves path eg. easeIn, elasticIn etc.

Ticker Providers

Ticker can be used by the object that needs to be notified every time the frame changes triggers. TickerProviderclass provides a ticker for the widget.

Using TickerProvider :

class MyAnimation extends StatefulWidget {
@override
_MyAnimationState createState() => _MyAnimationState();
}
class _MyAnimationState extends State<MyAnimation>
with TickerProviderStateMixin {
@override
Widget build(BuildContext context) {
return Container();
}
}

AnimationController

By the name, we can understand that it’s a controller that controls the animation. This object has so many properties. The object must be initialised inside the initState() of the class.

class MyAnimation extends StatefulWidget {
@override
_MyAnimationState createState() => _MyAnimationState();
}
class _MyAnimationState extends State<MyAnimation>
with TickerProviderStateMixin {
AnimationController _animationController;

@override
void initState() {
_animation = AnimationController(
vsync: this,
duration: Duration(
seconds: 1,
),
);
super.initState();
}
@override
Widget build(BuildContext context) {
return Container();
}
}

Creating a color animation:

class MyAnimation extends StatefulWidget {
@override
_MyAnimationState createState() => _MyAnimationState();
}
class _MyAnimationState extends State<MyAnimation>
with TickerProviderStateMixin {
AnimationController _animationController;
Animation _animation;
@override
void initState() {
_animationController = AnimationController(
vsync: this,
duration: Duration(
seconds: 1,
),
);
_animation = ColorTween(begin: Colors.deepOrangeAccent, end: Colors.green)
.animate(_animationController);
    _animationController.forward();
super.initState();
}
@override
Widget build(BuildContext context) {
return Container(
height: 50,
color: _animation.value,
); }
}

This is an example to create your first animation. Here I have just used all the above topics. So let me summarize the whole scenario.The first step is to add TickerProviderStateMixin to the state class of StatefulWidget. Then create a AnimationController that we will use to perform various actions with the animation. Then you need to initialize a AnimationController object that is use to pass the current class context and duration and any more. To pass the Tween create a Animation and pass ColorTween object (inside the initState() method) that takes the start and end color that we need to change while animating the container colors. Then add animate() ,this allows Tweens to be chained before obtaining an Animation. Now forward that AnimationController , so that it can get started with animation _animationController.forward(); .

Adding curve in animation:

CurveAnimation() creates a curved animation. It takes a parent, curve arguments. parent takes a AnimationController and curve takes a Curve .

_animation = ColorTween(begin: Colors.red, end: Colors.green)
.animate(CurvedAnimation(
parent: _animationController,
curve: Curves.bounceIn,
));

Now you are ready to go to implement animation into your apps. Thanks…


Thanks for reading this article ❤

If I got something wrong? Let me know in the comments. I would love to improve.

Clap 👏 If this article helps you.

If we got something wrong? Let me know in the comments. we would love to improve.


From Our Parent Company Aeologic

Aeologic Technologies is a leading AI-driven digital transformation company in India, helping businesses unlock growth with AI automation, IoT solutions, and custom web & mobile app development. We also specialize in AIDC solutions and technical manpower augmentation, offering end-to-end support from strategy and design to deployment and optimization.

Trusted across industries like manufacturing, healthcare, logistics, BFSI, and smart cities, Aeologic combines innovation with deep industry expertise to deliver future-ready solutions.

FlutterDevs team of Flutter developers to build high-quality and functionally-rich apps. Hire flutter developer for your cross-platform Flutter mobile app project on an hourly or full-time basis as per your requirement! You can connect with us on Facebook, GitHub, Twitter, and LinkedIn for any flutter related queries.

We welcome feedback and hope that you share what you’re working on using #FlutterDevs. We truly enjoy seeing how you use Flutter to build beautiful, interactive web experiences!.

Headless CMS In Flutter

0

HI, everyone I am glad to be back with another topic, this time i will be covering Headless CMS with flutter.

So, What is Headless CMS, or rather lets start from what is CMS itself.

CMS stands for Content Management System. It helps by controlling what content to be shown to user, content mostly is managed by people who don’t have much knowledge about the code, so for them it might look like just a basic form where they put in data, the data get stored in Database and then our app extracts that data from Database and displays to user. It is useful because all the content can be managed separately and would not need to be coded in manually, so that even for a smallest change you won’t have to waste time to search where you put in that particular string and then change it.


Now, coming to Headless CMS

The “Headless” is the new approach towards CMS whereas in the traditional CMS it was mostly coupled with a web page but, this new approach helps to widen that horizon and makes it so that content can be displayed on any device of users choice.

The devices are called “Heads” and since there are many devices so that means there is not a single fixed head.

This approach is better and an overall improvement over traditional CMS.

The way it works is that it provides us an API for all of our data and if we like we can use that directly in our project to show changes to user, Hence why this approach is better than traditional CMS

What will we be using for this short demo?

For this short demo on Headless CMS approach we will be using StoryBlok.

Storyblok – Headless CMS: Organize your content for the world
Storyblok helps your team to tell your story and manage content for every use-case: corporate websites, e-commerce…www.storyblok.com

It provides you an API with all your data you have entered into it.

I won’t go into too much detail over this -but all you need to do is create your own space and then define schema and then publish that in the content and go to settings to generate your token and then get the API.

That’s basically it!

Now to get onto the coding part!

How to handle API ?

There are multiple ways of handling an API call in flutter, but the simplest would be to use the http package from pub.dev, just paste that in the pubspec.yaml file.

http: any

That’s all you needed to do. Now to use this package we will import it as below

import 'package:http/http.dart' as http;

We have added as “http” there so that we can use its functions with ease,

Now to make an API call we can do that by making a separate function called _fetch() and make it asynchronous.

_fetch() async {

}

Now inside that function we need to make a variable that will help us get the response from the API so we will call that response.

Its type would be of http.Response, its always better to define the types,

and to give this variable value, It will have the value of http.get(“ <YOUR API HERE>”);.

Be sure to put in await before that so that we can wait for it to get the response from the API

_fetch() async {
final http.Response response = await http.get("https://api.storyblok.com/v1/cdn/stories?page=1&token=5kNqPrD6wYQRHakzUrxrGwtt");
}

Now once we are done with the API call and have gotten the response we need to check if that response was correct or not and we do that by accessing a property of http.Response type variables that is statusCode

We make a simple check that if the statusCode was 200 then no error occurred and we got the response we desired.

if(response.statusCode ==200) {

// YOUR FUNCTION BODY HERE
}

for now once we get the API response and the statusCode is 200 lets decode it.

For that we will use an inbuilt method called jsonDecode(<YOUR RESPONSE VARIABLE>)

final Map<String,dynamic> json = jsonDecode(response.body);

We have accessed the body of the response we got and have gotten that body part into a json variable which is of type Map<String,dynamic>.

now we can just print the json and get all the data we require, to use the data we can use it like we use any other map

However i recommend making a Modal class for dealing with this, an example would be

class Fetch {
final name;
final created;
final published;
final alternates;
final id;
final uuid;
final content;
final slug;
final full_slug;
final default_full_slug;
final sort_by_date;
final position;
final tag_list;
final isStartPage;
final parent_id;
final meta_data;
final release_id;
final lang;
final path;
final translated_slugs;

Fetch({this.name, this.created, this.published, this.alternates, this.id,
this.uuid, this.content, this.slug, this.full_slug,
this.default_full_slug, this.sort_by_date, this.position, this.tag_list,
this.isStartPage, this.parent_id, this.meta_data, this.release_id,
this.lang, this.path, this.translated_slugs});

factory Fetch.fromFetch( map) {
return Fetch(
name: map["name"],
created: map["created_at"],
published: map["published_at"],
alternates: map["alternates"],
id: map["id"],
uuid: map["uuid"],
content: map["content"],
slug: map["slug"],
full_slug: map["full_slug"],
default_full_slug: map["default_full_slug"],
sort_by_date: map["sort_by_date"],
position: map["position"],
tag_list: map["tag_list"],
isStartPage: map["is_startpage"],
parent_id: map["parent_id"],
meta_data: map["meta_data"],
release_id: map["release_id"],
lang: map["lang"],
path: map["path"],
translated_slugs: map["translated_slugs"]
);
}


}

So we have defined all the keys in the map as a variable here and we are gonna make an object of this Modal class and use that object to show what we want from the json data.

If you want more help making a Modal class you can contact me anytime you like

Now how we provide data from json to it?

Its beyond simple really i usually do it like this

List list = json['stories'];
print(list);
list.map((i) {
Fetch fetch = Fetch.fromFetch(i);
print(fetch.id);
print("fetch name => ${fetch.name}");
}).toList();

Well in my json ‘stories’ was a key which had a List as its value so i made this so i can get the data of all list items into my modal class and print them,

You can declare another List of type Fetch and add in it the fetch instance so that you can use it whenever you like,

Example

List<Fetch> fetchList =[];
List list = json['stories'];
print(list);
list.map((i) {
Fetch fetch = Fetch.fromFetch(i);
fetchList.add(fetch);

}).toList();

Now this makes our work much, much easier. Instead of writing the key in strings over and over again we can simply use it like fetchList[0].name or fetchList[0].id etc.

Now all that is left is to either bind it to a button or if you want to run it at app startup then call the function in initState();

As always you can find the full code for this in the GitHub. Hope you guys enjoyed reading through this, If you have any queries be sure to let me know, and i will try to solve them.


From Our Parent Company Aeologic

Aeologic Technologies is a leading AI-driven digital transformation company in India, helping businesses unlock growth with AI automation, IoT solutions, and custom web & mobile app development. We also specialize in AIDC solutions and technical manpower augmentation, offering end-to-end support from strategy and design to deployment and optimization.

Trusted across industries like manufacturing, healthcare, logistics, BFSI, and smart cities, Aeologic combines innovation with deep industry expertise to deliver future-ready solutions.

Feel free to connect with us:
And read more articles from FlutterDevs.com.

FlutterDevs team of Flutter developers to build high-quality and functionally-rich apps. Hire flutter developer for your cross-platform Flutter mobile app project on an hourly or full-time basis as per your requirement! You can connect with us on Facebook, GitHub, Twitter, and LinkedIn for any flutter related queries.

We welcome feedback and hope that you share what you’re working on using #FlutterDevs. We truly enjoy seeing how you use Flutter to build beautiful, interactive web experiences.

Auth using AWS Amplify In Flutter

0

Authorization and Authentication in your apps plays an important role and we’re very well aware of the fact in day-to-day acitivities. Motsly every app that we install needs you to authenticate yourself before you could use it and same goes for authorization. In Flutter we have been doing this using Firebase

What’s AWS Amplify ?

AWS Amplify is a set of tools and services that enables mobile and front-end web developers to build secure, scalable full stack applications, powered by AWS. With Amplify, it’s easy to create custom onboarding flows, develop voice-enabled experiences, build AI-powered real-time feeds, launch targeted campaigns, and more. No matter the use case, AWS Amplify helps you develop and release great apps your customers will love. AWS Amplify includes an open-source framework with use-case centric libraries and a powerful toolchain to create and add cloud-based features to your app, and a web hosting service to deploy static web applications.

Pre-requisites:

npm install -g @aws-amplify/cli@flutter-preview

Note: If you don’t have nodejs and npm already installed, please use install Npm and NodeJs beforehand. Also,an already existing install of @aws-amplify/cli wont work, you may need to install flutter-preview version.

  • You need to sign up for an AWS account if you don’t already have it.

Integrate Amplify into your app:

Now, here for this demo, I’m going to use the Auth flow of the app using AWS which generally I use to do using Firebase before so I’m assuming that you have the demo UI for the Sign-Up and Sign-In flow ready as I won’t be going to the UI part here.

  • Import Amplify packages into your project inside the pubspec.yaml file:
amplify_core:  latest version 
amplify_auth_cognito: latest version
  • Fetch the Amplify packages entered above using the below command:
flutter pub get
  • To make sure you have installed the proper amplify cli version run the below command:
amplify --version

Note: The output of this command should have “-flutter-preview” appended to it. If not, then run “npm install -g @aws-amplify/cli@flutter-preview” in the terminal.

  • Now that you have the correct version of amplify installed, it’s time to connect to the AWS cloud and for that, we need to initialize the amplify, use the following command to initialize the Amplify:
amplify init
  • The next step is to configure the user for AWS. This will help create a new user or set an already created user for this project. Use the following command to configure AWS:
amplify configure
AWS User creation process

What is AWS Cognito?

Amazon Cognito lets you add user sign-up, sign-in, and access control to your web and mobile apps quickly and easily. Amazon Cognito scales to millions of users and supports sign-in with social identity providers, such as Facebook, Google, and Amazon, and enterprise identity providers via SAML 2.0.

This will help set up social sign-in, user authentication which we are going to integrate into our demo. The AWS amplify category has a default, built-in support for the AWS Cognito.

Prerequisites:

  • A Flutter application with Flutter SDK ≥1.20 and Amplify libraries integrated as mentioned above.

Configurations:

To start using the auth resources into your project run the following command into the terminal

amplify add auth
  • You’ll be prompted with few questions to configure the auth preferences just go with the defaults,
? Do you want to use the default authentication and security configuration? `Default configuration` 
? How do you want users to be able to sign in? `Username`
? Do you want to configure advanced settings? `No, I am done.`
  • After the auth configuration has been set you need to push all these changes made till now to the cloud and for that, you can use the below command,
amplify push 

Auth using Amplify:

Now that the basic setup has been done and if everything did go well then you can proceed ahead with the Auth flow integration into your UI for registration and sign-in .

For SignUp:

Just like you use to handle Firbase Auth flow in the signup screen, just need to implement AWS api calls.

try {
Map<String, dynamic> userAttributes = {
"email": emailController.text,
"phone_number": phoneController.text,
// additional attributes as needed
};
SignUpResult res = await Amplify.Auth.signUp(
username: "myusername",
password: "mysupersecurepassword",
options: CognitoSignUpOptions(
userAttributes: userAttributes
));
} on AuthError
catch (e) {
print(e);
}

Now, the user will be confirmed. For that, a confirmation code will be sent to the email address by the user. You need to create a separate UI for the confirmation code as the user have to enter the code received in his/her email and will passed to the confirmSignUp call.

try {
SignUpResult res = await Amplify.Auth.confirmSignUp(
username: "myusername",
confirmationCode: "123456"
);
} on AuthError catch (e) {
print(e);
}

Upon the successful completion of signup flow you can see Confirm signUp Succeded message on the terminal.

For SignIn:

In the SignIn UI, imlement the AWS signIn api calls.

try {
SignInResult res = await Amplify.Auth.signIn(
username: usernameController.text.trim(),
password: passwordController.text.trim(),
);
} on AuthError catch (e) {
print(e);
}

Upon the successful completion of signin flow you can see Sign in Succeded message on the terminal.


From Our Parent Company Aeologic

Aeologic Technologies is a leading AI-driven digital transformation company in India, helping businesses unlock growth with AI automation, IoT solutions, and custom web & mobile app development. We also specialize in AIDC solutions and technical manpower augmentation, offering end-to-end support from strategy and design to deployment and optimization.

Trusted across industries like manufacturing, healthcare, logistics, BFSI, and smart cities, Aeologic combines innovation with deep industry expertise to deliver future-ready solutions.

Feel free to connect with us
And read more articles from FlutterDevs.com

FlutterDevs team of Flutter developers to build high-quality and functionally-rich apps. Hire flutter developer for your cross-platform Flutter mobile app project on an hourly or full-time basis as per your requirement! You can connect with us on Facebook, GitHub, and Twitter for any flutter related queries.

Custom Progress Indicator In Flutter

In this article, we will explore the Custom Progress Indicator in a flutter Using the liquid progress indicator package. With the help of the package, we can easily achieve flutter animated liquid wave progress indicators.

We will implement a demo of the Custom Progress Indicator that can be easily embedded in your flutter applications.


Table Of Contents :

Custom Progress Indicator

Implementation

Code Implement

Code File

Conclusion


Custom Progress Indicator :

A Custom liquid progress indicator is what we’ll actually use to draw our animated liquid wave progress bar. Liquid Custom Progress Indicator sub-classes need to implement the liquid progress bar Custom Progress Indicator .with the help of custom indicator, we can give custom shape to our progress bar.

Demo Module :

Implementation :

Step 1: Add dependencies.

Add dependencies to pubspec — yaml file.

dependencies:
liquid_progress_indicator: ^0.3.2

Step 2: import the package :

import 'package:liquid_progress_indicator/liquid_progress_indicator.dart';

Step 3: Run flutter package get

Code Implement :

Create a new dart file is called custom_progress_indicator.dart inside the lib folder

In this screen,First of all,We have set the percentage timer in the init state which will increase the timer when the progress bar in running them in your Application.

@override
void initState() {
Timer timer;
timer = Timer.periodic(Duration(milliseconds:300),(_){
print('Percent Update');
setState(() {
percent+=1;
if(percent >= 100){
timer.cancel();
// percent=0;
}
});
});
super.initState();
}

Now we will initialize the LiquidCircularProgressIndicator which is a progress bar show in liquid form.

LiquidCircularProgressIndicator(
value:percent/100, // Defaults to 0.5.
valueColor: AlwaysStoppedAnimation(Colors.pink),
backgroundColor: Colors.white,
borderColor: Colors.red,
borderWidth:4.0,
direction: Axis.vertical,
center:Text(percent.toString() +"%",style: TextStyle(fontSize:12.0,fontWeight: FontWeight.w600,color: Colors.black),),
),

Now we will initialize the LiquidLinearProgressIndicator which is a progress bar show in liquid form.

LiquidLinearProgressIndicator(
value:percent/100,
valueColor: AlwaysStoppedAnimation(Colors.pink),
backgroundColor: Colors.white,
borderColor: Colors.red,
borderWidth: 5.0,
borderRadius: 12.0,
direction: Axis.horizontal,
center:Text(percent.toString() +"%",style: TextStyle(fontSize:12.0,fontWeight: FontWeight.w600,color: Colors.black),),

),

Creating Our Custom Shaped Indicator :

LiquidCustomProgressIndicator(
value:percent/100,
valueColor: AlwaysStoppedAnimation(Colors.cyan),
backgroundColor: Colors.grey[100],
Colors.black),),
direction: Axis.vertical,
shapePath:_buildBoatPath(),
),

Code File :

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:liquid_progress_indicator/liquid_progress_indicator.dart';
import 'dart:math' as math;

class CustomProgressIndicator extends StatefulWidget {
@override
_CustomProgressIndicatorState createState() =>
_CustomProgressIndicatorState();
}

class _CustomProgressIndicatorState extends State<CustomProgressIndicator> {
double _height;
double _width;

double percent = 0.0;

@override
void initState() {
Timer timer;
timer = Timer.periodic(Duration(milliseconds: 300), (_) {
print('Percent Update');
setState(() {
percent += 1;
if (percent >= 100) {
timer.cancel();
// percent=0;
}
});
});
super.initState();
}

@override
Widget build(BuildContext context) {
_height = MediaQuery.of(context).size.height;
_width = MediaQuery.of(context).size.width;

return Scaffold(
appBar: AppBar(
title: Text(
"Liquid Progress Bar",
style: TextStyle(color: Colors.black),
),
backgroundColor: Colors.white,
centerTitle: true,
),
body: Container(
height: _height,
width: _width,
padding: EdgeInsets.all(20),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Column(
children: [
Text(
'Liquid Circular Progress Indicator',
style: TextStyle(
fontStyle: FontStyle.italic,
fontWeight: FontWeight.w700,
fontSize: 15),
),
SizedBox(
height: 40,
),
Container(
height: 130,
width: 130,
child: LiquidCircularProgressIndicator(
value: percent / 100,
// Defaults to 0.5.
valueColor: AlwaysStoppedAnimation(Colors.pink),
backgroundColor: Colors.white,
borderColor: Colors.red,
borderWidth: 4.0,
direction: Axis.vertical,
center: Text(
percent.toString() + "%",
style: TextStyle(
fontSize: 12.0,
fontWeight: FontWeight.w600,
color: Colors.black),
),
),
),
],
),
Column(
children: [
Text(
'Liquid linear progress indicator',
style: TextStyle(
fontStyle: FontStyle.italic,
fontWeight: FontWeight.w700,
fontSize: 15),
),
SizedBox(
height: 40,
),
Container(
height: 40,
child: LiquidLinearProgressIndicator(
value: percent / 100,
valueColor: AlwaysStoppedAnimation(Colors.pink),
backgroundColor: Colors.white,
borderColor: Colors.red,
borderWidth: 5.0,
borderRadius: 12.0,
direction: Axis.horizontal,
center: Text(
percent.toString() + "%",
style: TextStyle(
fontSize: 12.0,
fontWeight: FontWeight.w600,
color: Colors.black),
),
),
),
],
),
Column(
children: [
Text(
'Liquid custom progress indicator.',
style: TextStyle(
fontStyle: FontStyle.italic,
fontWeight: FontWeight.w700,
fontSize: 15),
),
Container(
child: LiquidCustomProgressIndicator(
value: percent / 100,
valueColor: AlwaysStoppedAnimation(Colors.cyan),
backgroundColor: Colors.grey[100],
direction: Axis.vertical,
shapePath: _buildBoatPath(),
),
),
],
),
],
),
),
);
}

Path _buildBoatPath() {
return Path()
..moveTo(15, 120)
..lineTo(0, 85)
..lineTo(50, 85)
..lineTo(60, 80)
..lineTo(60, 85)
..lineTo(120, 85)
..lineTo(105, 120) //and back to the origin, could not be necessary #1
..close();
}
}

Conclusion :

In this article, I have explained a Custom Progress Indicator demo, you can modify and experiment according to your own, this little introduction was from the date time picker from our side.

I hope this blog helps will provide you with sufficient information in Trying up the Custom Progress Indicator in your flutter project. In this demo explain the liquid progress bar through the liquid_progress_indicator package in a flutter. So please try it.

❤ ❤ Thanks for reading this article ❤❤


If I got something wrong? Let me know in the comments. I would love to improve.

Clap 👏 If this article helps you.


From Our Parent Company Aeologic

Aeologic Technologies is a leading AI-driven digital transformation company in India, helping businesses unlock growth with AI automation, IoT solutions, and custom web & mobile app development. We also specialize in AIDC solutions and technical manpower augmentation, offering end-to-end support from strategy and design to deployment and optimization.

Trusted across industries like manufacturing, healthcare, logistics, BFSI, and smart cities, Aeologic combines innovation with deep industry expertise to deliver future-ready solutions.

Feel free to connect with us
And read more articles from FlutterDevs.com

FlutterDevs team of Flutter developers to build high-quality and functionally-rich apps. Hire flutter developer for your cross-platform Flutter mobile app project on an hourly or full-time basis as per your requirement! You can connect with us on Facebook, GitHub, Twitter, and LinkedIn for any flutter related queries.

Implement Showcase In Flutter

An extraordinary application UI limits the friction between user and application usefulness. A method for decreasing that grating is to feature and showcase the parts of your application. This is useful when a user launches your application interestingly. With the assistance of the Showcase and ShowCaseWidget widget, we can showcase the feature in the Flutter application.

This article will explore the Implement Showcase In Flutter. We will see how to implement a demo program. It will show a highlight of our app using the showcaseview package in your flutter applications.

showcaseview | Flutter Package
A Flutter package allows you to Showcase/Highlight your widgets step by step. Add dependency to pubspec.yaml Get the…pub.dev


Table Of Contents::

Introduction

Constructor

Parameters

Implementation

Code Implement

Code File

Conclusion



Introduction:

The showcase will feature the fundamental features of our application. At the point when the user taps on the screen, the widgets we have as a component of the feature will be introduced in a predefined request.

Demo Module::

This demo video shows how to implement the Showcase in a flutter and shows how a Showcase will work using the showcaseview package in your flutter applications. We will show a user press on the screen, then the showcase will be presented and When you run the app, the showcase will start instantly on the main page. It will be shown on your device.

Constructor:

To utilize Showcase, you need to call the constructor underneath:

const Showcase({
required this.key,
required this.child,
this.title,
required this.description,
this.shapeBorder,
this.overlayColor = Colors.black45,
this.overlayOpacity = 0.75,
this.titleTextStyle,
this.descTextStyle,
this.showcaseBackgroundColor = Colors.white,
this.textColor = Colors.black,
this.scrollLoadingWidget = const CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation(Colors.white)),
this.showArrow = true,
this.onTargetClick,
this.disposeOnTap,
this.animationDuration = const Duration(milliseconds: 2000),
this.disableAnimation,
this.contentPadding =
const EdgeInsets.symmetric(vertical: 8, horizontal: 8),
this.onToolTipClick,
this.overlayPadding = EdgeInsets.zero,
this.blurValue,
this.radius,
this.onTargetLongPress,
this.onTargetDoubleTap,
})

All fields marked with @required must not be empty in the above Constructor.

Parameters:

There are some parameters of Showcase are:

  • > key: This parameter is used to unique GlobalKey to identify features showcased.
  • > child: This parameter is used to the widget can only have one child. To layout multiple children, let this widget’s child be a widget such as Row, Column, or Stack, which have a children property, and then provide the children with that widget.
  • > description: This parameter displays a string about the showcased feature.
  • > animationDuration: This parameter is used for the duration over which to animate the parameters of this container. It represents a difference from one point in time to another.

Implementation:

Step 1: Add the dependencies

Add dependencies to pubspec — yaml file.

dependencies:
flutter:
sdk: flutter
showcaseview: ^1.1.6

Step 2: Add the assets

Add assets to pubspec — yaml file.

assets:
- assets/

Step 3: Import

import 'package:showcaseview/showcaseview.dart';

Step 4: Run flutter packages get in the root directory of your app.

How to implement code in dart file :

You need to implement it in your code respectively:

Create a new dart file called main.dart inside the lib folder.

Before we implement the showcase for individual widgets, we want to wrap our page that will show the showcase with a ShowCaseWidget. We should set the required builder parameter, which will contain the Builder widget returning our ShowcaseDemo.

@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter ShowCase Demo',
debugShowCheckedModeBanner: false,
home: Scaffold(
body: ShowCaseWidget(
builder: Builder(builder: (context) => const ShowcaseDemo()),
),
),
);
}

Presently, we will make a ShowcaseDemo class in the main. dart file. The ShowCaseWidget to know which widgets we need to be showcased, we want to make a key for all of those widgets. In our application, there are five widgets we need to bring to the consideration of our users when they arrive at the ShowcaseDemo.

final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
final GlobalKey _first = GlobalKey();
final GlobalKey _second = GlobalKey();
final GlobalKey _third = GlobalKey();
final GlobalKey _fourth = GlobalKey();
final GlobalKey _fifth = GlobalKey();

For the showcase to begin on page construct, we should call the startShowCase the strategy within the initState of the ShowcaseDemo.

Note, notwithstanding, that calling this technique simply the manner in which we did in the button would deliver an error. To keep this from occurring, we really want to put this strategy call inside a callback function and give it to WidgetsBinding.instance!.addPostFrameCallback(). This will guarantee that everything is executed accurately during the build.

Presently, if you run the application, our delightful showcase will begin when the page builds. Tap through it until the showcase is done.

@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback(
(_) => ShowCaseWidget.of(context)
.startShowCase([_first, _second, _third, _fourth, _fifth]),
);
}

In the build method, we will return Scaffold. We will add _scaffoldKey

@override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
......
)}

First Showcase will be added on AppBar. We will add a key, description, and its child. Its child, we will add IconButton. In this button, we will add onPressed and icon.

leading: Showcase(
key: _first,
description: 'Press here to open drawer',
child: IconButton(
onPressed: () {
_scaffoldKey.currentState!.openDrawer();
},
icon: const Icon(Icons.menu),
),
),

When we run the application, we ought to get the screen’s output like the underneath screen capture.

First Showcase Output

Then, Second Showcase we will add an app bar title with the key, description, and child. In a child, we will add the text “Flutter Showcase Demo”. In a description, we will add the string “This is a demo app title”.

title: Showcase(
key: _second,
description: 'This is a demo app title',
child: const Text('Flutter Showcase Demo')),

When we run the application, we ought to get the screen’s output like the underneath screen capture.

Second Showcase Output

Now, we will add a third Showcase on an action widget. In this widget, We will add a key was _third, the description was “Press to see notification” and, child.

actions: [
Showcase(
key: _third,
description: 'Press to see notification',
child: IconButton(
onPressed: () {},
icon: const Icon(Icons.notifications_active)))
],

When we run the application, we ought to get the screen’s output like the underneath screen capture.

Third Showcase Output

Next, we will add a fourth Showcase on a body part. In the body, we will add the Column widget. In this widget, we will add crossAxisAlignment and mainAxisAlignment as the center. Its child, we will add the Showcase method. In this method, we will add key was _fourth, the description was “FlutterDevs specializes in creating cost-effective and efficient applications”, and child. In a child, new will add an image.

Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Center(
child: Showcase(
key: _fourth,
description:
'FlutterDevs specializes in creating cost-effective and efficient applications',
child: Image.asset(
"assets/logo.png",
height: 400,
width: 350,
)),
),
],
),

When we run the application, we ought to get the screen’s output like the underneath screen capture.

Fourth Showcase Output

We will create a floatingActionButton equal to the Showcase widget. In this widget, we will add a key that was _fifth, the title was “Add Image’”, the description was “Click here to add new Image”.

floatingActionButton: Showcase(
key: _fifth,
title: 'Add Image',
description: 'Click here to add new Image',
shapeBorder: const CircleBorder(),
child: FloatingActionButton(
backgroundColor: Colors.cyan,
onPressed: () {},
child: const Icon(
Icons.image,
),
),
),

When we run the application, we ought to get the screen’s output like the underneath screen capture.

Fifth Showcase Output

Code File:

import 'package:flutter/material.dart';
import 'package:showcaseview/showcaseview.dart';

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

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

@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter ShowCase Demo',
debugShowCheckedModeBanner: false,
home: Scaffold(
body: ShowCaseWidget(
builder: Builder(builder: (context) => const ShowcaseDemo()),
),
),
);
}
}

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

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

class _ShowcaseDemoState extends State<ShowcaseDemo> {
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
final GlobalKey _first = GlobalKey();
final GlobalKey _second = GlobalKey();
final GlobalKey _third = GlobalKey();
final GlobalKey _fourth = GlobalKey();
final GlobalKey _fifth = GlobalKey();

@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback(
(_) => ShowCaseWidget.of(context)
.startShowCase([_first, _second, _third, _fourth, _fifth]),
);
}

@override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
drawer: Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: const <Widget>[
DrawerHeader(
decoration: BoxDecoration(
color: Colors.cyan,
),
child: Text(
'Drawer Header',
style: TextStyle(
color: Colors.white,
fontSize: 24,
),
),
),
ListTile(
leading: Icon(Icons.account_circle),
title: Text('Profile'),
),
ListTile(
leading: Icon(Icons.settings),
title: Text('Settings'),
),
],
),
),
appBar: AppBar(
leading: Showcase(
key: _first,
description: 'Press here to open drawer',
child: IconButton(
onPressed: () {
_scaffoldKey.currentState!.openDrawer();
},
icon: const Icon(Icons.menu),
),
),
actions: [
Showcase(
key: _third,
description: 'Press to see notification',
child: IconButton(
onPressed: () {},
icon: const Icon(Icons.notifications_active)))
],
title: Showcase(
key: _second,
description: 'This is a demo app title',
child: const Text('Flutter Showcase Demo')),
centerTitle: true,
automaticallyImplyLeading: false,
backgroundColor: Colors.cyan,
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Center(
child: Showcase(
key: _fourth,
description:
'FlutterDevs specializes in creating cost-effective and efficient applications',
child: Image.asset(
"assets/logo.png",
height: 400,
width: 350,
)),
),
],
),
floatingActionButton: Showcase(
key: _fifth,
title: 'Add Image',
description: 'Click here to add new Image',
shapeBorder: const CircleBorder(),
child: FloatingActionButton(
backgroundColor: Colors.cyan,
onPressed: () {},
child: const Icon(
Icons.image,
),
),
),
);
}
}

Conclusion:

In the article, I have explained the Showcase basic structure in a flutter; you can modify this code according to your choice. This was a small introduction to Showcase On User Interaction from my side, and it’s working using Flutter.

I hope this blog will provide you with sufficient information on Trying the Implementing Showcase in your flutter projectsWe will show you what the Introduction is. Make a demo program for working Showcase using the showcaseview package in your flutter applications. So please try it.

❤ ❤ Thanks for reading this article ❤❤

If I got something wrong? Let me know in the comments. I would love to improve.

Clap 👏 If this article helps you.


From Our Parent Company Aeologic

Aeologic Technologies is a leading AI-driven digital transformation company in India, helping businesses unlock growth with AI automation, IoT solutions, and custom web & mobile app development. We also specialize in AIDC solutions and technical manpower augmentation, offering end-to-end support from strategy and design to deployment and optimization.

Trusted across industries like manufacturing, healthcare, logistics, BFSI, and smart cities, Aeologic combines innovation with deep industry expertise to deliver future-ready solutions.

FlutterDevs team of Flutter developers to build high-quality and functionally-rich apps. Hire a flutter developer for your cross-platform Flutter mobile app project on an hourly or full-time basis as per your requirement! For any flutter-related queries, you can connect with us on Facebook, GitHub, Twitter, and LinkedIn.

We welcome feedback and hope that you share what you’re working on using #FlutterDevs. We truly enjoy seeing how you use Flutter to build beautiful, interactive web experiences.