Custom bottom navigation bar notch problem in iphone 12 mini - ios

How to make custom navigation bar like default navigation bar to adopt notch problem
Code:
Scaffold(
floatingActionButtonLocation: FloatingActionButtonLocation
.startDocked, //specify the location of the FAB
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.blue,
onPressed: () {
print('OK');
},
tooltip: "start FAB",
child: Container(
height: 60,
margin: EdgeInsets.all(15.0),
child: Icon(Icons.add),
),
elevation: 4.0,
),
bottomNavigationBar: BottomAppBar(
child: Container(
color: Colors.lightBlue,
height: 60,
),
));

This is how I resolved it but here I am not going to used bottomNavigationBar Widget
Scaffold(
floatingActionButtonLocation: FloatingActionButtonLocation
.startDocked, //specify the location of the FAB
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.blue,
onPressed: () {
print('OK');
},
tooltip: "start FAB",
child: Container(
height: 60,
margin: EdgeInsets.all(15.0),
child: Icon(Icons.add),
),
elevation: 4.0,
),
bottomNavigationBar: BottomAppBar(
color: Colors.blue,
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
color: Colors.lightBlue,
height: 50,
),
],
),
));

please try safearea widget its really helpfull
import 'package:flutter/material.dart';
class BaseScaffold extends StatelessWidget {
Widget child;
BaseScaffold({Key? key, required this.child}) : super(key: key);
#override
Widget build(BuildContext context) {
return SafeArea(
child:your widget,
);
}
}

Related

How to Make Two Floating Action Button in Flutter?

