flutter chat app with stream.io members page - flutter

i am using stream io for my flutter chat app and i have a couple of 'group' channels, meaning there's multiple users in the channel. i am having problems integrating a members page. does anybody knows how to use 'querying members' from https://getstream.io/chat/docs/flutter-dart/query_members/?language=dart#query-options ? any help will be greatly appreciated!
// ignore_for_file: deprecated_member_use
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:ibchat/helpers.dart';
import 'package:ibchat/screens/screens.dart';
import 'package:ibchat/themes/theme.dart';
import 'package:ibchat/widgets/widgets.dart';
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
import 'package:ibchat/stream/app.dart';
class CommunityProfileScreen extends StatefulWidget {
static Route routeWithChannel(Channel channel) => MaterialPageRoute(
builder: (context) => StreamChannel(
channel: channel,
child: const CommunityProfileScreen(),
));
const CommunityProfileScreen({Key? key}) : super(key: key);
#override
State<CommunityProfileScreen> createState() => _CommunityProfileScreenState();
}
class _CommunityProfileScreenState extends State<CommunityProfileScreen> {
final channelListController = ChannelListController();
final List<String> _areaOfInterest = [
'PersonalDevelopment',
'AcquiringNewSkills',
'Mentoring',
'Coaching',
'WealthManagement',
'InvestingOnPassiveIncome',
'BusinessDevelopment',
'BuildingANetwork',
'GrowingMyBusiness',
'PartnershipAndAlliances',
'RecruitmentOfTalents',
'Lifestyle',
'LuxuryExperiences',
'TheArtOfLiving'
];
#override
Widget build(BuildContext context) {
return ChannelListCore(
channelListController: channelListController,
filter: Filter.and([
Filter.and(
[
Filter.equal('type', 'messaging'),
Filter.in_('members', [
StreamChatCore.of(context).currentUser!.id,
]),
Filter.notIn('members', const ['influential-brands']),
],
),
Filter.nor([
Filter.equal('id', _areaOfInterest[0]),
Filter.equal('id', _areaOfInterest[1]),
Filter.equal('id', _areaOfInterest[2]),
Filter.equal('id', _areaOfInterest[3]),
Filter.equal('id', _areaOfInterest[4]),
Filter.equal('id', _areaOfInterest[5]),
Filter.equal('id', _areaOfInterest[6]),
Filter.equal('id', _areaOfInterest[7]),
Filter.equal('id', _areaOfInterest[8]),
Filter.equal('id', _areaOfInterest[9]),
Filter.equal('id', _areaOfInterest[10]),
Filter.equal('id', _areaOfInterest[11]),
Filter.equal('id', _areaOfInterest[12]),
Filter.equal('id', _areaOfInterest[13]),
]),
]),
sort: const [SortOption('name', direction: SortOption.DESC)],
emptyBuilder: (context) {
return Scaffold(
appBar: AppBar(
leadingWidth: 54,
leading: Align(
alignment: Alignment.centerRight,
child: IconBackground(
icon: CupertinoIcons.chevron_back,
onTap: () => Navigator.of(context).pop()),
),
title: const _AppBarTitle(),
),
body: const Center(
child: Text('No Other Members', textAlign: TextAlign.center),
),
);
},
errorBuilder: (context, error) => const DisplayErrorMessage(),
loadingBuilder: (
context,
) =>
const Center(
child: SizedBox(
height: 100,
width: 100,
child: CircularProgressIndicator(
color: AppColors.accent,
),
)),
listBuilder: (context, channels) {
return Scaffold(
appBar: AppBar(
leadingWidth: 54,
leading: Align(
alignment: Alignment.centerRight,
child: IconBackground(
icon: CupertinoIcons.chevron_back,
onTap: () => Navigator.of(context).pop()),
),
title: const _AppBarTitle(),
),
body: CustomScrollView(
slivers: [
SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) {
return _ProfileTile(
channel: channels[index],
);
},
childCount: channels.length,
),
)
],
),
);
},
);
}
}
class _ProfileTile extends StatelessWidget {
const _ProfileTile({Key? key, required this.channel}) : super(key: key);
final Channel channel;
#override
Widget build(BuildContext context) {
return InkWell(
onTap: () {
Navigator.of(context).push(ChatScreen.routeWithChannel(channel));
},
child: Container(
height: 100,
margin: const EdgeInsets.symmetric(horizontal: 8),
decoration: const BoxDecoration(
border: Border(bottom: BorderSide(color: Colors.grey, width: 0.2))),
child: Padding(
padding: const EdgeInsets.all(4.0),
child: Row(
children: [
Padding(
padding: const EdgeInsets.all(12.0),
child: Avatar.medium(
url: // needs help
),
),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: Text(
// needs help,
overflow: TextOverflow.ellipsis,
style: const TextStyle(
fontSize: 16,
letterSpacing: 0.2,
wordSpacing: 1.5,
fontWeight: FontWeight.w900)),
),
],
)),
],
),
),
),
);
}
}
class _AppBarTitle extends StatelessWidget {
const _AppBarTitle({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Row(
children: [
Expanded(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text('Members Of Community',
style: GoogleFonts.lato(
fontSize: 24,
fontWeight: FontWeight.bold,
color: Colors.black)),
const SizedBox(height: 2),
],
)),
const SizedBox(
width: 16,
),
Hero(
tag: 'community-profile-picture',
child: Padding(
padding: const EdgeInsets.only(bottom: 4),
child: Avatar.medium(
url: Helpers.randomPictureUrl(),
onTap: () => Navigator.of(context).pop()),
),
),
],
);
}
}

Related

News pages doesn't show article or blogs after building apk

