How to switch class when a tab is clicked using google_nav_bar Flutter - flutter

I'm using google_nav_bar and line_icons from pub.
I have 3 classes named Home(), Likes(), Profile(). I want to switch classes when a bottom navigation bar tab is clicked, I have made a list of the classes, but I'm not sure how to change the classes when a tab is clicked.
Here is the code I have so far:
class MainScreen extends StatefulWidget {
#override
_MainScreenState createState() => _MainScreenState();
}
class _MainScreenState extends State<MainScreen> {
int _page = 0;
final screens = [
Home(),
Likes(),
Profile()
];
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey[100],
bottomNavigationBar: GNav(
rippleColor: Colors.grey[300],
hoverColor: Colors.grey[100],
gap: 8,
activeColor: Colors.black,
iconSize: 24,
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
duration: Duration(milliseconds: 400),
tabBackgroundColor: Colors.grey[100],
color: Colors.black,
tabs: [
GButton(
icon: LineIcons.home,
text: 'Home',
),
GButton(
icon: LineIcons.heart,
text: 'Likes',
),
GButton(
icon: LineIcons.user,
text: 'Profile',
),
],
selectedIndex: _page,
onTabChange: (index) {
setState(() {
_page = index;
});
},
),
body: /*new Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: _page == 0
? Home()
: _page == 1
? Likes()
: Profile(),
),*/
Center(
child: screens.elementAt(_page),
),
);
}
}
I would like to navigate the bottom navigation bar to the Likes() class when the second tab is clicked and navigate to the Profile() class when the third navigation bar is clicked..

Everything is working fine. Replace Tab widget with different widgets like Home(), Likes(), Profile()..
Now it will be like
class Tab extends StatelessWidget {
final int tab;
const Tab({
Key? key,
required this.tab,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Container(
child: Text("$tab"),
);
}
}
class MainScreen extends StatefulWidget {
#override
_MainScreenState createState() => _MainScreenState();
}
class _MainScreenState extends State<MainScreen> {
int _page = 0;
final screens = const [Tab(tab: 1), Tab(tab: 2), Tab(tab: 3)];
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey[100],
bottomNavigationBar: GNav(
rippleColor: Colors.grey[300]!,
hoverColor: Colors.grey[100]!,
gap: 8,
activeColor: Colors.black,
iconSize: 24,
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12),
duration: const Duration(milliseconds: 400),
tabBackgroundColor: Colors.grey[100]!,
color: Colors.black,
tabs: const [
GButton(
icon: LineIcons.home,
text: 'Home',
),
GButton(
icon: LineIcons.heart,
text: 'Likes',
),
GButton(
icon: LineIcons.user,
text: 'Profile',
),
],
selectedIndex: _page,
onTabChange: (index) {
setState(() {
_page = index;
});
},
),
body: Center(
child: screens[_page],
),
);
}
}
Does it solve in your case?

