I am trying to create a Bottom Navigation Bar with a button group in the middle. The 2 icons on either side of the button group will switch the displayed screen. The centered button group has 3 buttons which would act on the displayed screen. This is similar to the new Google Assistant bottom bar
.
I tried using the BottomNavigationBar with the centre item a custom widget. However the sizes of all the items end up equal. Any help creating this layout would be appreciated. Thanks.
This is the design I am trying to achieve
Here's what I have now:
#override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async => false,
child: Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.primary,
foregroundColor: Theme.of(context).colorScheme.secondary,
leading: IconButton(
icon: Image.asset(alInvertedIcon, width: 32, semanticLabel: "Home screen"),
onPressed: () {
push(const HomeScreen());
},
iconSize: 32,
),
title: Image.asset(alTextInv, width: 175),
centerTitle: true,
actions: [
IconButton(
icon: const Icon(Icons.person_outlined, semanticLabel: "User Profile"),
onPressed: () {
push(const ProfileScreen());
},
iconSize: 32,
)
],
),
body: bodyWidget,
bottomNavigationBar: BottomNavigationBar(
type: BottomNavigationBarType.fixed,
onTap: _onItemTapped,
showSelectedLabels: false,
showUnselectedLabels: false,
backgroundColor: Theme.of(context).colorScheme.secondary,
selectedItemColor: Theme.of(context).colorScheme.primary,
unselectedItemColor: Colors.grey,
currentIndex: _currentIndex,
items: [
const BottomNavigationBarItem(
icon: Icon(
Icons.camera_alt,
),
label: 'Visual',
),
BottomNavigationBarItem(
icon: SizedBox(
width: 300,
child: _actionPanel(),
),
label: 'Add',
),
const BottomNavigationBarItem(
icon: Icon(
Icons.chat,
),
label: 'Text',
),
],
),
),
);
}
Widget _actionPanel() {
return Material(
elevation: 1.0,
borderRadius: const BorderRadius.all(Radius.circular(25)),
child: Row(
children: <Widget>[
IconButton(
onPressed: () {},
icon: const Icon(
Icons.refresh,
),
),
IconButton(
onPressed: () {},
icon: const Icon(
Icons.mic,
),
),
IconButton(
onPressed: () {},
icon: const Icon(
Icons.camera,
),
),
],
),
);
}
Try using this way.
Widget _actionPanel() {
return Material(
elevation: 1.0,
borderRadius: BorderRadius.all(Radius.circular(25)),
child: Container(
padding: EdgeInsets.symmetric(vertical: 3),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
MaterialButton(
onPressed: () {},
shape: CircleBorder(),
minWidth: 0,
padding: EdgeInsets.all(5),
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
child: Icon(Icons.refresh),
),
MaterialButton(
onPressed: () {},
shape: CircleBorder(),
minWidth: 0,
padding: EdgeInsets.all(5),
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
child: Icon(Icons.mic),
),
MaterialButton(
onPressed: () {},
shape: CircleBorder(),
minWidth: 0,
padding: EdgeInsets.all(5),
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
child: Icon(Icons.camera),
),
],
),
),
);
}
Related
I want a docked bottom navigation bar in flutter where the item in the center is uplifted and fixed,
any idea how can I do that
this is the output that I want and I don't have any idea I can I do that
try adding floating action button in scaffold
Scaffold(
bottomNavigationBar: BottomAppBar(
child: Row(
children: [
IconButton(icon: Icon(Icons.menu), onPressed: () {}),
Spacer(),
IconButton(icon: Icon(Icons.search), onPressed: () {}),
IconButton(icon: Icon(Icons.more_vert), onPressed: () {}),
],
),
),
floatingActionButton:
FloatingActionButton(child: Icon(Icons.add), onPressed: () {}),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
),
See I have two options for you here (potentially three):
1. Create a mix of bottom-navigation-bar and floating-action-button
floatingActionButton: FloatingActionButton(
onPressed: () {},
shape:
RoundedRectangleBorder(borderRadius: BorderRadius.circular(15)),
child: Icon(Icons.video_call),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
bottomNavigationBar: BottomAppBar(
color: Colors.redAccent,
notchMargin: 5,
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
IconButton(
icon: Icon(
Icons.menu,
color: Colors.white,
),
onPressed: () {},
),
IconButton(
icon: Icon(
Icons.search,
color: Colors.white,
),
onPressed: () {},
),
IconButton(
icon: Icon(
Icons.print,
color: Colors.white,
),
onPressed: () {},
),
IconButton(
icon: Icon(
Icons.people,
color: Colors.white,
),
onPressed: () {},
),
],
),
),
pseudo second:
Create a notch in the bottom-navigation-bar :
bottomNavigationBar: BottomAppBar(
shape: shape: AutomaticNotchedShape(
RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(
top: Radius.circular(15),
),
),
RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(10)),
),
), // by adding this line in the above code
color: Colors.redAccent,
notchMargin: 5,
child: Row(
2. Use Stack BottomNavBar Combo :
Stack(
children: [
Align(
alignment: Alignment.bottomCenter,
child: BottomNavigationBar(
backgroundColor: Colors.transparent,
items: const [
BottomNavigationBarItem(
icon: Icon(
Icons.home,
color: Colors.white,
),
label: 'a',
backgroundColor: Colors.transparent),
BottomNavigationBarItem(
icon: Icon(Icons.search),
label: 'a',
backgroundColor: Colors.yellow),
BottomNavigationBarItem(
icon: Icon(Icons.person),
label: 'a',
backgroundColor: Colors.blue,
),
BottomNavigationBarItem(
icon: Icon(Icons.person),
label: 'a',
backgroundColor: Colors.blue,
),
],
type: BottomNavigationBarType.shifting,
selectedItemColor: Colors.black,
iconSize: 20,
elevation: 5),
),
Positioned(
top: height * 0.25,
left: width * 0.40,
child: FloatingActionButton(
onPressed: () {},
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(15)),
child: Icon(Icons.video_call),
),
),
],
),
),
),
],
),
Try below code:
Scaffold(
body: Container(),
floatingActionButton: FloatingActionButton(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
onPressed: () {},
tooltip: 'Increment',
child: Icon(Icons.video_camera_back),
elevation: 4.0,
backgroundColor: Colors.pink,
),
bottomNavigationBar: BottomAppBar(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Expanded(
child: IconButton(icon: Icon(Icons.home), onPressed: () {}),
),
Expanded(
child: IconButton(icon: Icon(Icons.show_chart), onPressed: () {}),
),
Expanded(child: new Text('')),
Expanded(
child: IconButton(icon: Icon(Icons.tab), onPressed: () {}),
),
Expanded(
child: IconButton(icon: Icon(Icons.settings), onPressed: () {}),
),
],
),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
)
Result->
Refer persistent_bottom_nav_bar also and refer bottom_nav_bar also for more design of
I need to add 3 buttons at the bottom, all buttons need in one row top of the body content
I need to add 3 buttons at the bottom of app
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('WinLife'),
elevation: 10,
backgroundColor: const Color(0XFF82B58D),
leading: Container(
padding: EdgeInsets.all(5),
child: Image.asset('assets/images/logo/WinLife.png'),
),
actions: <Widget>[
IconButton(
icon: Icon(
Icons.favorite,
color: Colors.white,
),
onPressed: () {},
),
IconButton(
icon: Icon(
Icons.settings,
color: Colors.white,
),
onPressed: () {},
)
],
),
body: ListView.builder(
itemBuilder: (BuildContext ctx, int index) {
return Padding(
padding: EdgeInsets.all(10),
child: Card(
shadowColor: const Color(0XFF82B58D),
shape: Border.all(
color: const Color(0XFF82B58D),
width: 2,
),
elevation: 50,
color: const Color(0XFF82B58D),
child: Column(
children: <Widget>[
Image.asset(imgList[index]),
SizedBox(
height: 200,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: const <Widget>[
Icon(
Icons.favorite,
color: Colors.white,
size: 25,
),
Icon(
Icons.download,
color: Colors.white,
size: 25,
),
Icon(
Icons.share,
color: Colors.white,
size: 25,
),
],
),
],
),
),
);
},
itemCount: imgList.length,
),
);
}
There is a property called persistentFooterButtons in scaffold widget. It is using to show widgets to the screen footer. you can add any type of widgets inside to that. below some example code with output image FYR
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('WinLife'),
elevation: 10,
backgroundColor: const Color(0XFF82B58D),
leading: Container(
padding: const EdgeInsets.all(5),
child: Image.asset('assets/images/logo/WinLife.png'),
),
actions: <Widget>[
IconButton(
icon: const Icon(
Icons.favorite,
color: Colors.white,
),
onPressed: () {},
),
IconButton(
icon: const Icon(
Icons.settings,
color: Colors.white,
),
onPressed: () {},
)
],
),
body: Container(),
persistentFooterButtons: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
persistentFooterButtonWidget(),
persistentFooterButtonWidget(),
persistentFooterButtonWidget(),
],
),
],
);
}
persistentFooterButtonWidget() {
return OutlinedButton.icon(
label: const Text("Book now", style: TextStyle(color: Colors.black)),
onPressed: () {},
icon: const Icon(Icons.library_add_check_sharp, color: Colors.black, size: 20.0),
style: ButtonStyle(
fixedSize: MaterialStateProperty.all(
const Size(170.0, 40.0),
),
shape: MaterialStateProperty.all(RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30),
)),
side: MaterialStateProperty.all(
BorderSide(color: Colors.orange.shade200, width: 2)),
overlayColor: MaterialStateProperty.resolveWith<Color?>(
(Set<MaterialState> states) {
if (states.contains(MaterialState.hovered)) {
return Colors.orange.shade200;
}
if (states.contains(MaterialState.pressed)) {
return Colors.orange.shade200;
}
return null; // Defer to the widget's default.
}),
),
);
}
I want my floatingActionButton to stay like this when using persistentFooterButtons
If I add persistentFooterButtons, it becomes like this, but I want it lower and docked
This is the stateful widget with the bottom bar:
class Main extends StatefulWidget {
const Main({Key? key}) : super(key: key);
#override
State<Main> createState() => _MainState();
}
class _MainState extends State<Main> {
int selectedIndex = 0;
static User user = FirebaseAuth.instance.currentUser!;
final screens = [
const Home(),
const Search(),
const Library(),
Account(user: user),
];
#override
Widget build(BuildContext context) {
return Scaffold(
persistentFooterButtons: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.center,
children: const [
IconButton(
iconSize: 35,
icon: Icon(Icons.play_arrow),
onPressed: null,
),
Text("Some data over hereSome data "),
IconButton(
icon: Icon(Icons.favorite),
onPressed: null,
)
],
)
],
floatingActionButton: FloatingActionButton(
onPressed: () {},
child: const FittedBox(child: PlayButton()),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
resizeToAvoidBottomInset: false,
bottomNavigationBar: BottomAppBar(
shape: const CircularNotchedRectangle(),
notchMargin: 5,
color: Colors.red,
child: BottomNavigationBar(
backgroundColor: Colors.transparent,
type: BottomNavigationBarType.fixed,
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(
IconlyLight.home,
color: Colors.white,
),
activeIcon: Icon(
IconlyBold.home,
color: Colors.white,
shadows: [
BoxShadow(
blurRadius: 30,
color: Colors.white,
),
],
),
label: 'Home',
),
BottomNavigationBarItem(
icon: Icon(
IconlyLight.search,
color: Colors.white,
),
activeIcon: Icon(
IconlyBold.search,
color: Colors.white,
shadows: [
BoxShadow(
blurRadius: 30,
color: Colors.white,
),
],
),
label: 'Search',
),
BottomNavigationBarItem(
icon: Icon(
Iconsax.music_library_2,
color: Colors.white,
),
activeIcon: Icon(
Iconsax.music_library_25,
color: Colors.white,
shadows: [
BoxShadow(
blurRadius: 30,
color: Colors.white,
),
],
),
label: 'Library',
),
BottomNavigationBarItem(
icon: Icon(
IconlyLight.profile,
color: Colors.white,
),
activeIcon: Icon(
IconlyBold.profile,
color: Colors.white,
shadows: [
BoxShadow(
blurRadius: 30,
color: Colors.white,
),
],
),
label: 'Account',
),
],
currentIndex: selectedIndex,
unselectedItemColor: Colors.white,
selectedItemColor: Colors.white,
onTap: (index) => setState(() => selectedIndex = index),
),
),
body: IndexedStack(
index: selectedIndex,
children: screens,
),
);
}
}
The key elements are
persistentFooterButtons: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.center,
children: const [
IconButton(
iconSize: 35,
icon: Icon(Icons.play_arrow),
onPressed: null,
),
Text("Some data over hereSome data "),
IconButton(
icon: Icon(Icons.favorite),
onPressed: null,
)
],
)
],
floatingActionButton: FloatingActionButton(
onPressed: () {},
child: const FittedBox(child: PlayButton()),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
I ended up pushing the FAB down using a Stack with Positioned
floatingActionButton: Stack(
alignment: Alignment.bottomCenter,
clipBehavior: Clip.none,
children: [
Positioned(
bottom: 5,
child: FloatingActionButton(
onPressed: () {},
),
),
],
),
i'm getting a bug where button click animation always show behind the stack
bottomNavigationBar: Stack(
children: [
BottomNavigationBar(
type: BottomNavigationBarType.fixed,
items: [
BottomNavigationBarItem(...),
BottomNavigationBarItem(...),
BottomNavigationBarItem(...),
// Imitate an invisible icon
BottomNavigationBarItem(
icon: const Icon(Icons.add_circle, size: 0),
title: const Text(''),
),
],
currentIndex: _selectedIndex,
fixedColor: Colors.indigo,
onTap: _onItemTapped,
iconSize: 24,
),
Positioned(
right: 32.0,
top: 8.5,
child: CircleAvatar(
child: IconButton(
splashColor: Colors.green,
icon: Icon(Icons.add),
onPressed: () {},
),
),
)
],
),enter image description here
wrap your icon button with the Material widget
Material(
borderRadius: BorderRadius.circular(4),
color: Colors.grey.withOpacity(0.5),
child: InkWell(
borderRadius: BorderRadius.circular(4),
radius: 25,
onTap: ()=>Navigator.pop(context),
splashColor: Colors.grey,
highlightColor: Colors.grey,
child: Container(
width: 34,
height: 34,
child: Icon(
Icons.arrow_back,
color: Colours.colorPrimary,
size: 24,
),
),
))
it should work
How to make this arrow icon in the center of the button
it's see the edge of icon is the center of icon, and I want make flutter see the center of icon is the center of icon
for more explain:
my code:
AppBar(
backgroundColor: Colors.transparent,
leading:
// Here the code of the button
SizedBox(
height: getProportionateScreenHeight(20),
width: getProportionateScreenWidth(10),
child: Padding(
padding: EdgeInsets.all(8),
child: FlatButton(
padding: EdgeInsets.zero,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
color: Colors.white,
onPressed: () {
Navigator.pop(context);
},
child: Center(
child: Icon(
Icons.arrow_back_ios,
),
),
),
),
),
// ....
actions: [
IconButton(
icon: Icon(
Icons.favorite,
color: favFlag ? Colors.red : Colors.red[100],
),
onPressed: () {
setState(() {
favFlag = !favFlag;
});
},
),
],
);
And it's was working with me before last upgrade.
I think there is some problem with the use of your height and width factor for SizedBox. I used simple values for these and it is working fine.
In fact, I removed the SizedBox widget and there was no such effect. I have attached the pic after the code as well :)
appBar: AppBar(
backgroundColor: Colors.transparent,
leading:
// Here the code of the button
SizedBox(
height: 20,
width: 20,
child: Padding(
padding: EdgeInsets.all(8),
child: FlatButton(
padding: EdgeInsets.zero,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
color: Colors.white,
onPressed: () {
// Navigator.pop(context);
},
child: Center(
child: Icon(
Icons.arrow_back_ios,
),
),
),
),
),
actions: [
IconButton(
icon: Icon(
Icons.favorite,
color: favFlag ? Colors.red : Colors.red[100],
),
onPressed: () {
setState(() {
favFlag = !favFlag;
});
},
),
],
),
Output:
My solution
AppBar(
backgroundColor: Colors.transparent,
// Here the code of the button
leading: Padding(
padding: EdgeInsets.all(8),
child: FlatButton(
padding: EdgeInsets.zero,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
color: Colors.white,
onPressed: () {
Navigator.pop(context);
},
child: Stack(
alignment: Alignment.center,
children: [
Positioned.directional(
textDirection: Directionality.of(context),
end: 3,
child: Icon(
Icons.arrow_back_ios,
),
),
],
),
),
),
// ....
actions: [
IconButton(
icon: Icon(
Icons.favorite,
color: favFlag ? Colors.red : Colors.red[100],
),
onPressed: () {
setState(() {
favFlag = !favFlag;
});
AdsService.listByPagination();
},
),
],
);
I've positioned it to center manually, so I prefer if there an another clean short solution.