Created counter app with one floating action button.
If i want to add one more button for reset the counter, where can i add second floating action button at bottom bar?
Also i have to add any method in void section or is there any reset counter function available?
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Counter App',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Counter App'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Text('You have pressed the button $_counter times.'),
),
bottomNavigationBar: BottomAppBar(
child: Container(
height: 50.0,
),
),
floatingActionButton: FloatingActionButton(
onPressed: () => setState(() {
_counter++;
}),
tooltip: 'Increment Counter',
child: Icon(Icons.add),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
);
}
}
floatingActionButton property on Scaffold widget do not need to take FloatingActionButton widget necessarily. It can also take Column or Row widgets.
Below, I'm sharing my Scaffold widget example with two floating action buttons on top of each other.
return Scaffold(
appBar: AppBar(
title: Text(""),
),
body: SingleChildScrollView(/*...*/),
floatingActionButton: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
FloatingActionButton(
child: Icon(
Icons.delete
),
onPressed: () {
//...
},
heroTag: null,
),
SizedBox(
height: 10,
),
FloatingActionButton(
child: Icon(
Icons.star
),
onPressed: () => _someFunc(),
heroTag: null,
)
]
)
);
You can use the flutter_speed_dial package: https://pub.dartlang.org/packages/flutter_speed_dial
On the link above have a example showing how to use it. You must use SpeedDial class and on children[] you can add some buttons with SpeedDialChild. The sample below shows 2 FABs.
Example using it:
Widget _getFAB() {
return SpeedDial(
animatedIcon: AnimatedIcons.menu_close,
animatedIconTheme: IconThemeData(size: 22),
backgroundColor: Color(0xFF801E48),
visible: true,
curve: Curves.bounceIn,
children: [
// FAB 1
SpeedDialChild(
child: Icon(Icons.assignment_turned_in),
backgroundColor: Color(0xFF801E48),
onTap: () { /* do anything */ },
label: 'Button 1',
labelStyle: TextStyle(
fontWeight: FontWeight.w500,
color: Colors.white,
fontSize: 16.0),
labelBackgroundColor: Color(0xFF801E48)),
// FAB 2
SpeedDialChild(
child: Icon(Icons.assignment_turned_in),
backgroundColor: Color(0xFF801E48),
onTap: () {
setState(() {
_counter = 0;
});
},
label: 'Button 2',
labelStyle: TextStyle(
fontWeight: FontWeight.w500,
color: Colors.white,
fontSize: 16.0),
labelBackgroundColor: Color(0xFF801E48))
],
);
}
Result:
According to medium post
You can use Column (for vertical alignment) or Row widget (for horizontal alignment) with 2 FAB as children and just set hero Tag null or assign diffent HeroTags.
You can make it by setup "heroTag: null" as below:
Stack(
children: <Widget>[
Align(
alignment: Alignment.bottomLeft,
child: FloatingActionButton(
heroTag: null,
...),
),
Align(
alignment: Alignment.bottomRight,
child: FloatingActionButton(
heroTag: null,
...),
),
],
)
Yes, It's worked..!
floatingActionButton: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
FloatingActionButton(
onPressed: () => {},
child: Icon(Icons.navigate_before_rounded),
heroTag: "fab1",
),
FloatingActionButton(
onPressed: () => {},
child: Icon(Icons.navigate_next_rounded),
heroTag: "fab2",
),
]
)
I fixed it with this, also to add space between the buttons you can add a width and the 'hero' tags are very important.
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
floatingActionButton: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
FloatingActionButton(
backgroundColor: Colors.green,
heroTag: "btn",
onPressed: () => _speak(textEditingController.text),
child: Icon(Icons.play_arrow),
),
SizedBox(
width: 40,
),
FloatingActionButton(
backgroundColor: Colors.red,
heroTag: "btn2",
onPressed: () => _stop(),
child: Icon(Icons.stop),
)
],
),
)
enter image description here
In Flutter Documentation, we can use at most one floating action button on a single screen. We can do it using RawMaterialButton() widget. This widget parent widget of the floating action button
It's something like that
class RoundIconButton extends StatelessWidget {
const RoundIconButton({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return RawMaterialButton(
constraints: BoxConstraints(minHeight: 40, minWidth: 40),
shape: CircleBorder(),
fillColor: Colors.white,
onPressed: () {},
child: Text("+"),
);
}
}
class Fab extends StatelessWidget {
const Fab({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Column(
children: [
RawMaterialButton(),
RawMaterialButton(),
],
);
}
}

Flutter How to set Title to Show Modal Bottom Sheet?

Is there a possibility to set title and perhaps navigation back button on this showModalBottomSheet?
I expect something like this...
Yes it's possible to do something like that in Flutter. You can use Column Widget and make its first child as a title bar or something like that with title and back arrow icon.
Here's the code for that:
import 'dart:async';
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
canvasColor: Colors.transparent,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget{
#override
HomePageS createState()=> HomePageS();
}
class HomePageS extends State<MyHomePage>{
#override
Widget build(BuildContext context){
return Scaffold(
body: Container(
color: Colors.white,
child: Center(
child: FlatButton(
child: Text("Show BottomSheet"),
onPressed: () async{
showModalBottomSheet(
context: context,
builder: (BuildContext context){
return ClipRRect(
borderRadius: BorderRadius.only(topLeft: Radius.circular(20.0), topRight: Radius.circular(20.0)),
child: Container(
color: Colors.white,
child: Column(
children: [
ListTile(
leading: Material(
color: Colors.transparent,
child: InkWell(
onTap: (){
Navigator.of(context).pop();
},
child: Icon(Icons.arrow_back) // the arrow back icon
),
),
title: Center(
child: Text("My Title") // Your desired title
)
),
]
)
)
);
}
);
}
)
)
)
);
}
}
Here is the output:
If you don't wanna use the InkWell widget, you can use the IconButton widget like this:
...
ListTile(
leading: IconButton(
icon: Icon(Icons.arrow_back),
onPressed: (){
Navigator.of(context).pop();
}
),
title: Center(
child: Text("My Title")
)
),
...
But if you noticed, the title text is not really centered. In this case, we can replace the ListTile widget to a Stack widget and do something like this:
child: Column(
children: [
Stack(
children: [
Container(
width: double.infinity,
height: 56.0,
child: Center(
child: Text("My Title") // Your desired title
),
),
Positioned(
left: 0.0,
top: 0.0,
child: IconButton(
icon: Icon(Icons.arrow_back), // Your desired icon
onPressed: (){
Navigator.of(context).pop();
}
)
)
]
),
]
)
...
This is the output:
But what would happen if we have a very long text for our title? It would definitely look like this:
Ugly, right? We can see that our Text widget overlaps with our IconButton widget. To avoid this, we can replace our Stack widget with a Row widget.
Here's the code for that:
...
child: Column(
children: [
Row( // A Row widget
mainAxisAlignment: MainAxisAlignment.spaceBetween, // Free space will be equally divided and will be placed between the children.
children: [
IconButton( // A normal IconButton
icon: Icon(Icons.arrow_back),
onPressed: (){
Navigator.of(context).pop();
}
),
Flexible( // A Flexible widget that will make its child flexible
child: Text(
"My Title is very very very very very very very long", // A very long text
overflow: TextOverflow.ellipsis, // handles overflowing of text
),
),
Opacity( // A Opacity widget
opacity: 0.0, // setting opacity to zero will make its child invisible
child: IconButton(
icon: Icon(Icons.clear), // some random icon
onPressed: null, // making the IconButton disabled
)
),
]
),
]
)
Output would be like this:
And this (if the title is not long):
I guess I have naive solution but this works perfectly for me. You might as well try it.
showModalBottomSheet(
barrierColor: Colors.transparent,
enableDrag: true,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(top: Radius.circular(20))),
context: context,
builder:(context){
return Padding(
padding: const EdgeInsets.only(left: 8.0, right: 8.0, bottom: 8.0),
child: Stack(children: [
Padding(
padding: const EdgeInsets.only(top: 65),
child: SingleChildScrollView(
child:<<Scrollable Wdgets>>,
),
),
Card(
elevation: 3,
color: Colors.grey[850],
child: ListTile(
leading: Text("YOUR TITLE",
style: TextStyle(
color: Colors.white,
fontSize: 20,
fontWeight: FontWeight.w500)),
trailing: GestureDetector(
onTap: () {
Navigator.pop(context);
},
child: Icon(
Icons.close,
color: Colors.white,
size: 20,
),
),
),
),
]),
);}

How to add notch to TabBar to place FloatingActionButton in it

I would like to create a notch inside the TabBar to place the FloatingActionBottom in it but I don't know how to do that.
I found nothing in the documentations or on the internet.
You can use the Bottom App Bar for this kind of User Interface
The hasNotch property of the BottomAppBar must be true.
This would get you what I am upto
Widget build(BuildContext context) {
return new Scaffold(
appBar: AppBar(title: const Text('Bottom App Bar')),
floatingActionButtonLocation:
FloatingActionButtonLocation.centerDocked,
floatingActionButton: FloatingActionButton(
child: const Icon(Icons.add), onPressed: () {},),
bottomNavigationBar: BottomAppBar(
hasNotch: true,
child: new Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
IconButton(icon: Icon(Icons.menu), onPressed: () {},),
IconButton(icon: Icon(Icons.search), onPressed: () {},),
],
),
),
);
}
Thank You!
Try implementing this revised version of the code. The FAB should persist across the three tabs
class BarTab extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: DefaultTabController(
length: 3,
child: Scaffold(
appBar: AppBar(
bottom: TabBar(
tabs: [
Tab(icon: Icon(Icons.directions_car)),
Tab(icon: Icon(Icons.directions_transit)),
Tab(icon: Icon(Icons.directions_bike)),
],
),
title: Text('Tabs Demo'),
),
body: TabBarView(
children: [
Icon(Icons.audio),
Icon(Icons.play),
Icon(Icons.maps),
],
),
floatingActionButton: FloatingActionButton(
onpressed:(){},
child: Icon(Icons.add),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
bottomNavigationBar:BottomAppBar(
color:Colors.blue,
hasNotch: true,
child:Container(
height:50.0
child:Row(
children: <Widget>[
IconButton(
icon: Icon(Icons.menu),
onPressed: (){})
]
)
)
),
),
);
}
2020 solution:
hasNotch property is no more in BottomAppBar, however, you can do this in Scaffold
bottomNavigationBar: BottomAppBar(
shape: CircularNotchedRectangle(), //this is what creates the notch
color: Colors.blue,
child: SizedBox(
height: height * 0.1,
width: width,
),
),
floatingActionButton: Container(
margin: EdgeInsets.all(10),
width: 80.0,
height: 80.0,
child: FloatingActionButton(
onPressed: () {},
child: Icon(
Icons.add,
size: 25.0,
),
),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked
output :

bottomNavigationBar using iPhone X

I have an issue with a bottomNavigationBar, the issue happens only on iPhone X, as there appears some padding below the BNB as if it were inside a SafeArea widget (and its not)
Well, how can I remove that padding? or maybe color it somehow?
This is my code for the build function
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: _buildAppBar(),
drawer: _buildDrawer(),
body: _isLoading
? Center(
child: CircularProgressIndicator(),
)
: new Container(
color: Colors.white,
child: _unauthorizedOrders()),
// floatingActionButton: FloatingActionButton(
// onPressed: () {},
// backgroundColor: primaryColor,
// child: Icon(Icons.flash_on, size: 30.0,),
// tooltip: 'Authorize Orders',
// ),
// floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
backgroundColor: Colors.red,
bottomNavigationBar: BottomAppBar(
child: Container(
height: 40.0,
color: primaryColor,
child: Row(
children: <Widget>[
// Padding(
// padding: const EdgeInsets.only(left: 10.0),
// child: Text(
// 'Orders: ${orders.length}',
// style: TextStyle(
// color: Colors.white,
// fontSize: 18.0,
// fontWeight: FontWeight.bold),
// ),
// ),
],
),
)),
);
}
EDIT: I have added the backgroundColor to the scaffold, removed the docked FAB and wrapped the body inside a container to paint it white, still doesn't work, I have updated the code above to show it
Use
SafeArea(
child: BottomAppBar(...)
);
A work-around will be to set the backgroundColor of your Scaffold to the same color as your BottomNavigationBar and have your content in a container with the color that you want.
Edit:
Here is a Sample code:
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'BNB Demo on iPhone X',
theme: new ThemeData(
brightness: Brightness.dark,
primaryColor: Colors.black,
),
home: new MyHomePage(title: 'BNB Demo on iPhone X'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return new SafeArea(
child: new Scaffold(
appBar: new AppBar(
title: new Text(widget.title),
),
body: new Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Text(
'You have pushed the button this many times:',
),
new Text(
'$_counter',
style: Theme.of(context).textTheme.display1,
),
],
),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add, color: Colors.white,),
backgroundColor: Colors.black,
onPressed: _incrementCounter,
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
bottomNavigationBar: new BottomAppBar(
child: Container(
height: 40.0,
color: Colors.black,
),
),
),
);
}
}
I had the same problem with this bottomAppBar.
I only erased the color attibute.
Hope it helps to someone.
BottomAppBar(
elevation: 0.0,
shape: widget.notchedShape,
child: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20.0), topRight: Radius.circular(20.0)),
color: Colors.white),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: items)
),
color: Colors.teal[50]);