Try below code hope its helpful to you. Just add your Widgets in your classes
Your BottomBar Widget.
class Example extends StatefulWidget {
#override
_ExampleState createState() => _ExampleState();
}
class _ExampleState extends State<Example> {
int _selectedIndex = 0;
static const List<Widget> _widgetOptions = <Widget>[
Home(),
Likes(),
Profile(),
];
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
elevation: 20,
title: const Text('GoogleNavBar'),
),
body: Center(
child: _widgetOptions.elementAt(_selectedIndex),
),
bottomNavigationBar: Container(
decoration: BoxDecoration(
color: Colors.white,
boxShadow: [
BoxShadow(
blurRadius: 20,
color: Colors.black.withOpacity(.1),
)
],
),
child: SafeArea(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 15.0, vertical: 8),
child: GNav(
rippleColor: Colors.grey[300]!,
hoverColor: Colors.grey[100]!,
gap: 8,
activeColor: Colors.black,
iconSize: 24,
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
duration: Duration(milliseconds: 400),
tabBackgroundColor: Colors.grey[100]!,
color: Colors.black,
tabs: [
GButton(
icon: LineIcons.home,
text: 'Home',
),
GButton(
icon: LineIcons.heart,
text: 'Likes',
),
GButton(
icon: LineIcons.user,
text: 'Profile',
),
],
selectedIndex: _selectedIndex,
onTabChange: (index) {
setState(() {
_selectedIndex = index;
});
},
),
),
),
),
);
}
}
Your Home Class
class Home extends StatelessWidget {
const Home({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Text(
'Home',
);
}
}
Your Likes Class
class Likes extends StatelessWidget {
const Likes({
Key? key,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Text(
'Likes',
);
}
}
Your Profile Class
class Profile extends StatelessWidget {
const Profile({
Key? key,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Text(
'Profile',
);
}
}

For a better switch use IndexedStack:
class MainScreen extends StatefulWidget {
#override
_MainScreenState createState() => _MainScreenState();
}
class _MainScreenState extends State<MainScreen> {
int _page = 0;
final screens = [
Home(),
Likes(),
Profile()
];
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey[100],
bottomNavigationBar: GNav(
rippleColor: Colors.grey[300],
hoverColor: Colors.grey[100],
gap: 8,
activeColor: Colors.black,
iconSize: 24,
padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
duration: Duration(milliseconds: 400),
tabBackgroundColor: Colors.grey[100],
color: Colors.black,
tabs: [
GButton(
icon: LineIcons.home,
text: 'Home',
),
GButton(
icon: LineIcons.heart,
text: 'Likes',
),
GButton(
icon: LineIcons.user,
text: 'Profile',
),
],
selectedIndex: _page,
onTabChange: (index) {
setState(() {
_page = index;
});
},
),
body: IndexedStack(
index: _page,
children: screens,
),
);
}
}

Related

Flutter change AppBottomNavigation body by tapping on button on another state

I have an AppBottomNavigation for five different states. In the first state, HomeScreen, I have a button. By tapping on this button, the state is to be changed to the third element of the AppBottomNavigation.How exactly can I implement this? I have already tried several times to call the method "bottomTapped" with index 2 via ScannderDummy. Unfortunately without success.
app_bottom_navigation.dart
class AppBottomNavigation extends StatefulWidget {
#override
_AppBottomNavigationState createState() => _AppBottomNavigationState();
}
class _AppBottomNavigationState extends State<AppBottomNavigation> {
int _selectedIndex = 0;
List<dynamic> menuItems = [
...
];
PageController pageController = PageController(
initialPage: 0,
keepPage: true,
);
Widget buildPageView() {
return PageView(
controller: pageController,
onPageChanged: (index) {
pageChanged(index);
},
children: <Widget>[
HomeScreen(),
CategoryScreen(),
ScannerScreen(),
CategoryScreen(),
ProfileSettingsScreen(),
],
);
}
pageChanged(int index) {
setState(() {
_selectedIndex = index;
});
}
bottomTapped(int index) {
setState(() {
_selectedIndex = index;
pageController.jumpToPage(index);
});
}
#override
Widget build(BuildContext context) {
SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
statusBarColor: Colors.transparent,
statusBarIconBrightness: Brightness.dark));
return Scaffold(
bottomNavigationBar: BottomNavigationBar(
backgroundColor: Colors.white,
showUnselectedLabels: true,
unselectedItemColor: Colors.grey,
type: BottomNavigationBarType.fixed,
selectedLabelStyle: GoogleFonts.outfit(
textStyle:
TextStyle(height: 1.5, fontSize: 10, fontWeight: FontWeight.bold),
),
unselectedLabelStyle: GoogleFonts.outfit(
textStyle: TextStyle(
height: 1.5,
fontSize: 10,
),
),
items: menuItems.map((i) {
return BottomNavigationBarItem(
icon: (i['icon']),
activeIcon: (i['icon']),
label: i['label'],
);
}).toList(),
currentIndex: _selectedIndex,
selectedItemColor: primaryColor,
onTap: (index) {
bottomTapped(index);
},
),
body: buildPageView(),
);
}
}
scanner_dummy.dart (Element from home_screen.dart)
class ScannerDummy extends StatelessWidget {
final AppBottomNavigation bn = new AppBottomNavigation();
#override
Widget build(BuildContext context) {
return InkWell(
onTap: () {
},
child: Container(
margin:
EdgeInsets.only(top: 6, bottom: 28.0, left: 28.0, right: 28.0),
padding: EdgeInsets.symmetric(
horizontal: 16.0,
),
height: 125,
width: double.infinity,
decoration: BoxDecoration(
color: darkGrey,
borderRadius: BorderRadius.all(Radius.circular(15)),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Icon(
LineIcons.retroCamera,
color: Colors.white,
size: 35.0,
),
Text(
'Artikel scannen & verkaufen',
textAlign: TextAlign.right,
style: GoogleFonts.outfit(
textStyle: TextStyle(
color: Colors.white,
fontSize: 16,
height: 2,
)),
),
],
)),
);
}
}
Thank you very much for your help.
Play with this widget. I am using callback method.
class ItemB extends StatefulWidget {
final VoidCallback callback;
ItemB({Key? key, required this.callback}) : super(key: key);
#override
State<ItemB> createState() => _ItemBState();
}
class _ItemBState extends State<ItemB> {
#override
Widget build(BuildContext context) {
return Column(
children: [
Text("B"),
ElevatedButton(
onPressed: widget.callback,
child: Text("switch Tab"),
),
],
);
}
}
class HomeWidgetX extends StatefulWidget {
const HomeWidgetX({Key? key}) : super(key: key);
#override
State<HomeWidgetX> createState() => _HomeWidgetXState();
}
class _HomeWidgetXState extends State<HomeWidgetX> {
int currentTab = 0;
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: [
Text("A"),
ItemB(
callback: () {
setState(() {
currentTab = 0;
});
},
)
][currentTab]),
bottomNavigationBar: BottomNavigationBar(
currentIndex: currentTab,
onTap: (value) {
currentTab = value;
setState(() {});
},
items: const [
BottomNavigationBarItem(
icon: Icon(Icons.abc),
label: "",
),
BottomNavigationBarItem(
icon: Icon(Icons.ac_unit),
label: "",
),
],
),
);
}
}

