I am using curved bottom navigation bar and I want everytime to have an option selected as default just for the look(e.g Home button) although I want the user to have the ability to tap it.But when I select as default the user hasn't. What can I do?
class MainClass extends StatelessWidget{
#override
Widget build(BuildContext context) {
return Scaffold(
body: MyRV(),
bottomNavigationBar:CurvedNavigationBar(
height: 50,
index: 1,
color: Colors.orange,
buttonBackgroundColor: Colors.white,
backgroundColor: Colors.blueAccent,
items: <Widget>[
Icon(Icons.arrow_back, size: 20,color: Colors.blueAccent,),
Icon(Icons.home, size: 20,color: Colors.blueAccent,),
Icon(Icons.contact_mail, size: 20,color: Colors.blueAccent,),
],
animationDuration:Duration(
milliseconds: 1000
),
animationCurve: Curves.linearToEaseOut,
onTap: (index) {
if (index==1)
Navigator.of(context).push(MaterialPageRoute(builder: (BuildContext context){return
b_afandou();})
);
},
),
);
}
}
You have already implement that. Here index: 1 means you have set default button as the button corresponding to index 1.
Check this for more details.
Corrected way to implement curved navigation bar
I noticed that the question is still getting viewed, so I would like to tell you that it was just a bug I guess. Cause I didn't do anything and it started working just fine.
The issue is you are navigation to different route instead of view. Use
body:[yourWidget1,yourWidget2,yourWidget3][_currentIndex]
class MainClass extends StatefulWidget {
#override
State<MainClass> createState() => _MainClassState();
}
class _MainClassState extends State<MainClass> {
int _currentIndex = 1;
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: [///this will hold your three page
Text("First View "),
Text("second/middle View "),
Text("Thired View "),
][_currentIndex],
),
bottomNavigationBar: CurvedNavigationBar(
height: 50,
index: _currentIndex,
color: Colors.orange,
buttonBackgroundColor: Colors.white,
backgroundColor: Colors.blueAccent,
items: <Widget>[
Icon(
Icons.arrow_back,
size: 20,
color: Colors.blueAccent,
),
Icon(
Icons.home,
size: 20,
color: Colors.blueAccent,
),
Icon(
Icons.contact_mail,
size: 20,
color: Colors.blueAccent,
),
],
animationDuration: Duration(milliseconds: 1000),
animationCurve: Curves.linearToEaseOut,
onTap: (index) {
setState(() {
_currentIndex = index;
});
},
),
);
}
}
More about curved_navigation_bar
Related
I have a homepage that includes an AppBar a bottomnavbar and a body to which I pass a list of widgets (pages) I want the navbar to navigate to when I click on its icons. I want to be able to display my bottomnavbar even in pages that are not included in the list .
Example when I click on a list tile it takes me to another details page , my navbar disappears I want the whole home page (appbar, bottomnavbar,...) to be static throughout the whole app without having to call each component on its own in my pages just like instagram style.
Here's my home page
class Home extends StatefulWidget {
const Home({Key? key}) : super(key: key);
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
#override
Widget build(BuildContext context) {
var pages = [
MyQrqc(),
NoDataUI(),
];
int index = 0;
var _appPageController = PageController();
return SafeArea(
child: Scaffold(
resizeToAvoidBottomInset: false,
appBar: PreferredSize(
preferredSize: Size.fromHeight(70.0), child: CustomAppBar()),
body: Container(
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/images/bg.png"),
fit: BoxFit.cover,
),
),
child: PageView(
children: pages,
onPageChanged: (index) {
setState(() {
index = index;
});
},
controller: _appPageController,
),
),
bottomNavigationBar: ClipRRect(
borderRadius: const BorderRadius.only(
topLeft: Radius.circular(17.0),
topRight: Radius.circular(17.0),
),
child: BottomAppBar(
clipBehavior: Clip.antiAlias, //bottom navigation bar on scaffold
color: Colors.transparent,
shape: CircularNotchedRectangle(), //shape of notch
notchMargin:
5, //notche margin between floating button and bottom appbar
child: Mainmenu(currentIndex: index, appPageController: _appPageController,),
),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
floatingActionButton: FloatingActionButton(
backgroundColor: kPrimaryLightColor,
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => MyQrqc()),
);
},
child: const Icon(Icons.add),
),
),
);
}
}
and this is my main menu page :
import 'package:deepnrise/Screens/qrqc/mes_qrqc_view.dart';
import 'package:deepnrise/constants/colors.dart';
import 'package:deepnrise/services/auth_services.dart';
import 'package:deepnrise/utils/size_config.dart';
import 'package:flutter/material.dart';
import 'package:deepnrise/services/settings/settings_service.dart';
import 'package:flutter_svg/flutter_svg.dart';
class Mainmenu extends StatefulWidget {
int currentIndex = 0;
var appPageController = PageController();
Mainmenu({Key? key, required this.currentIndex,required this.appPageController}) : super(key: key);
#override
CustomNavBar createState() => CustomNavBar();
}
class CustomNavBar extends State<Mainmenu> {
#override
Widget build(BuildContext context) {
setBottomBarIndex(index) {
setState(() {
widget.currentIndex = index;
});
widget.appPageController.animateToPage(index,
duration: Duration(milliseconds: 500), curve: Curves.ease);
}
SizeConfig.init(context);
return Container(
decoration: const BoxDecoration(
gradient: LinearGradient(
colors: [kPrimaryColor, kPrimaryLightColor],
begin: Alignment.topLeft,
end: Alignment.topRight,
stops: [0.1, 0.8],
tileMode: TileMode.clamp,
),
),
child: Wrap(
//children inside bottom appbar
alignment: WrapAlignment.spaceAround,
children: <Widget>[
const SizedBox(
width: 30,
),
IconButton(
icon: Image.asset("assets/icons/menuIcon2.png"),
onPressed: () {
setBottomBarIndex(0);
},
),
const SizedBox(
width: 20,
),
IconButton(
icon: Image.asset("assets/icons/menuIcon1.png"),
onPressed: () {
setBottomBarIndex(1);
},
),
const SizedBox(
width: 50,
),
IconButton(
icon: const Icon(
Icons.person,
color: Colors.white,
),
onPressed: () {
setBottomBarIndex(2);
},
),
const SizedBox(
width: 20,
),
IconButton(
icon: Image.asset("assets/icons/menuIcon3.png"),
onPressed: () {
setBottomBarIndex(3);
},
),
const SizedBox(
width: 20,
),
],
),
);
}
}
Here, First you need to create one file for BottomNavigationBar,
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
int _selectedIndex = 0;
//For changing the screen
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;
});
}
//This is a screens list which you want to navigate through BottomNavigationBar
final List<Widget> _children = [
const HomeScreen(),
const ProfileScreen()
];
#override
Widget build(BuildContext context) {
return Scaffold(
body: _children[_selectedIndex],
bottomNavigationBar: BottomNavigationBar(
iconSize: 32.0,
showSelectedLabels: true,
showUnselectedLabels: true,
selectedItemColor: Colors.white,
unselectedItemColor: Colors.white54,
currentIndex: _selectedIndex,
backgroundColor: Colors.black,
type: BottomNavigationBarType.fixed,
items: const [
BottomNavigationBarItem(
label: "Home",
icon: Icon(Icons.list),
),
BottomNavigationBarItem(
label: "Profile",
icon: Icon(Icons.person),
),
],
onTap: _onItemTapped,
),
);
}
}
Then, You can create another screens like HomeScreen, ProfileScreen etc.
So, By using this code HomePage to be static throughout the whole app without having to call each component in any screen.
To show the bottom navbar on all screens, one way is to use PageView with the bottom navbar. Another way is to use persistent_bottom_nav_bar
I am making a flutter app and i am working on the bottom navigation bar and i want to know if i can make the buttons to redirect the user to a new page UI from the app.I used this 'package:bubble_bottom_bar/bubble_bottom_bar.dart' and i don't know how to cal currentIndex = 1 ,2,3,4 to redirect to a new page when the user pressed the icon. I tried to add to my BubbleBottomBarItem a onPressed action but it doesn't work.
This is the code that i am using
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:tariffo/favoriteProviders.dart';
import 'package:tariffo/messages_list.dart';
import 'package:bubble_bottom_bar/bubble_bottom_bar.dart';
import 'HomePage.dart';
class BarDetail extends StatefulWidget {
#override
_BarDetailState createState() => _BarDetailState();
}
class _BarDetailState extends State<BarDetail> {
int currentIndex;
#override
void initState() {
super.initState();
currentIndex = 0;
}
changePage(int index) {
setState(() {
currentIndex = index;
});
}
#override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.only(top: MediaQuery.of(context).size.height * 0.8),
child: BubbleBottomBar(
opacity: 0.2,
backgroundColor: Colors.white,
borderRadius: BorderRadius.vertical(top: Radius.circular(16.0)),
currentIndex: currentIndex,
hasInk: true,
inkColor: Colors.black12,
hasNotch: true,
fabLocation: BubbleBottomBarFabLocation.end,
onTap: changePage,
items: <BubbleBottomBarItem>[
BubbleBottomBarItem(
backgroundColor: Colors.red,
icon: Icon(Icons.dashboard, color: Colors.black),
activeIcon: Icon(Icons.dashboard, color: Colors.red),
title: Text("Home")),
BubbleBottomBarItem(
backgroundColor: Colors.red,
icon: Icon(Icons.favorite_border, color: Colors.black),
activeIcon: Icon(Icons.dashboard, color: Colors.red),
title: Text("Saved")),
BubbleBottomBarItem(
backgroundColor: Colors.red,
icon: Icon(Icons.search, color: Colors.black),
activeIcon: Icon(Icons.dashboard, color: Colors.red),
title: Text("Search")),
BubbleBottomBarItem(
backgroundColor: Colors.red,
icon: Icon(Icons.send, color: Colors.black),
activeIcon: Icon(Icons.dashboard, color: Colors.red),
title: Text("Messages")),
],
),
);
}
}
and this are the pages that i want the buttons to open : FavoriteProviders(),MessageList()
Another way to go about it is by using PageView, create a PageController and assign it to the property of PageView called controller.
The controller - PageController _controller = PageController();
The PageView itself
PageView(
controller: _controller;
children: <Widget>[
FavoriteProviders(),
MessageList()
]
)
So FavoriteProviders() is now index 0, and MessageList() is now index 1
You can use one of these in the onTap to navigate to that page
_controller.jumpToPage(index) or
controller.animateToPage(index, duration: Duration(milliseconds: 500), curve: Curves.easeIn)
Pass in whatever you want for the duration and curve.
You should have something like this:
A list of pages:
final List<Widget> _pages = [
FavoriteProviders(),
MessageList()
];
A Scaffold where the body: _pages[currentIndex],
#override
Widget build(BuildContext context) {
return Scaffold(
bottomNavigationBar: _bubbleBottomNavBar(),
body: _pages[currentIndex],
)
}
where _bubbleBottomNavBar() is your bottom bar.
OR
Replace on onTap function with:
BubbleBottomBar(
opacity: 0.2,
backgroundColor: Colors.white,
borderRadius: BorderRadius.vertical(top: Radius.circular(16.0)),
currentIndex: currentIndex,
hasInk: true,
inkColor: Colors.black12,
hasNotch: true,
fabLocation: BubbleBottomBarFabLocation.end,
onTap: (index) {
if(index == 1)
Navigator.push(
context,
MaterialPageRoute(builder: (context) => FavoriteProviders()),
);
if (index == 2)
Navigator.push(
context,
MaterialPageRoute(builder: (context) => MessageList()),
);
},
items: <BubbleBottomBarItem>[
[...]
]
)
There are five navigation items in total and the widths are 154,153,154,153,154. I know it's kind of strange but the UI design is like this. As for this I guess I cannot use any Widget about navigator in the flutter lib.
Each item contains an icon and a text as usual but the distance between the two should be set exactly. I don't know if it can be set in flutter widget bottomNavigatorBar.
Commonly, the color of the icon, text and the background will change when selected.
What I have done: I created a widget and add it to the bottom of every pages. As you can imagine, when jumping to a new page, the navigation bar will re-render. That is not the same as we use in our mobile phones.
I have found some articles and blogs, but still can't solve my problem. Is there any reference?
You can use the below code and redirect this page into main.dart and can use test and icon also.
class nav extends StatefulWidget {
#override
_navState createState() => _navState();
}
class _navState extends State<nav> {
int tabIndex = 0;
List<Widget> listScreens;
#override
void initState() {
ScreenUtil.init(width: 375, height: 812);
super.initState();
listScreens = [
Home(),
Treatments(),
Request(),
Appointments(),
Menu(),
];
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: listScreens[tabIndex],
bottomNavigationBar: new Theme(
data: Theme.of(context).copyWith(
canvasColor: Color(0xFF320151),
primaryColor: Color(0xFF320151)),
child: BottomNavigationBar(
backgroundColor: Color(0xFF38095c),
selectedItemColor: Color(0xFFe34fd1),
unselectedItemColor: Color(0xFF510382),
currentIndex: tabIndex,
onTap: (int index) {
setState(() {
tabIndex = index;
});
},
items: [
BottomNavigationBarItem(
title: Text(""),
icon: Container(
width: 154, child: Center(child: Icon(AntDesign.home))),
),
BottomNavigationBarItem(
title: Text(""),
icon: Container(
width: 153,
child: Center(
child: Icon(MaterialCommunityIcons.medical_bag))),
),
BottomNavigationBarItem(
title: Text(""),
icon: Container(
width: 154,
child: Center(child: Icon(Fontisto.share_a))),
),
BottomNavigationBarItem(
title: Text(""),
icon: Container(
width: 153,
child: Center(child: Icon(AntDesign.calendar))),
),
BottomNavigationBarItem(
title: Text(""),
icon: Container(
width: 154,
child: Center(child: Icon(Ionicons.ios_person))),
),
]),
)),
);
}
}
My Home Screen is a Scaffold with a list of Dismissible widgets at its body. The child of each Dismissible is a custom widget I created, named Box. I have a FloatingActionButton that takes me to a new screen where I can add more Boxes to the list. (Each Box receive a String as an argument, that is used as its title).
I want the method onDismissed to show a SnackBar with the text "(Title of the box) excluded". However, this is not working as expected. The problem is that it always displays the title of the last box included, and not the title of the one I just dismissed. For example, if I add a Box named "Box 1", and then a Box named "Box 2", and then I dismiss the "Box 1", the snackbar will say "Box 2 excluded".
What am I doing wrong?
Here is the relevant code:
import 'package:flutter/material.dart';
import 'box.dart';
import 'addCounter.dart';
class Home extends StatefulWidget {
#override
HomeState createState() => HomeState();
}
class HomeState extends State<Home> {
List<String> lista;
void incrementLista(String novoItem) {
print('$lista');
setState(() {
lista.add(novoItem);
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Counters'),
backgroundColor: Colors.black,
),
body: ListView.builder(
itemCount: lista.length,
itemBuilder: (context, index) {
return Dismissible(
background: Container(color: Colors.grey[800], child: Icon(Icons.delete, color: Colors.grey[100])),
key: Key(lista[index]),
onDismissed: (direction) {
setState(() {
lista.removeAt(index);
});
Scaffold.of(context).showSnackBar(
SnackBar(content: Text(lista[index] + ' excluded.')));
},
child: Box(lista[index]));
},
),
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.grey[1000],
onPressed: () {
//Navega para tela de adicionar tarefa
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => AddCounter(f: incrementLista)));
},
child: Icon(Icons.add, color: Colors.white)),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
bottomNavigationBar: BottomNavigationBar(
//backgroundColor: Colors.grey[50],
unselectedItemColor: Colors.grey[700],
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(Icons.list),
title: Text('List'),
),
BottomNavigationBarItem(
icon: Icon(Icons.insert_chart),
title: Text('Chart'),
),
],
// currentIndex: _selectedIndex,
selectedItemColor: Colors.blue,
//onTap: _onItemTapped,
),
);
}
}
And here is the code of the addCounter.dart:
import 'package:flutter/material.dart';
class AddCounter extends StatefulWidget {
final Function f;
AddCounter({#required this.f});
#override
_AddCounterState createState() => _AddCounterState();
}
class _AddCounterState extends State<AddCounter> {
final myController = TextEditingController();
#override
void dispose() {
myController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Add a counter'),
backgroundColor: Colors.blue,
),
body: Column(children: [
Padding(
padding: EdgeInsets.all(15),
child: TextField(
controller: myController,
decoration: InputDecoration(
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.blue, width: 2)),
hintText: 'Type a name for the counter'),
),
),
RaisedButton(
color: Colors.green,
onPressed: () {
widget.f(myController.text);
Navigator.pop(context);
},
child: Text(
'Save',
style: TextStyle(color: Colors.white),
),
)
]));
}
}
I think the problem is that you first remove the item of the list. When you show the SnackBar the item is already removed so you can't access it in the list. So I would suggest to first show the Snackbar and then remove the item.
Like this: (In your itemBuilder)
return Dismissible(
background: Container(color: Colors.grey[800], child: Icon(Icons.delete,
color: Colors.grey[100])),
key: Key(lista[index]),
onDismissed: (direction) {
Scaffold.of(context).showSnackBar(
SnackBar(content: Text(lista[index] + ' excluded.')));
setState(() {
lista.removeAt(index);
});
},
child: Box(lista[index]));
},
I have a BottomNavigationBar which I need to add only one centralized button inside, but I am getting this error:
'package:flutter/src/material/bottom_navigation_bar.dart': Failed assertion: line 191 pos 15: 'items.length >= 2': is not true.
which is logical as the flutter's source code has this condition:
//..
assert(items.length >= 2),
So, here's my code, is there a workaround for this using BottomNavigationBar to keep the code clean?
BottomNavigationBar(
items: <BottomNavigationBarItem>[
buildBottomNavigationBarItem(
iconData: Icons.close,
),
// AN ERROR AFTER COMMENTING THIS:
// buildBottomNavigationBarItem(
// iconData: Icons.open,
// ),
],
),
BottomNavigationBarItem buildBottomNavigationBarItem(
{IconData iconData, String title = ''}
) {
return BottomNavigationBarItem(
icon: Icon(
iconData,
color: Theme.of(context).accentColor,
size: 0.04 * _deviceHeight,
),
title: Text(
title,
),
);
}
thanks
You can't use BottomNavigationBar but instead of it you can create your own widget and pass it into the bottomNavigationBar parameter.
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(primarySwatch: Colors.blue),
home: Scaffold(
body: SafeArea(
child: Text('Hi'),
),
bottomNavigationBar: Container(
height: 60,
color: Colors.black12,
child: InkWell(
onTap: () => print('tap on close'),
child: Padding(
padding: EdgeInsets.only(top: 8.0),
child: Column(
children: <Widget>[
Icon(
Icons.close,
color: Theme.of(context).accentColor,
),
Text('close'),
],
),
),
),
),
),
);
}
}
If the new, custom bottom navigation bar overlaps with the phone's OS GUI, you can wrap the InkWell with a SafeArea widget.
You can change the assert(items.length >= 2), to the length you want in the bottom navigation bar if you want to have three items turn the assert(items.length >= 2), to assert(items.length >= 3),