IconButton throws an exception

I'm trying to make a simple AppBar widget with some icons in Flutter, but I keep getting this assertion:
The following assertion was thrown building IconButton(Icon(IconData(U+0E5D2)); disabled; tooltip:
I pretty much just mimiced the documentation, but here is my code:
import 'package:flutter/material.dart';
void main() {
runApp(new MaterialApp(
title: "Stateless Widget Example",
home: new AppBar(title: new Text("App Bar"))
));
}
class AppBar extends StatelessWidget {
AppBar({this.title});
final Widget title;
#override
Widget build(BuildContext context) {
return new Container(
height: 56.0,
padding: const EdgeInsets.symmetric(horizontal: 8.0),
decoration: new BoxDecoration(
color: Colors.cyan,
border: new Border(
bottom: new BorderSide(
width: 1.0,
color: Colors.black
)
)
),
child: new Row (
children: <Widget> [
new IconButton(
icon: new Icon(Icons.menu),
tooltip: 'Navigation menu',
onPressed: null, // null disables the button
),
new Expanded(child: title)
]
)
);
}
}
I feel like I'm missing an import or something. But I'm not completely sure. Perhaps my computer was just acting up, because Flutter run has been buggy for me. I'm new to Dart and Flutter, so perhaps I'm just not seeing an obvious error.
IconButton is a Material Widget, so you need to use it inside a Material parent, for example something like this:
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(title: new Text(widget.title), actions: <Widget>[
new IconButton(
icon: new Icon(Icons.favorite),
tooltip: 'Favorite',
onPressed: () {},
),
new IconButton(
icon: new Icon(Icons.more_vert),
tooltip: 'Navigation menu',
onPressed: () {},
),
]),
body: new Center(
child: new Text('This is the body of the page.'),
),
);
}
Check to ensure that your pubspec.yaml contains the following:
flutter:
uses-material-design: true
That will ensure that the Material Icons font is included with your application, so that you can use the icons in the Icons class.
addButton() {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.symmetric(vertical: 10.0),
child: SizedBox(
height: 45,
width: 200,
child: ElevatedButton.icon(
onPressed: () async {},
style: ButtonStyle(
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30.0),
)),
elevation: MaterialStateProperty.all(1),
backgroundColor: MaterialStateProperty.all(Colors.blue),
),
icon: Icon(Icons.add, size: 18),
label: Text("Add question"),
),
),
),
],
);
}
you lost meterial widget
IconButton needs Material
return new Material(
child: new Container(
height: 56.0,
padding: const EdgeInsets.symmetric(horizontal: 8.0),
decoration: new BoxDecoration(
color: Colors.cyan,
border: new Border(
bottom: new BorderSide(
width: 1.0,
color: Colors.black
)
)
),
child: new Row (
children: <Widget> [
new IconButton(
icon: new Icon(Icons.menu),
tooltip: 'Navigation menu',
onPressed: null, // null disables the button
),
new Expanded(child: title)
]
)
);

Resources