Trying to create a method to control font size. Flutter App

I'm trying to create a font size control, the idea is that the user can change the font size of the entire app through the Slider, drag this bar and adjust it like 14px, 16px, 18px, 20px... minimum and maximum. I also read that the best way to make the changes on several screens will be using the provider, what is your opinion on this choice?
This is the starting code.
class Settings extends StatefulWidget {
const Settings({Key? key}) : super(key: key);
#override
State<Settings> createState() => _SettingsState();
}
class _SettingsState extends State<Settings> {
double _rating = 20;
#override
void initState() {
SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersive);
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
elevation: 0,
backgroundColor: Colors.transparent,
iconTheme: IconThemeData(color: Colors.blue[900]),
title: const Text(
'Settings',
style: TextStyle(
color: Colors.black,
),
),
),
body: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
ListTile(
title: Text('Button'),
trailing: Icon(
Icons.arrow_forward_ios,
color: Colors.blue,
),
onTap: () {
showModalBottomSheet<void>(
context: context,
builder: (BuildContext context) {
return Container(
height: 200,
color: Colors.white,
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'Change font',
style: TextStyle(
),
),
),
Slider(
value: _rating,
min: 0,
max: 28,
divisions: 4,
label: _rating.round().toString(),
onChanged: (newRating) {
setState(() => _rating = newRating);
},
),
],
),
),
);
}
);
},
),
],
),
);
}
}
I have created a provider example it might help you
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
void main() {
runApp(MultiProvider(providers: [
ChangeNotifierProvider(create: (_) => SliderValue()),
], child: MyApp()));
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: SizableText(),
);
}
}
class SliderValue with ChangeNotifier {
double _value = 5;
double get value => _value;
void increment(double val) {
_value = val;
notifyListeners();
}
}
class SizableText extends StatefulWidget {
const SizableText({Key? key}) : super(key: key);
#override
State<SizableText> createState() => _SizableTextState();
}
class _SizableTextState extends State<SizableText> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("AppBar")),
body: Center(
child: Column(
children: <Widget>[
Container(
margin: EdgeInsets.only(right: 10),
decoration: new BoxDecoration(
color: Colors.blue,
borderRadius: new BorderRadius.all(new Radius.circular(5.0)),
boxShadow: [
new BoxShadow(
color: Colors.black38,
offset: new Offset(0.0, 2.0),
blurRadius: 10)
]),
child: new Slider(
value: context.watch<SliderValue>().value,
activeColor: Colors.white,
inactiveColor: Colors.white,
onChanged: (double s) {
context.read<SliderValue>().increment(s);
},
divisions: 10,
min: 0.0,
max: 10.0,
),
),
Text1(text: 'Hello'),
Text1(text: 'Hi'),
],
),
),
);
}
}
class Text1 extends StatelessWidget {
Text1({this.text});
final String? text;
#override
Widget build(BuildContext context) {
return Text(text ?? '',
style: TextStyle(fontSize: 10 * context.watch<SliderValue>().value));
}
}
Basic idea is stored fonsize value in somewhere that Text can reach, state management will update the value of fonsize and notify to theres subscription. Im not using provider so im use an other state management is get to do this.
// ignore_for_file: prefer_const_constructors_in_immutables
import 'package:flutter/material.dart';
import 'package:get/get.dart';
class HomeController extends GetxController {
var fontSizeObx = RxDouble(12);
setFontsize(double value) => fontSizeObx.value = value;
}
class HomeRoute extends StatelessWidget {
HomeRoute({Key? key}) : super(key: key);
final controller = Get.put(HomeController());
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Obx(
() => Column(
children: [
Text(
'Hello world',
style: TextStyle(fontSize: controller.fontSizeObx.value),
),
Slider(
value: controller.fontSizeObx.value,
onChanged: controller.setFontsize,
divisions: 10,
min: 10.0,
max: 100.0,
)
],
),
),
),
);
}
}
You can try this
double _value = 5;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("AppBar")),
body: Center(
child: Column(
children: <Widget>[
Container(
margin: EdgeInsets.only(right: 10),
decoration: new BoxDecoration(
color: Colors.blue,
borderRadius: new BorderRadius.all(new Radius.circular(5.0)),
boxShadow: [new BoxShadow(color: Colors.black38,
offset: new Offset(0.0, 2.0), blurRadius: 10)]),
child: new Slider(
value: _value,
activeColor: Colors.white,
inactiveColor: Colors.white,
onChanged: (double s) {
setState(() {
_value = s;
});
},
divisions: 10,
min: 0.0,
max: 10.0,
),
),
Text("Hello World", style: TextStyle(fontSize: 10 * _value)),
],
),
),
);
}