I'm creating a flutter project on which it consist of news feature sadly after building an apk and installing it to try in become an empty screen with grey shade, i also try to test it on my phone and this is what happen i dont know where the bugs came from.. please help me
here's the code
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';
import 'Article_View.dart';
import 'News_Categories.dart';
import 'helper/Data.dart';
import 'helper/News.dart';
import 'model/Article_Model.dart';
import 'model/CategoryModel.dart';
class NewsHomePage extends StatefulWidget {
#override
_NewsHomePageState createState() => _NewsHomePageState();
}
class _NewsHomePageState extends State<NewsHomePage> {
List<CategoryModel> categories = <CategoryModel>[];
List<ArticleModel> articles = <ArticleModel>[];
bool _loading = true;
//bannerads
late BannerAd _bannerads;
bool _isAdsLoaded = false ;
#override
void initState() {
// TODO: implement initState
super.initState();
categories = getCategories();
getNews();
_initBannerAds();
}
getNews() async {
News newsClass = News();
await newsClass.getNews();
articles = newsClass.news;
setState(() {
_loading = false;
});
}
_initBannerAds(){
_bannerads = BannerAd(
size: AdSize.banner,
// ignore: deprecated_member_use
adUnitId: "ca-app-pub-8634651641429291/4830511818",
listener: BannerAdListener(
onAdLoaded: (ad){
setState(() {
_isAdsLoaded =true;
});
},
onAdFailedToLoad: (ad,error){}
),
request: const AdRequest()
);
_bannerads.load();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.green,
elevation: 0.0,
title: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: const [
Text('Stock '),
Text(
'News',
style: TextStyle(
color: Colors.black54,
),
),
],
),
centerTitle:true,
bottom: const PreferredSize(
preferredSize: Size.zero,
child: Text("Powered by news.org")),
),
body: _loading
? Container(
child: const Center(
child: CircularProgressIndicator(),
),
)
: SingleChildScrollView(
child: Container(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
///Categories
Container(
padding: const EdgeInsets.symmetric(horizontal: 22.0),
height: 90.0,
child: Expanded(
child: ListView.builder(
itemCount: categories.length,
scrollDirection: Axis.horizontal,
shrinkWrap: true,
itemBuilder: (context, index) {
return CategoryTile(
imageUrl: categories[index].imageAssetUrl,
categoryName: categories[index].categoryName,
);
}),
),
),
///Blogs
Container(
padding: const EdgeInsets.only(top: 16.0),
child: Expanded(
child: ListView.builder(
physics: const ClampingScrollPhysics(),
shrinkWrap: true,
itemCount: articles.length,
itemBuilder: (context, index) {
return BlogTile(
imageURL: articles[index].urlToImage,
title: articles[index].title,
desc: articles[index].description,
url: articles[index].url,
);
},
),
),
),
],
),
),
),
bottomNavigationBar: _isAdsLoaded?SizedBox(
height: _bannerads.size.height.toDouble(),
width: _bannerads.size.width.toDouble(),
child: AdWidget(ad: _bannerads),
)
:const SizedBox(),
);
}
}
class CategoryTile extends StatelessWidget {
final String imageUrl, categoryName;
const CategoryTile({required this.imageUrl, required this.categoryName});
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => CategoryNews(
category: categoryName.toLowerCase(),
),
),
);
},
child: Container(
margin: EdgeInsets.only(right: 10.0),
child: Stack(
children: [
ClipRRect(
borderRadius: BorderRadius.circular(6),
child: imageUrl != null
? CachedNetworkImage(
imageUrl: imageUrl,
width: 120,
height: 60.0,
fit: BoxFit.cover,
)
: Image.network(
imageUrl,
width: 120.0,
height: 60.0,
fit: BoxFit.cover,
),
),
Container(
alignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.black26,
borderRadius: BorderRadius.circular(6),
),
width: 120,
height: 60.0,
child: Text(
categoryName,
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w500,
fontSize: 18.0,
),
),
),
],
),
),
);
}
}
class BlogTile extends StatelessWidget {
final String imageURL, title, desc, url;
BlogTile(
{required this.imageURL,
required this.title,
required this.desc,
required this.url});
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ArticleView(
blogUrl: url,
)),
);
},
child: Container(
margin: const EdgeInsets.only(bottom: 16.0, left: 10.0, right: 10.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
ClipRRect(
borderRadius: BorderRadius.circular(6.0),
child: imageURL != null
? CachedNetworkImage(
imageUrl: imageURL,
)
: Image.network(imageURL),
),
const SizedBox(
height: 8.0,
),
Text(
title,
style: const TextStyle(
//color: Colors.black87,
fontSize: 17.0,
fontWeight: FontWeight.w500,
),
),
const SizedBox(
height: 8.0,
),
Text(
desc,
style: const TextStyle(
//color: Colors.black54,
),
),
],
),
),
);
}
}
and here's the screen shots of the app
[![debugging app][1]][1]
[![build app][2]][2]
[1]: https://i.stack.imgur.com/tvBsG.jpg
[2]: https://i.stack.imgur.com/wOuxS.jpg
Check if this line exists in android/app/src/main/AndroidManifest.xml file. If it doesn't add it right below the package name line. This will grant the app INTERNET permission so it can access it & display the data from the internet.
<uses-permission android:name="android.permission.INTERNET"/>
Flutter by default only adds the INTERNET permission in debug mode. When you build an APK in release mode, you have to explicitly add the permission by including the above line.
More info here.

Custom Sliver App Bar in flutter with an Image and 2 Text widgets going into app bar on scrolling