Change appBar in for each button clicked in flutter

Is there any way that I can change AppBar's 'title:' that will be based to my BottomNavigationBar's button label? I am building an app where the navigation bar will call each classes' on button click,
Like this maybe?
appbar: AppBar(
title: SelectedIndex(label/tile),
),
Here's the source code:
import 'package:flutter/material.dart';
import 'BoosterCommunity_Page.dart';
import 'Diary_Page.dart';
import 'GradeTracker_Page.dart';
import 'CalendarView_Page.dart';
import 'QuotesPage.dart';
import 'ListView_Page.dart';
class HomePage extends StatefulWidget {
HomePage({Key? key}): super(key: key);
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
PageController _pageController = PageController();
List<Widget> _screens = [
QuotesPage(), ListViewPage(), CalendarViewPage(), GradeTrackerPage(), DiaryPage(), BoosterCommunityPage(),
];
void _onPageChanged(int index) {}
void _onItemsTapped(int selectedIndex) {
_pageController.jumpToPage(selectedIndex);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
//I want it to be implemented in this line
title: (BottomNavBar selected index title or label),
),
body: PageView(
controller: _pageController,
children: _screens,
onPageChanged: _onPageChanged,
physics: NeverScrollableScrollPhysics(),
),
bottomNavigationBar: BottomNavigationBar(
onTap: _onItemsTapped,
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home, color: Colors.grey,),
label: 'Home',
),
BottomNavigationBarItem(
icon: Icon(Icons.list, color: Colors.grey,),
label: 'Task List',
),
BottomNavigationBarItem(
icon: Icon(Icons.calendar_view_month, color: Colors.grey,),
label: 'Calendar View',
),
BottomNavigationBarItem(
icon: Icon(Icons.grade, color: Colors.grey,),
label: 'Grade Tracker',
),
BottomNavigationBarItem(
icon: Icon(Icons.book, color: Colors.grey,),
label: 'Diary Page',
),
BottomNavigationBarItem(
icon: Icon(Icons.business, color: Colors.grey,),
label: 'Booster Community',
),
],
),
drawer: Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: [
Container(
height: 100.0,
child: const DrawerHeader(
decoration: BoxDecoration(
color: Colors.orange,
),
child: Text('Sign in first'),
),
),
ListTile(
title: const Text('Account'),
onTap: () {
Navigator.pop(context);
},
),
ListTile(
title: const Text('Settings'),
onTap: () {
Navigator.pop(context);
},
),
ListTile(
title: const Text('Help and Support'),
onTap: (){
Navigator.pop(context);
},
),
],
),
),
);
}
}
Is it possible or is there an easy way? please let me know, thank you in advance.
Try this one, here I use currentPage to hold the index of the selected bottom navigation item and pageTitle to show the title on the app bar. Now whenever the user tap on the item in the bottom bar all you have to do is to update currentIndex and pageTitle by fetching the specific key at the index in the map bottomNavigateData.
import 'package:flutter/material.dart';
void main() =>
runApp(MaterialApp(debugShowCheckedModeBanner: false, home:
HomePage()));
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
static int currentPage = 0;
static Map<String, Icon> bottomNavigateData = {
'Home': const Icon(
Icons.home,
color: Colors.grey,
),
'Task List': const Icon(
Icons.list,
color: Colors.grey,
),
};
String pageTitle = bottomNavigateData.keys.first;
final PageController _pageController = PageController();
final List<Widget> _screens = [
QuotesPage(),
ListViewPage(),
];
void _onPageChanged(int index) {}
void _onItemsTapped(int selectedIndex) {
setState(() {
currentPage = selectedIndex;
pageTitle = bottomNavigateData.keys.elementAt(selectedIndex);
});
_pageController.jumpToPage(selectedIndex);
}
#override
Widget build(BuildContext context) {
List<BottomNavigationBarItem> navigations = [];
bottomNavigateData
.forEach((k, v) => navigations.add(BottomNavigationBarItem(
icon: v,
label: k,
)));
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text(pageTitle),
),
body: PageView(
controller: _pageController,
children: _screens,
onPageChanged: _onPageChanged,
physics: const NeverScrollableScrollPhysics(),
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: currentPage, onTap: _onItemsTapped, items: navigations),
drawer: Drawer(
child: ListView(
padding: EdgeInsets.zero,
children: [
Container(
height: 100.0,
child: const DrawerHeader(
decoration: BoxDecoration(
color: Colors.orange,
),
child: Text('Sign in first'),
),
),
ListTile(
title: const Text('Account'),
onTap: () {
Navigator.pop(context);
},
),
ListTile(
title: const Text('Settings'),
onTap: () {
Navigator.pop(context);
},
),
ListTile(
title: const Text('Help and Support'),
onTap: () {
Navigator.pop(context);
},
),
],
),
),
);
}
}
Widget QuotesPage() {
return Container(color: Colors.white, child: const Text("Page1"));
}
Widget ListViewPage() {
return Container(color: Colors.white, child: const Text("Page2"));
}
Yes, easily. Just define your NavigationBarItems in a variable, update selection index in onTap with setState, and set appBar title based on selection. Something like this:
import 'package:flutter/material.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 Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const HomePage(),
);
}
}
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
#override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
int _currentIndex = 0;
static const _navigationBarItems = <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Home',
),
BottomNavigationBarItem(
icon: Icon(Icons.message),
label: 'Message',
),
BottomNavigationBarItem(
icon: Icon(Icons.person),
label: 'Person',
),
];
static const List<Widget> _pages = <Widget>[
Text('home'),
Text('message'),
Text('person'),
];
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(_navigationBarItems[_currentIndex].label!),
),
body: Center(
child: _pages.elementAt(_currentIndex),
),
bottomNavigationBar: BottomNavigationBar(
items: _navigationBarItems,
currentIndex: _currentIndex,
selectedItemColor: Colors.amber[800],
onTap: (int index) {
setState(() {
_currentIndex = index;
});
},
),
);
}
}

How to achieve this result in flutter?

How to have the notch appear whenever a tab is selected in Flutter?
And how to animate the change by having the notch slide whenever another tab is selected?
Thank you for the help in advance
This is the workaround that I can do :
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
/// This Widget is the main application widget.
class MyApp extends StatelessWidget {
static const String _title = 'Flutter Code Sample';
#override
Widget build(BuildContext context) {
return MaterialApp(
title: _title,
home: MyStatefulWidget(),
);
}
}
class MyStatefulWidget extends StatefulWidget {
MyStatefulWidget({Key key}) : super(key: key);
#override
_MyStatefulWidgetState createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
int _selectedIndex = 0;
#override
Widget build(BuildContext context) {
return Scaffold(
body: Row(
children: <Widget>[
NavigationRail(
selectedIndex: _selectedIndex,
onDestinationSelected: (int index) {
setState(() {
_selectedIndex = index;
});
},
labelType: NavigationRailLabelType.selected,
destinations: [
NavigationRailDestination(
icon: Text("Food"),
label: Container(
width: 8,
height: 8,
decoration: BoxDecoration(
color: Colors.red,
shape: BoxShape.circle,
)),
),
NavigationRailDestination(
icon: Text("Bakery"),
label: Container(
width: 8,
height: 8,
decoration: BoxDecoration(
color: Colors.red,
shape: BoxShape.circle,
)),
),
NavigationRailDestination(
icon: Text("Drinks"),
label: Container(
width: 8,
height: 8,
decoration: BoxDecoration(
color: Colors.red,
shape: BoxShape.circle,
)),
),
],
),
VerticalDivider(thickness: 1, width: 1),
// This is the main content.
Expanded(
child: Center(
child: Text(
'selectedIndex: $_selectedIndex',
style: Theme.of(context).textTheme.headline4,
),
),
)
],
),
);
}
}
You could use NavigationRail for Side Bar. But I'm not sure how to make the notch, anyway I hope this can help you a bit

How to handle a one widget state from another widget state?

I am making a flutter application that have shopping cart. Right now, i am just working on a single functionality of it when we select a particular product, after increase or decrease its quantity then our cart doesnot show the quantity of that item on the cart immediately. we have to go to another widget then it update the count on cart.
Note: HomeScreen comprise of two stateful widget, one is bottom navigation bar which have cart and other icons along with other icons and their respective UI's and other one is Product screen which is showing all our products, and in my product screen i used listview and in its UI i used - and + icons to increase or decrease its quantity. I am sharing the code of the widget - and +(a small portion of product screen) on which i want to implement this functionality.
This is the video link to show
https://youtu.be/3qqVpmWguys
HomeScreen:
class HomeScreen extends StatefulWidget {
#override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
//static _HomeScreenState of(BuildContext context) => context.ancestorStateOfType(const TypeMatcher<_HomeScreenState>());
int _currentindex = 0;
var cart;
final List<Widget> children = [
ProductScreen(),
OrderScreen(),
CartScreen(),
AccountScreen(),
];
List<BottomNavigationBarItem> _buildNavigationItems() {
var bloc = Provider.of<CartManager>(context);
int totalCount = bloc.getCart().length;
setState(() {
totalCount;
});
return <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(
Icons.reorder,
size: 30,
color: Colors.white,
),
title: Text(
'Product',
style: TextStyle(fontSize: 15, color: Colors.white),
),
),
BottomNavigationBarItem(
icon: Icon(
Icons.add_alert,
size: 30,
color: Colors.white,
),
title: Text(
'Order',
style: TextStyle(fontSize: 15, color: Colors.white),
),
),
BottomNavigationBarItem(
icon: Stack(
children: <Widget>[
Icon(
Icons.shopping_cart,
size: 30,
color: Colors.white,
),
Positioned(
bottom: 12.0,
right: 0.0,
child: Container(
constraints: BoxConstraints(
minWidth: 20.0,
minHeight: 20.0,
),
decoration: BoxDecoration(
color: Colors.red,
borderRadius: BorderRadius.circular(10.0),
),
child: Center(
child: Text(
'$totalCount',
style: TextStyle(
fontSize: 12,
color: Colors.white,
fontWeight: FontWeight.bold,
),
),
),
),
)
],
),
title: Text(
'Cart',
style: TextStyle(fontSize: 15, color: Colors.white),
),
),
BottomNavigationBarItem(
icon: Icon(
Icons.lock,
size: 30,
color: Colors.white,
),
title: Text(
'Account',
style: TextStyle(fontSize: 15, color: Colors.white),
),
),
];
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
backgroundColor: Colors.white,
resizeToAvoidBottomPadding: true,
body: children[_currentindex],
bottomNavigationBar: BottomNavigationBar(
fixedColor: Colors.transparent,
backgroundColor: Colors.orange,
onTap: onNavigationTapbar,
currentIndex: _currentindex,
items: _buildNavigationItems(),
type: BottomNavigationBarType.fixed,
),
),
);
}
void onNavigationTapbar(int index) {
setState(() {
_currentindex = index;
});
}
}
ProductScreen incrementor or decrementor:
class TEProductIncrementor extends StatefulWidget {
var product;
TEProductIncrementor({
this.product,
});
#override
_TEProductIncrementorState createState() => new _TEProductIncrementorState();
}
class _TEProductIncrementorState extends State<TEProductIncrementor> {
int totalCount = 0;
#override
Widget build(BuildContext context) {
var cartmanager = CartManager();
void decrementsavecallback() {
// bloc.decreaseToCart(widget.ctlist);
//CartManager().updateToCart(totalCount.toString(), widget.ctlist);
setState(() {
if (totalCount > 0) {
totalCount--;
cartmanager.updateToCart(totalCount.toString(),widget.product);
}
});
}
void increasesavecallback() {
setState(() {
totalCount++;
cartmanager.updateToCart(totalCount.toString(),widget.product);
});
}
return Container(
margin: EdgeInsets.only(top: 8),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10), color: Colors.orange),
child: Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
IconButton(
iconSize: 30,
icon: new Icon(
Icons.remove,
),
onPressed: () {
decrementsavecallback();
},
),
Text(
totalCount.toString(),
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
IconButton(
iconSize: 30,
icon: new Icon(Icons.add),
onPressed: () {
increasesavecallback();
},
)
],
),
),
);
}
}
You can pass the entire function into a widget just implemented like below
class Parent extends StatefulWidget {
#override
_ParentState createState() => _ParentState();
}
class _ParentState extends State<Parent> {
#override
Widget build(BuildContext context) {
return Button(
(){
setState(() {
///define your logic here
});
}
);
}
}
class Button extends StatelessWidget {
final Function onTap;
Button(this.onTap);
#override
Widget build(BuildContext context) {
return FlatButton(
onPressed: onTap,
);
}
}
But if your project is pretty big then I will recommend you to use any state management libraries just like redux or mobx.
https://pub.dev/packages/mobx
You can use BLoC pattern for this,
Here is full answer and demo code that you can check.
Why not use keys?
Assign at both widget a GlobalKey and then, when you need to update that state you just need to call
yourGlobalKeyName.currentState.setState((){
//your code
});