i want to implement the sliver app bar as shown in the the 2 pictures given below. After much googling , I fount about the CustomScrollView widget and the SliverAppBar widget but all the tutorials and blogs online about sliver app bars show a simple one where an image disappears into an app bar with a text as title on scrolling. However here what I want to achieve is slightly different and I am having a hard time trying to figure out how to do it. Can anyone help me with it?
You can try this:
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
#override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
ScrollController? _scrollController;
bool lastStatus = true;
double height = 200;
void _scrollListener() {
if (_isShrink != lastStatus) {
setState(() {
lastStatus = _isShrink;
});
}
}
bool get _isShrink {
return _scrollController != null &&
_scrollController!.hasClients &&
_scrollController!.offset > (height - kToolbarHeight);
}
#override
void initState() {
super.initState();
_scrollController = ScrollController()..addListener(_scrollListener);
}
#override
void dispose() {
_scrollController?.removeListener(_scrollListener);
_scrollController?.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
final TextTheme textTheme = Theme.of(context).textTheme;
return MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData.dark(),
title: 'Horizons Weather',
home: Scaffold(
body: NestedScrollView(
controller: _scrollController,
headerSliverBuilder: (context, innerBoxIsScrolled) {
return [
SliverAppBar(
elevation: 0,
backgroundColor: Colors.blueGrey,
pinned: true,
expandedHeight: 275,
flexibleSpace: FlexibleSpaceBar(
collapseMode: CollapseMode.parallax,
title: _isShrink
? const Text(
"Profile",
)
: null,
background: SafeArea(
child: Column(
children: [
Padding(
padding: const EdgeInsets.only(top: 48),
child: ClipRRect(
borderRadius: BorderRadius.circular(100),
child: Image.network(
headerImage,
fit: BoxFit.cover,
height: 100,
width: 100,
),
),
),
const SizedBox(
height: 16,
),
Text(
"Flipkart",
style: textTheme.headline4,
),
const SizedBox(
height: 8,
),
const Text(
"flipkart.com",
),
const SizedBox(
height: 5,
),
const Text(
"Info about the company",
),
],
),
),
),
actions: _isShrink
? [
Padding(
padding: const EdgeInsets.only(left: 8, right: 12),
child: Row(
children: [
Padding(
padding:
const EdgeInsets.only(left: 8, right: 8),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: const [
Text(
"Flipkart",
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
Text(
"flipkart.com",
style: TextStyle(
fontSize: 12,
),
),
],
),
),
ClipRRect(
borderRadius: BorderRadius.circular(100),
child: Image.network(
headerImage,
fit: BoxFit.cover,
height: 30,
width: 30,
),
),
],
),
),
]
: null,
),
];
},
body: CustomScrollView(
scrollBehavior: const ConstantScrollBehavior(),
slivers: [
SliverList(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Center(child: Text("Item: $index")),
);
},
childCount: 50,
),
),
],
),
),
drawer: Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: <Widget>[
const UserAccountsDrawerHeader(
accountName: Text("Zakaria Hossain"),
accountEmail: Text("zakariaaltime#gmail.com"),
currentAccountPicture: CircleAvatar(
backgroundColor: Colors.orange,
child: Text(
"A",
style: TextStyle(fontSize: 40.0),
),
),
),
ListTile(
leading: Icon(Icons.home),
title: Text("Home"),
onTap: () {
Navigator.pop(context);
},
),
ListTile(
leading: Icon(Icons.settings),
title: Text("Settings"),
onTap: () {
Navigator.pop(context);
},
),
ListTile(
leading: Icon(Icons.contacts),
title: Text("Contact Us"),
onTap: () {
Navigator.pop(context);
},
),
],
),
),
),
);
}
}
Demo

How to Refresh page data API get data dynamically in flutter

I used the RefreshIndicator to pull to refresh the page data but it not working
This is my code!! help me to over come the issue on refresh on data
import 'dart:async';
import 'package:apitest3/services/api_manager.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'models/statusinfo.dart';
import 'package:flutter/services.dart';
class TestPage extends StatefulWidget {
const TestPage({Key? key}) : super(key: key);
#override
_TestPageState createState() => _TestPageState();
}
class _TestPageState extends State<TestPage> {
late Future<Status> _status;
final GlobalKey<RefreshIndicatorState> _refreshIndicatorkey =
new GlobalKey<RefreshIndicatorState>();
#override
void initState() {
_status = API_Manager().getStatus();
super.initState();
WidgetsBinding.instance?.addPostFrameCallback(
(_) => _refreshIndicatorkey.currentState?.show());
}
#override
Widget build(BuildContext context) {
final key = new GlobalKey<ScaffoldState>();
return Scaffold(
body: SafeArea(
child: RefreshIndicator(
key: keyStatus,
onRefresh: () => _status,
child: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [Colors.purple, Colors.blue])),
padding: EdgeInsets.all(4),
child: FutureBuilder<Status>(
future: _status,
builder: (context, snapshot) {
if (snapshot.hasData) {
return ListView.builder(
padding: EdgeInsets.all(4),
itemCount: 1,
itemBuilder: (context, index) {
var result = snapshot.data!.result.syncInfo;
return Flexible(
child: Card(
elevation: 20,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
color: Colors.indigo.shade900,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
Container(
child: Text(
"Latest Block Hash ",
style: TextStyle(
fontSize: 15,
color: Colors.white),
)),
],
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
children: [
RaisedButton.icon(
color: Colors.blueAccent,
onPressed: () {
Clipboard.setData(ClipboardData(
text: result.latestBlockHash));
key.currentState!
.showSnackBar(new SnackBar(
backgroundColor:Colors.amberAccent,
content: new Text(
"Copied to Latest Block Hash!!",
style: TextStyle(
color: Colors.red),
),
));
},
icon: Icon(
Icons.copy,
color: Colors.white,
size: 15,
),
label: Text(
"${result.latestBlockHash}",
style: TextStyle(
fontSize: 7.1,
color: Colors.white),
overflow: TextOverflow.ellipsis,
maxLines: 1,
)),
),
),
),
);
}
}
),
),
Card(
color: Colors.blueAccent,
child: Padding(
padding: const EdgeInsets.all(6.0),
child: Container(
height: 20,
child: Row(
children: [
Text(
" ${result.latestBlockTime
.toString()}",
style: TextStyle(
fontSize: 10,
color: Colors.white),
),
],
),
],
),
),
);
});
} else
return Center(child: CircularProgressIndicator()
//CupertinoActivityIndicator()
);
},
),
),
),
),
);
}
}
I don't know what i made mistake on this code for refresh function
And all so i try to root navigation method but it pop more pages on the same page so once try to close the page it there several pages to close,
so, try to help me on proper way to pull refresh on the page.
You need to update the state after refreshing on onRefresh callback. Currently, you are just assigning it to a Future variable.
This is a simple way to do it.
RefreshIndicator(
onRefresh: () { setState((){
// Update your data here
}); },
child: ...
)

Acessing List items on another class

Hi I would like to know how can I access the items of a list on a different class where the list was created.Particularly i want to access items of the restaurantList on the Restaurant Screen class.
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:projectfooddelivery/Src/models/restaurant.dart';
List<Restaurant> restaurantList=[
Restaurant(image:"kfcloja.jpg",distance: "2 miles away",location:"Shoprite do magoanine",restaurantName: "KFC"),
Restaurant(image:"dominos.jpg",distance: "0.9 miles away",location:"Downtown",restaurantName: "Dominos"),
Restaurant(image:"kfclogo.png",distance: "2 miles away",location:"Shoprite do magoanine",restaurantName: "KFC"),
];//I would like to access the items on the list
class RestaurantWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
height: 350,
child: ListView.builder(
scrollDirection: Axis.vertical,
itemCount: restaurantList.length,
itemBuilder: (_, index) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
decoration: BoxDecoration(
border: Border.all(
width: 1.0,
color: Colors.grey[100]
),
borderRadius: BorderRadius.circular(20)
),
child: Row(
children: <Widget>[
Container(
width: 150,
child: ClipRRect(
borderRadius: BorderRadius.circular(20),
child: Image.asset("images/${restaurantList[index].image}",fit:BoxFit.cover ,)
)
),
Padding(
padding: const EdgeInsets.all(3.0),
child: Container(
padding: EdgeInsets.all(2),
height: 70,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text("${restaurantList[index].restaurantName}",style: TextStyle(fontWeight: FontWeight.bold),),
Row(
children: <Widget>[
Icon(Icons.star,size: 15,color:Colors.yellowAccent,),
Icon(Icons.star,size: 15,color:Colors.yellowAccent),
Icon(Icons.star,size: 15,color:Colors.yellowAccent),
Icon(Icons.star,size: 15,color:Colors.yellowAccent),
Icon(Icons.star_half,size: 15,color:Colors.yellowAccent),
],
),
Text("${restaurantList[index].location}"),
Text("${restaurantList[index].distance}"),
],
),
),
),
],
),
),
);
},
),
);
}
}
In this class
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:projectfooddelivery/Src/widgets/menu_widget.dart';
import 'package:smooth_star_rating/smooth_star_rating.dart';
class RestaurantScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
width: 400,
child: Column(
children: <Widget>[
Stack(
children: <Widget>[
Image.asset(
"images/kfcloja.jpg",
fit: BoxFit.cover,
),
Positioned(
child: IconButton(
icon: Icon(Icons.keyboard_arrow_left,size: 40,color: Colors.white,),
onPressed: (){},
),
top: 15,
)
],
),
Padding(
padding: const EdgeInsets.only(top: 14, left: 14, right: 14),
child: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text(
"Restaurant KFC",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 18,
),
),
Text(
"0.2 miles away",
style: TextStyle(
fontSize: 16,
),
),
],
),
Align(
alignment: Alignment.topLeft,
child: SmoothStarRating(
allowHalfRating: false,
starCount: 5,
size: 20.0,
filledIconData: Icons.blur_off,
halfFilledIconData: Icons.blur_on,
color: Colors.yellowAccent,
borderColor: Colors.yellowAccent,
spacing: 0.0),
),
Align(
alignment: Alignment.topLeft,
child: Text("200 Main St, New york"),
),
Padding(
padding: const EdgeInsets.only(
left: 30, right: 30, top: 20, bottom: 5),
child: Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
FlatButton.icon(
shape: new RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(10.0),
),
color: Theme.of(context).primaryColor,
icon: Icon(
Icons.rate_review,
color: Colors.white,
),
label: Text(
'Reviews',
style: TextStyle(color: Colors.white),
),
onPressed: () {},
),
FlatButton.icon(
shape: new RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(10.0),
),
color: Theme.of(context).primaryColor,
icon: Icon(
Icons.contact_phone,
color: Colors.white,
),
label: Text(
'Contact',
style: TextStyle(color: Colors.white),
),
onPressed: () {},
)
],
),
),
),
Text(
"Menu",
textAlign: TextAlign.center,
style: TextStyle(fontSize: 20),
),
MenuWidget(),
],
)
),
)
],
),
),
);
}
}
You can send and receive the data from one screen to another as follow , you need to use the Navigator for it , In below example i am sending the data from class A to class B as follow
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => B(bean: restaurantList[index])), //// HERE B IS THE CLASS ON WHICH YOU NEED TO CARRY DATA FROM CLASS A
);
And inside the B class you need to create the contrsutor to receive the data from A like below
class B extends StatefulWidget {
Restaurant bean;
B ({Key key, #required this.bean}) : super(key: key); ////YOU WILL GET THE DATA HERE FROM THE CONSTRUCTOR , AND USE IT INSIDE THE CLASS LIKE "widget.bean"
#override
State<StatefulWidget> createState() {
// TODO: implement createState
return _B();
}
}
And please check the example of it to pass data from one class to another
A class which send data to B class
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'B.dart';
import 'Fields.dart';
class A extends StatefulWidget {
#override
State<StatefulWidget> createState() {
// TODO: implement createState
return _A();
}
}
class _A extends State<A> {
Widget build(BuildContext context) {
return MaterialApp(
title: 'Screen A',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primaryColor: Colors.red,
accentColor: Color(0xFFFEF9EB),
),
home: Scaffold(
appBar: new AppBar(),
body: Container(
margin: EdgeInsets.all(20.0),
child: Column(
children: <Widget>[
Padding(
padding: EdgeInsets.all(10.0),
child: Text("Screen A"),
),
Expanded(
child: ListView.builder(
itemCount: fields.length,
itemBuilder: (BuildContext ctxt, int index) {
return ListTile(
title: new Text("Rating #${fields[index].rating}"),
subtitle: new Text(fields[index].title),
onTap: (){
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => B(bean: fields [index])), //// HERE B IS THE CLASS ON WHICH YOU NEED TO CARRY DATA FROM CLASS A
);
},
);
}),
)
],
),
)));
}
}
List<Fields> fields = [
new Fields(
'One',
1,
),
new Fields(
'Two',
2,
),
new Fields(
'Three',
3,
),
new Fields(
'Four',
4,
),
new Fields(
'Five',
5,
),
];
Now check B class which receive the data from A class
import 'package:flutter/material.dart';
import 'Fields.dart';
class B extends StatefulWidget{
Fields bean;
B ({Key key, #required this.bean}) : super(key: key); ////YOU WILL GET THE DATA HERE FROM THE CONSTRUCTOR , AND USE IT INSIDE THE CLASS LIKE "widget.bean"
#override
State<StatefulWidget> createState() {
// TODO: implement createState
return _B ();
}
}
class _B extends State<B> {
#override
Widget build(BuildContext context) {
// TODO: implement build
return MaterialApp(
title: 'Screen A',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primaryColor: Colors.red,
accentColor: Color(0xFFFEF9EB),
),
home: Scaffold(
appBar: new AppBar(),
body: Container(
margin: EdgeInsets.all(20.0),
child: Column(
children: <Widget>[
Padding(
padding: EdgeInsets.all(10.0),
child: Center(
child: Text("Screen B" ,style: TextStyle(fontSize: 20.0),),
)
),
Text("Rating=>>> ${widget.bean.rating} and Title ${widget.bean.title} ")
],
),
)));
}
}
And I have used the Pojo class for the list ,please check it once
Fields.dart
class Fields {
final String title;
final int rating;
Fields(this.title, this.rating);
}
And the output of the above program as follow.

How to change a bottom navigation bar icon in the setState() function in flutter?

I'm building a food ordering app in flutter. What I want is, when the user adds items to the cart, I want the cart icon in the bottom navigation bar to obtain a red dot on top to notify the user of the addition of items to the cart.
To achieve this, I have created a global variable called no_of_cart_items and when the user adds an item to the cart, I increment this variable in the setState() function as follows:
setState(() {
GlobalVariables.no_of_cart_items+=1;
// change icon here
});
In this setState() function, I wish to change the icon in the bottom navigation bar. How should I do this?
Thank you.
FULL CODE
This is main.dart
//import lines
void main() => runApp(CanteenApp());
class CanteenApp extends StatefulWidget {
#override
_CanteenAppState createState() => _CanteenAppState();
}
class _CanteenAppState extends State<CanteenApp> {
int _currentindex=0; // index of bottom tab
int admin=GlobalVariables.admin;
BottomNavigationBadge badger = new BottomNavigationBadge(
backgroundColor: Colors.red,
badgeShape: BottomNavigationBadgeShape.circle,
textColor: Colors.white,
position: BottomNavigationBadgePosition.topRight,
textSize: 8);
Widget callpage(int currentIndex) {
switch (currentIndex) {
case 0: return UserProfile();
case 1: return Menu();
case 2: return Cart();
break;
default: return UserProfile();
}
}
#override
Widget build(BuildContext context) {
if(admin==1 && _currentindex==2) {
//if you're the admin and have called the history page
return MaterialApp(
debugShowCheckedModeBanner: false,
home: DefaultTabController(
length: 2,
child: Scaffold(
resizeToAvoidBottomPadding: false,
appBar: PreferredSize(
preferredSize: Size.fromHeight(80.0),
child: AppBar(
bottom: TabBar(
indicatorColor: Colors.white,
indicatorWeight: 5,
tabs: <Widget>[
Tab(
child: Align(
alignment: Alignment.center,
child: Text(
'Order History',
style: TextStyle(
fontSize: 20
),
)
)
),
Tab(
child: Align(
alignment: Alignment.center,
child: Text(
'Deposit / Withdraw\nHistory',
style: TextStyle(
fontSize: 17
),
textAlign: TextAlign.center,
)
)
),
],
),
),
),
body: TabBarView(
children: <Widget>[
AdminOrderHistory(),
DepositWithdrawHistory()
],
),
bottomNavigationBar: BottomNavigationBar(
elevation: 10,
currentIndex: _currentindex,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.account_circle),
title: Text('Profile'),
),
BottomNavigationBarItem(
icon: Icon(Icons.restaurant_menu),
title: Text('Menu'),
),
BottomNavigationBarItem(
icon: Icon(Icons.history),
title: Text('History'),
),
],
onTap: (index){
setState(() {
_currentindex=index;
});
}
),
),
),
theme: appTheme,
);
}
else if(admin==1){
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
resizeToAvoidBottomPadding: false,
body: callpage(_currentindex),
bottomNavigationBar: BottomNavigationBar(
elevation: 10,
currentIndex: _currentindex,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.account_circle),
title: Text('Profile'),
),
BottomNavigationBarItem(
icon: Icon(Icons.restaurant_menu),
title: Text('Menu'),
),
BottomNavigationBarItem(
icon: Icon(Icons.history),
title: Text('History'),
),
],
onTap: (index){
setState(() {
_currentindex=index;
});
}
),
),
theme: appTheme,
);
}
else if(admin==0){
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
resizeToAvoidBottomPadding: false,
body: callpage(_currentindex),
bottomNavigationBar:BottomNavigationBar(
elevation: 10,
currentIndex: _currentindex,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.account_circle),
title: Text('Profile'),
),
BottomNavigationBarItem(
icon: Icon(Icons.restaurant_menu),
title: Text('Menu'),
),
BottomNavigationBarItem(
title: Text('Cart'),
icon: Badge(
showBadge: true,
badgeContent: Text(
GlobalVariables.no_of_cart_items.toString(),
style: TextStyle(
color: Colors.white
),
),
child: Icon(Icons.shopping_cart)
)
),
],
onTap: (index){
setState(() {
_currentindex=index;
});
}
),
),
theme: appTheme,
);
}
}
}
This is menu.dart
//import lines
int admin=GlobalVariables.admin;
List snacksmenuitems=[
['Vada Pav', 15],
['Samosa Pav', 15],
['Punjabi Samosa', 25],
['Pav', 5]
];
List ricemenuitems=[
['Fried Rice', 62],
['Schezwan Rice', 69],
['Singapore Rice', 69],
['Manchow Rice', 73],
];
class Menu extends StatefulWidget {
#override
_MenuState createState() => _MenuState();
}
class _MenuState extends State<Menu> {
#override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
MenuTopPart(),
MenuBottomPart(),
],
);
}
}
Color firstColor = Color(0xFFF47D15);
Color secondColor = Color(0xFFEF772C);
class MenuTopPart extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
ClipPath(
clipper: CustomShapeClipper(),
child: Container(
height:140.0,
width:MediaQuery.of(context).size.width,
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [firstColor, secondColor],
)
),
child: Column(
children: <Widget>[
SizedBox(height: 53.0),
Text(
'MENU',
style: TextStyle(
fontSize: 30.0,
color: Colors.white,
),
textAlign: TextAlign.center,
),
],
)
)
)
],
);
}
}
class MenuBottomPart extends StatefulWidget {
#override
_MenuBottomPartState createState() => _MenuBottomPartState();
}
class _MenuBottomPartState extends State<MenuBottomPart> {
#override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
SizedBox(height: 10),
SizedBox(height: 10),
Padding(
padding: const EdgeInsets.fromLTRB(20, 0, 20, 10),
child: Container(
height: MediaQuery
.of(context)
.size
.height * 0.60,
child: ListView(
padding: EdgeInsets.fromLTRB(0, 0, 0, 0),
scrollDirection: Axis.vertical,
children: <Widget>[
Card(
child: Padding(
padding: const EdgeInsets.fromLTRB(5, 0, 5, 0),
child: ExpansionTile(
title: Text('SNACKS'),
children: snacksmenuitems.map((menuitem) {
//print(menuitem);
return MenuItem(menuitem: menuitem);
/*SizedBox(height:10),
MenuItem(),
SizedBox(height:10),
MenuItem(),
SizedBox(height:10),
MenuItem()*/
}).toList()
),
)
),
SizedBox(height: 10),
Card(
child: Padding(
padding: const EdgeInsets.fromLTRB(5, 0, 5, 0),
child: ExpansionTile(
title: Text('RICE ITEMS'),
children: ricemenuitems.map((menuitem) {
//print(menuitem);
return MenuItem(menuitem: menuitem);
/*SizedBox(height:10),
MenuItem(),
SizedBox(height:10),
MenuItem(),
SizedBox(height:10),
MenuItem()*/
}).toList()
),
)
)
]
),
),
)
]
);
}
}
class MenuItem extends StatefulWidget {
List menuitem=[];
MenuItem({Key key, this.menuitem}): super(key: key);
#override
_MenuItemState createState() => _MenuItemState();
}
class _MenuItemState extends State<MenuItem> {
#override
Widget build(BuildContext context) {
return Container(
margin: const EdgeInsets.only(bottom: 10),
decoration: BoxDecoration(
border: Border.all(color: Colors.black12),
borderRadius: BorderRadius.all(Radius.circular(10))
),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Image(
image: NetworkImage('https://www.whiskaffair.com/wp-content/uploads/2018/08/Mumbai-Pav-Bhaji-4.jpg'),
width: 80,
height: 80
),
SizedBox(width:10),
Padding(
padding: const EdgeInsets.fromLTRB(0, 5, 0, 0),
child: Container(
width:190,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
widget.menuitem[0],
style: TextStyle(
fontSize:19,
color: Colors.grey[900]
),
),
SizedBox(height:5.0),
Padding(
padding: const EdgeInsets.fromLTRB(0, 10, 0, 0),
child: Row(
children: <Widget>[
Row(
children: <Widget>[
Text(
'₹',
style: TextStyle(
fontSize: 15,
color: Colors.grey[800]
),
),
Text(
widget.menuitem[1].toString(),
style: TextStyle(
fontSize: 15,
color: Colors.grey[800]
),
)
],
),
SizedBox(width:70),
Container(
child: Row(
children: <Widget>[
SizedBox(
width:30,
height:30,
child: FloatingActionButton(
onPressed: (){
setState(() {
if(GlobalVariables.allcartitems[widget.menuitem[0]][0]>0){
GlobalVariables.no_of_cart_items-=1;
GlobalVariables.allcartitems[widget.menuitem[0]][0]-=1;
GlobalVariables.totalcost-=GlobalVariables.allcartitems[widget.menuitem[0]][1];
// CHECK IF CART HAS NO ITEMS AND REMOVE BADGE HERE
}
});
},
elevation: 1,
child: Icon(Icons.remove, size: 18),
backgroundColor: Colors.red[300],
mini: true,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(5.0))),
),
),
Padding(
padding: const EdgeInsets.fromLTRB(5, 0, 5, 0),
child: Text(
GlobalVariables.allcartitems[widget.menuitem[0]][0].toString(),
style: TextStyle(
fontSize: 18
),
),
),
SizedBox(
width:30,
height:30,
child: FloatingActionButton(
onPressed: (){
setState(() {
GlobalVariables.no_of_cart_items+=1;
GlobalVariables.allcartitems[widget.menuitem[0]][0]+=1;
GlobalVariables.totalcost+=GlobalVariables.allcartitems[widget.menuitem[0]][1];
// SET BADGE HERE
});
},
elevation: 1,
child: Icon(Icons.add, size: 20),
backgroundColor: Colors.green[300],
mini:true,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(5.0))),
),
)
],
)
)
],
),
),
],
),
),
)
],
),
);
}
}
This is cart.dart:
import 'dart:convert';
import 'package:canteen_app/pages/globalvar.dart';
import 'package:canteen_app/pages/globalvar.dart' as prefix0;
import 'package:canteen_app/pages/orderReceipt.dart';
import 'package:flutter/material.dart';
import 'package:canteen_app/pages/CustomShapeClipper.dart';
import 'package:http/http.dart' as http;
import 'package:intl/intl.dart';
class Cart extends StatefulWidget {
#override
_CartState createState() => _CartState();
}
class _CartState extends State<Cart> {
#override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
CartTopPart(),
CartBottomPart()
],
);
}
}
class CartTopPart extends StatefulWidget {
#override
_CartTopPartState createState() => _CartTopPartState();
}
Color firstColor = Color(0xFFF47D15);
Color secondColor = Color(0xFFEF772C);
class _CartTopPartState extends State<CartTopPart> {
#override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
ClipPath(
clipper: CustomShapeClipper(),
child: Container(
height:140.0,
width:MediaQuery.of(context).size.width,
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [firstColor, secondColor],
)
),
child: Column(
children: <Widget>[
SizedBox(height: 53.0),
Text(
'CART',
style: TextStyle(
fontSize: 30.0,
color: Colors.white,
),
textAlign: TextAlign.center,
),
],
)
)
)
],
);
}
}
var cartmenuitems = GlobalVariables.allcartitems.keys.toList();
class CartBottomPart extends StatefulWidget {
#override
_CartBottomPartState createState() => _CartBottomPartState();
}
class _CartBottomPartState extends State<CartBottomPart> {
bool _isLoading=false;
createAlertDialog(BuildContext context, String errormessage){
return showDialog(
context: context,
builder: (context){
return AlertDialog(
content: Text(errormessage)
);
}
);
}
#override
Widget build(BuildContext context) {
if(GlobalVariables.no_of_cart_items>0) {
return _isLoading==true ? Center(child: CircularProgressIndicator()) : Padding(
padding: const EdgeInsets.fromLTRB(20, 10, 20, 10),
child: Column(
children: <Widget>[
Container(
height: MediaQuery
.of(context)
.size
.height * 0.40,
child: ListView(
padding: EdgeInsets.fromLTRB(0, 10, 0, 0),
scrollDirection: Axis.vertical,
children: cartmenuitems.map((menuitem) {
//print(cartmenuitems);
// print(GlobalVariables.allcartitems[menuitem]);
//if(GlobalVariables.allcartitems[menuitem]>=1) {
//print('heyy');
return CartOrderDish(menuitem: menuitem);
//}
}).toList()
),
),
Divider(
color: Colors.black
),
Row(
children: <Widget>[
Text(
'Total Amount:',
style: TextStyle(
fontSize: 20
),
),
SizedBox(width: 140),
Row(
children: <Widget>[
Text(
'₹',
style: TextStyle(
fontSize: 20
),
),
Text(
GlobalVariables.totalcost.toString(),
style: TextStyle(
fontSize: 20
)
)
],
)
],
),
SizedBox(height: 5),
Align(
alignment: Alignment.centerLeft,
child: Text(
'(Inclusive of GST)',
style: TextStyle(
fontSize: 15
),
),
),
SizedBox(height: 18),
RaisedButton(
onPressed: () {
if((GlobalVariables.accountbalance-GlobalVariables.totalcost)<0){
createAlertDialog(context, "Whoops! The total cost exceeds your account balance!\n\nYour account balance can be updated at the CASH COUNTER.");
}
else {
setState(() {
_isLoading = true;
});
// creating a list of all cart items to send to php
List cart = [];
cartmenuitems.map((menuitem) {
if (GlobalVariables.allcartitems[menuitem][0] > 0) {
cart.add([menuitem, GlobalVariables.allcartitems[menuitem][0], GlobalVariables.allcartitems[menuitem][1] * GlobalVariables.allcartitems[menuitem][0]]);
}
}).toList();
print(jsonEncode(cart));
Future placeOrderFunction() async {
print(GlobalVariables.username);
final response = await http.post(
"https://kjscecanteenapp.000webhostapp.com/place_order_sys.php",
body: {
"cart": json.encode(cart),
"username": GlobalVariables.username
});
// print(response.body);
var decodedResponse = json.decode(response.body);
print(decodedResponse);
setState(() {
_isLoading = false;
});
if (decodedResponse['error'] != -1) {
// means no error
int orderId=decodedResponse['error'];
int cost=GlobalVariables.totalcost;
GlobalVariables.no_of_cart_items = 0;
String date=DateFormat('dd-MMM-yyyy').format(DateTime.now());
cartmenuitems.map((menuitem) {
if (GlobalVariables.allcartitems[menuitem][0] > 0) {
GlobalVariables.allcartitems[menuitem][0] = 0;
}
});
GlobalVariables ob = new GlobalVariables();
ob.resetcart();
GlobalVariables.accountbalance -= GlobalVariables.totalcost;
GlobalVariables.totalcost = 0;
Navigator.of(context)
.push(MaterialPageRoute<Null>(
builder: (BuildContext context) {
return new OrderReceipt(orderId: orderId, cost: cost, date: date, cart: cart);
}));
}
else{
createAlertDialog(context, "There was some error during the order placement. Don't worry tho try again in a few seconds!");
}
}
placeOrderFunction();
}
},
elevation: 5.0,
textColor: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5.0)),
padding: const EdgeInsets.all(0.0),
child: Container(
decoration: const BoxDecoration(
gradient: LinearGradient(
colors: <Color>[
Color(0xFF0083B0),
Color(0xFF00B4DB),
]
)
),
padding: const EdgeInsets.fromLTRB(40, 15, 40, 15),
child: Text(
'Place Order',
style: TextStyle(
fontSize: 20
),
),
)
)
],
),
);
}
else {
return Padding(
padding: const EdgeInsets.all(20.0),
child: Container(
height: MediaQuery.of(context).size.height*0.6,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Text(
'Please add some items into your cart.',
style: TextStyle(
fontSize: 20,
),
textAlign: TextAlign.center,
),
],
),
),
);
}
}
}
class CartOrderDish extends StatefulWidget {
String menuitem;
CartOrderDish({Key key, this.menuitem}): super(key: key);
#override
_CartOrderDishState createState() => _CartOrderDishState();
}
class _CartOrderDishState extends State<CartOrderDish> {
#override
Widget build(BuildContext context) {
if(GlobalVariables.allcartitems[widget.menuitem][0]>0) {
int price=GlobalVariables.allcartitems[widget.menuitem][0]*GlobalVariables.allcartitems[widget.menuitem][1];
return Padding(
padding: const EdgeInsets.fromLTRB(0, 0, 0, 10),
child: Row(
children: <Widget>[
Expanded(
child: Text(
widget.menuitem,
style: TextStyle(
fontSize: 20
),
),
),
SizedBox(width: 50),
Container(
child: Row(
children: <Widget>[
SizedBox(
width: 30,
height: 30,
child: FloatingActionButton(
heroTag: 'fab1',
elevation: 1,
child: Icon(Icons.remove, size: 18),
backgroundColor: Colors.red[300],
mini: true,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(5.0))),
),
),
Padding(
padding: const EdgeInsets.fromLTRB(5, 0, 5, 0),
child: Text(
GlobalVariables.allcartitems[widget.menuitem][0].toString(),
style: TextStyle(
fontSize: 18
),
),
),
SizedBox(
width: 30,
height: 30,
child: FloatingActionButton(
heroTag: 'fab2',
elevation: 1,
child: Icon(Icons.add, size: 20),
backgroundColor: Colors.green[300],
mini: true,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(5.0))),
),
)
],
)
),
SizedBox(width: 50),
Row(
children: <Widget>[
Text(
'₹',
style: TextStyle(
fontSize: 20
),
),
Text(
price.toString(),
style: TextStyle(
fontSize:20
)
)
],
)
],
),
);
}
else{
return Container();
}
}
}
Instead of changing the entire icon to indicate items added to cart, you could use Badge
Badge package: https://pub.dev/packages/badges
Update-1: For implementing the badges:
var p1badge = false;
var p2badge = false;
List<BottomNavigationBarItem> buildBottomNavBarItems() {
return [
BottomNavigationBarItem(
icon: Badge(
showBadge: p1badge,
child: Icon(Icons.filter_1),
),
title: Text('Page-1')),
BottomNavigationBarItem(
icon: Badge(
showBadge: p2badge,
child: Icon(Icons.filter_2),
),
title: Text('Page-2'))
];
}
Use a VoidCallback to update the badge:
class Page1 extends StatelessWidget {
VoidCallback onP1Badge;
Page1({this.onP1Badge});
#override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
RaisedButton(
child: Text('P1 BADGE'),
onPressed: () {onP1Badge();},
),
],
);
}
}
Change the value of p1badge to true and call setState():
pages = [
Page1(
onP1Badge: () {
p1badge = true;
setState(() {});
},
),
Page2()
];
Update-2: Check this out: https://github.com/TheArhaam/Flutter-BottomNavigationBar-Badge
GIF: