Flutter searchbar layout issue BoxConstraints forces an infinite width - dart

I am trying to imitate a searchview similar to attached image, but I am getting following error. I can achieve this using ListTile but I can't set padding to the icons or TextField. So I am trying to achieve this using Row widget. Please have a look at my code and help me to draw this searchbar.
I/flutter (19181): The following assertion was thrown during
performLayout():
I/flutter (19181): BoxConstraints forces an infinite width.
I/flutter (19181): These invalid constraints were provided to
RenderAnimatedOpacity's layout() function by the
I/flutter (19181): following function, which probably computed
the invalid constraints in question:
I/flutter (19181): _RenderDecoration._layout.layoutLineBox (package:flutter/src/material/input_decorator.dart:767:11)
I/flutter (19181): The offending constraints were:
I/flutter (19181): BoxConstraints(w=Infinity, 0.0<=h<=46.0)
Here is my code:
new Container(
height: 70.0,
color: Theme.of(context).primaryColor,
child: new Padding(
padding: const EdgeInsets.all(8.0),
child: new Card(
child: new Container(
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
new Icon(Icons.search),
new Container(
height: double.infinity,
width: double.infinity,
child: new TextField(
controller: controller,
decoration: new InputDecoration(
hintText: 'Search', border: InputBorder.none),
// onChanged: onSearchTextChanged,
),
),
new IconButton(icon: new Icon(Icons.cancel), onPressed: () {
controller.clear();
// onSearchTextChanged('');
},),
],
),
)
))),

EDIT: This answer is a quick fix for the above question.
Best practice is Derek Lakin's answer
Answer:
To maximize container's width, set its width to
MediaQuery.of(context).size.width
Check this code:
new Container(
height: 70.0,
color: Theme.of(context).primaryColor,
child: new Padding(
padding: const EdgeInsets.all(8.0),
child: new Card(
child: new Container(
child: new Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
new Icon(Icons.search),
new Container(
//height: double.infinity, //This is extra
width: MediaQuery.of(context).size.width - 100.0, // Subtract sums of paddings and margins from actual width
child: new TextField(
controller: controller,
decoration: new InputDecoration(
hintText: 'Search', border: InputBorder.none),
// onChanged: onSearchTextChanged,
),
),
new IconButton(icon: new Icon(Icons.cancel), onPressed: () {
controller.clear();
// onSearchTextChanged('');
},),
],
),
)
)))

You're trying to define infinite height and width for the Container that is a parent of the TextField, which wants to use all the space.
The following works by using Expanded to fill the available space:
Container(
height: 70.0,
child: Card(
margin: EdgeInsets.all(8.0),
child: Row(
children: <Widget>[
Padding(
padding: EdgeInsets.all(8.0),
child: Icon(Icons.search),
),
Expanded(
child: TextField(
decoration: new InputDecoration(
hintText: 'Search', border: InputBorder.none),
),
flex: 1,
),
IconButton(
icon: Icon(Icons.cancel),
onPressed: () {},
)
],
),
),
),

Related

Incorrect use of ParentWidget. Expanded widgets must be placed inside flex widget

Widget build(BuildContext context) {
return Scaffold(
backgroundColor:Colors.white,
body:Expanded(
child: Column(
children: <Widget>[
Container(
child: Column(
children: <Widget>[
Container(
width: MediaQuery.of(context).size.width*0.9,
height: MediaQuery.of(context).size.height*0.22,
color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
SizedBox(height: 36.0,),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text("MON COMPTE",style: TextStyle(fontSize:30,fontWeight:FontWeight.bold),),
Container(
height: 50.0,
width: 50.0,
child: FloatingActionButton(
backgroundColor: Color(0xffd57031),
onPressed: (){
},
child: Icon(Icons.help_outline,size: 30.0,),),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Container(
decoration: BoxDecoration(
border:Border(bottom: BorderSide(color: Color(0xffd57031),width: check?3.0:1.0))
),
width: MediaQuery.of(context).size.width/2.2,
child: FlatButton(onPressed: (){
setState(() {
check = true;
});
ctrl.animateToPage(0, duration: Duration(milliseconds: 200), curve: Curves.fastOutSlowIn);
}, child: Text("Se connecter",style:TextStyle(color: Color(0xffd57031),fontSize: 20,fontWeight: FontWeight.bold)))),
Container(
decoration: BoxDecoration(
border:Border(bottom: BorderSide(color: Color(0xffd57031),width: check?1.0:3.0))
),
width: MediaQuery.of(context).size.width/2.31,
child: FlatButton(onPressed: (){
setState(() {
check = false;
});
ctrl.animateToPage(1, duration: Duration(milliseconds: 200), curve: Curves.fastOutSlowIn);
}, child: Text("S'inscrire",style:TextStyle(color: Color(0xffd57031),fontSize: 20,fontWeight: FontWeight.bold)))),
],
)
],
),
),
Container(
height:MediaQuery.of(context).size.height*0.78,
child: PageView(
controller: ctrl,
children: <Widget>[
Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
SizedBox(height:20.0),
txtField("E-mail"),
SizedBox(height:20.0),
txtField("Mot de passe"),
SizedBox(height:40.0),
Container(
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
color: Colors.black12,
blurRadius: 20.0,
spreadRadius: 5.0
)
],
),
width: MediaQuery.of(context).size.width*0.7,
height: 50.0,
child: FlatButton(onPressed: (){}, child: Text("Se connecter",style: TextStyle(color:Colors.white,)),color: Color(0xffd57031),)),
SizedBox(height:40.0),
Text('Mot de passe oublié ?',style: TextStyle(color:Color(0xffd57031),),),
Divider(color: Color(0xffd57031),thickness: 1.5,indent: 112.0,endIndent: 125,height:1,)
],
),
),
],
),
)
],
),
),
],
),
),
);
}
and there is the error
I/flutter (20272): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
I/flutter (20272): The following assertion was thrown building _BodyBuilder:
I/flutter (20272): Incorrect use of ParentDataWidget.
I/flutter (20272): Expanded widgets must be placed inside Flex widgets.
I/flutter (20272): Expanded(no depth, flex: 1, dirty) has no Flex ancestor at all.
I/flutter (20272): The ownership chain for the parent of the offending Expanded was:
I/flutter (20272): _BodyBuilder ← MediaQuery ← LayoutId-[<_ScaffoldSlot.body>] ← CustomMultiChildLayout ←
I/flutter (20272): AnimatedBuilder ← DefaultTextStyle ← AnimatedDefaultTextStyle ← _InkFeatures-[GlobalKey#9611b ink
I/flutter (20272): renderer] ← NotificationListener ← PhysicalModel ← ⋯
I/flutter (20272):
I/flutter (20272): The relevant error-causing widget was:
I/flutter (20272): Scaffold file:///Users/macbook/AndroidStudioProjects/monmercato/lib/Screens/Login.dart:37:12
You are getting the error because you are using an Expanded widget to wrap your Column.
To fix this, try:
1) Remove the Expanded widget wrapping the Column
2) If you want the Widgets to take the screen height, remove the Expanded widget and wrap your Column widget with a Container(give the container a width and height property)
Check the code below, it works fine:
Widget build(BuildContext context) {
return Scaffold(
backgroundColor:Colors.white,
Container(
// give the container your preferred height here
height: MediaQuery.of(context).size.height,
// give the container your preferred width here
width: MediaQuery.of(context).size.width,
child: Column(
children: <Widget>[
Container(
child: Column(
children: <Widget>[
Container(
width: MediaQuery.of(context).size.width*0.9,
height: MediaQuery.of(context).size.height*0.22,
color: Colors.white,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
SizedBox(height: 36.0,),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Text("MON COMPTE",style: TextStyle(fontSize:30,fontWeight:FontWeight.bold),),
Container(
height: 50.0,
width: 50.0,
child: FloatingActionButton(
backgroundColor: Color(0xffd57031),
onPressed: (){
},
child: Icon(Icons.help_outline,size: 30.0,),),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Container(
decoration: BoxDecoration(
border:Border(bottom: BorderSide(color: Color(0xffd57031),width: check?3.0:1.0))
),
width: MediaQuery.of(context).size.width/2.2,
child: FlatButton(onPressed: (){
setState(() {
check = true;
});
ctrl.animateToPage(0, duration: Duration(milliseconds: 200), curve: Curves.fastOutSlowIn);
}, child: Text("Se connecter",style:TextStyle(color: Color(0xffd57031),fontSize: 20,fontWeight: FontWeight.bold)))),
Container(
decoration: BoxDecoration(
border:Border(bottom: BorderSide(color: Color(0xffd57031),width: check?1.0:3.0))
),
width: MediaQuery.of(context).size.width/2.31,
child: FlatButton(onPressed: (){
setState(() {
check = false;
});
ctrl.animateToPage(1, duration: Duration(milliseconds: 200), curve: Curves.fastOutSlowIn);
}, child: Text("S'inscrire",style:TextStyle(color: Color(0xffd57031),fontSize: 20,fontWeight: FontWeight.bold)))),
],
)
],
),
),
Container(
height:MediaQuery.of(context).size.height*0.78,
child: PageView(
controller: ctrl,
children: <Widget>[
Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
SizedBox(height:20.0),
txtField("E-mail"),
SizedBox(height:20.0),
txtField("Mot de passe"),
SizedBox(height:40.0),
Container(
decoration: BoxDecoration(
boxShadow: [
BoxShadow(
color: Colors.black12,
blurRadius: 20.0,
spreadRadius: 5.0
)
],
),
width: MediaQuery.of(context).size.width*0.7,
height: 50.0,
child: FlatButton(onPressed: (){}, child: Text("Se connecter",style: TextStyle(color:Colors.white,)),color: Color(0xffd57031),)),
SizedBox(height:40.0),
Text('Mot de passe oublié ?',style: TextStyle(color:Color(0xffd57031),),),
Divider(color: Color(0xffd57031),thickness: 1.5,indent: 112.0,endIndent: 125,height:1,)
],
),
),
],
),
)
],
),
),
],
),
),
);
I hope this helps.
You have to just remove First Expanded Widget.
Scaffold(
backgroundColor: Colors.white,
body: Column(// remove Expandede
children: <Widget>[

Exception thrown when I tried implementing a Login Screen

I'm developing a flutter app and I tried using a Login Screen from Flutter Screens and ran into a problem. When I run the app, it does not work and a list of errors is just shown to me. I'm wondering if I'm even using it correctly.
This is my main:
import 'package:flutter/material.dart';
import 'AppDrawer.dart';
import 'LoginScreen.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Test App',
theme: new ThemeData(
primaryColor: Colors.blue.shade400
),
debugShowCheckedModeBanner: false,
// home: new AppDrawer(),
home: new Container(
child: LoginScreen(
backgroundColor1: Color(0xFF444152),
backgroundColor2: Color(0xFF6f6c7d),
highlightColor: Color(0xfff65aa3),
foregroundColor: Colors.white,
logo: new AssetImage("assets/images/full-bloom.png"),
),
),
);
}
}
This is the LoginScreen class which I took from the Flutter Screens repo (it is under LoginScreen2):
import 'package:flutter/material.dart';
class LoginScreen extends StatelessWidget {
final Color backgroundColor1;
final Color backgroundColor2;
final Color highlightColor;
final Color foregroundColor;
final AssetImage logo;
LoginScreen({Key k, this.backgroundColor1, this.backgroundColor2, this.highlightColor, this.foregroundColor, this.logo});
#override
Widget build(BuildContext context) {
return Container(
decoration: new BoxDecoration(
gradient: new LinearGradient(
begin: Alignment.centerLeft,
end: new Alignment(1.0, 0.0), // 10% of the width, so there are ten blinds.
colors: [this.backgroundColor1, this.backgroundColor2], // whitish to gray
tileMode: TileMode.repeated, // repeats the gradient over the canvas
),
),
height: MediaQuery.of(context).size.height,
child: Column(
children: <Widget>[
Container(
padding: const EdgeInsets.only(top: 150.0, bottom: 50.0),
child: Center(
child: new Column(
children: <Widget>[
Container(
height: 128.0,
width: 128.0,
child: new CircleAvatar(
backgroundColor: Colors.transparent,
foregroundColor: this.foregroundColor,
radius: 100.0,
child: new Text(
"S",
style: TextStyle(
fontSize: 50.0,
fontWeight: FontWeight.w100,
),
),
),
decoration: BoxDecoration(
border: Border.all(
color: this.foregroundColor,
width: 1.0,
),
shape: BoxShape.circle,
//image: DecorationImage(image: this.logo)
),
),
new Padding(
padding: const EdgeInsets.all(16.0),
child: new Text(
"Samarth Agarwal",
style: TextStyle(color: this.foregroundColor),
),
)
],
),
),
),
new Container(
width: MediaQuery.of(context).size.width,
margin: const EdgeInsets.only(left: 40.0, right: 40.0),
alignment: Alignment.center,
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
color: this.foregroundColor,
width: 0.5,
style: BorderStyle.solid),
),
),
padding: const EdgeInsets.only(left: 0.0, right: 10.0),
child: new Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
new Padding(
padding:
EdgeInsets.only(top: 10.0, bottom: 10.0, right: 00.0),
child: Icon(
Icons.alternate_email,
color: this.foregroundColor,
),
),
new Expanded(
child: TextField(
textAlign: TextAlign.center,
decoration: InputDecoration(
border: InputBorder.none,
hintText: 'samarthagarwal#live.com',
hintStyle: TextStyle(color: this.foregroundColor),
),
),
),
],
),
),
new Container(
width: MediaQuery.of(context).size.width,
margin: const EdgeInsets.only(left: 40.0, right: 40.0, top: 10.0),
alignment: Alignment.center,
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
color: this.foregroundColor,
width: 0.5,
style: BorderStyle.solid),
),
),
padding: const EdgeInsets.only(left: 0.0, right: 10.0),
child: new Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
new Padding(
padding:
EdgeInsets.only(top: 10.0, bottom: 10.0, right: 00.0),
child: Icon(
Icons.lock_open,
color: this.foregroundColor,
),
),
new Expanded(
child: TextField(
obscureText: true,
textAlign: TextAlign.center,
decoration: InputDecoration(
border: InputBorder.none,
hintText: '*********',
hintStyle: TextStyle(color: this.foregroundColor),
),
),
),
],
),
),
new Container(
width: MediaQuery.of(context).size.width,
margin: const EdgeInsets.only(left: 40.0, right: 40.0, top: 30.0),
alignment: Alignment.center,
child: new Row(
children: <Widget>[
new Expanded(
child: new FlatButton(
padding: const EdgeInsets.symmetric(
vertical: 20.0, horizontal: 20.0),
color: this.highlightColor,
onPressed: () => {},
child: Text(
"Log In",
style: TextStyle(color: this.foregroundColor),
),
),
),
],
),
),
new Container(
width: MediaQuery.of(context).size.width,
margin: const EdgeInsets.only(left: 40.0, right: 40.0, top: 10.0),
alignment: Alignment.center,
child: new Row(
children: <Widget>[
new Expanded(
child: new FlatButton(
padding: const EdgeInsets.symmetric(
vertical: 20.0, horizontal: 20.0),
color: Colors.transparent,
onPressed: () => {},
child: Text(
"Forgot your password?",
style: TextStyle(color: this.foregroundColor.withOpacity(0.5)),
),
),
),
],
),
),
new Expanded(child: Divider(),),
new Container(
width: MediaQuery.of(context).size.width,
margin: const EdgeInsets.only(left: 40.0, right: 40.0, top: 10.0, bottom: 20.0),
alignment: Alignment.center,
child: new Row(
children: <Widget>[
new Expanded(
child: new FlatButton(
padding: const EdgeInsets.symmetric(
vertical: 20.0, horizontal: 20.0),
color: Colors.transparent,
onPressed: () => {},
child: Text(
"Don't have an account? Create One",
style: TextStyle(color: this.foregroundColor.withOpacity(0.5)),
),
),
),
],
),
),
],
),
);
}
}
I think that maybe I'm using the container wrongly in my main at this line:
home: new Container(
Anyone have any thoughts on what could be the problem ?
The error which pops out is as follows (it goes on, this is just the first few lines):
I/flutter (11670): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
I/flutter (11670): The following assertion was thrown building TextField(decoration: InputDecoration(hintText:
I/flutter (11670): "samarthagarwal#live.com", border: _NoInputBorder()), textAlign: center, dirty, state:
I/flutter (11670): _TextFieldState#de3eb):
I/flutter (11670): No Material widget found.
I/flutter (11670): TextField widgets require a Material widget ancestor.
I/flutter (11670): In material design, most widgets are conceptually "printed" on a sheet of material. In Flutter's
I/flutter (11670): material library, that material is represented by the Material widget. It is the Material widget
I/flutter (11670): that renders ink splashes, for instance. Because of this, many material library widgets require that
I/flutter (11670): there be a Material widget in the tree above them.
I/flutter (11670): To introduce a Material widget, you can either directly include one, or use a widget that contains
I/flutter (11670): Material itself, such as a Card, Dialog, Drawer, or Scaffold.
I/flutter (11670): The specific widget that could not find a Material ancestor was:
I/flutter (11670): TextField(decoration: InputDecoration(hintText: "samarthagarwal#live.com", border:
I/flutter (11670): _NoInputBorder()), textAlign: center)
I/flutter (11670): The ancestors of this widget were:
I/flutter (11670): Expanded(flex: 1)
I/flutter (11670): Row(direction: horizontal, mainAxisAlignment: spaceBetween, crossAxisAlignment: center)
I/flutter (11670): Align(alignment: center)
I/flutter (11670): Padding(padding: EdgeInsets(0.0, 0.0, 10.0, 0.5))
I/flutter (11670): DecoratedBox(bg: BoxDecoration(border: Border(bottom: BorderSide(Color(0xffffffff), 0.5,
I/flutter (11670): BorderStyle.solid))))
You need to Simply Wrap your parent container with Scaffold.
home: Scaffold(
body: new Container(
child: LoginScreen(
backgroundColor1: Color(0xFF444152),
backgroundColor2: Color(0xFF6f6c7d),
highlightColor: Color(0xfff65aa3),
foregroundColor: Colors.white,
logo: new AssetImage("assets/images/full-bloom.png"),
),
),
),

How do I make the global type context variable in flutter?

I just figured out some problem when I tried to navigate from one page to the other in flutter. The Navigation.push method requires the context variable and I need reference to the context for navigating.
Widget navBox(Color aColor, double left, double top, Icon icon,String action, Route route) {
return Positioned (
left: left,
top: top,
child: InkWell(
borderRadius: BorderRadius.circular(30.0),
onTap: () {
Navigator.push(context, route);
},
child: new Container(
height: 220.0,
width: 220.0,
decoration: BoxDecoration(
color: aColor,
borderRadius: BorderRadius.circular(30.0),
),
child: Padding(
padding: EdgeInsets.all(40.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
icon,
new Text(action, style: TextStyle(color: Colors.white, fontSize: 20.0, fontFamily: 'Oxygen')),
],
),
),
),
),
);
}
I expected to navigate to the other page by the call of this function with proper route defined.
I got the error like:
The following NoSuchMethodError was thrown while handling a gesture
The method 'ancestorStateOfType' was called on null.
Just add a context parameter to the method's signature. But also have in mind that methods shouldn't have so many parameters, because it makes them harder to use.
Wrapping the InkWell with the new Builder or the Material widget solves the problem.
Here's the snippet on how I solved the problem:
child: new Container(
height: 220.0,
width: 220.0,
decoration: BoxDecoration(
color: aColor,
borderRadius: BorderRadius.circular(30.0),
),
child: new Builder(
builder: (context) => InkWell(
onTap: () {
Navigator.push(context,
MaterialPageRoute(builder: (context) => GetData()),);
},
child: Padding(
padding: EdgeInsets.all(40.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
icon,
new Text(action, style: TextStyle(color: Colors.white, fontSize: 20.0, fontFamily: 'Oxygen')),
],
),
),
),
),
),
I am only listing the Container widget of the function. So rest of them could be figured out by yourself.

widgets not align in the bottom of a screen in flutter

I have a screen like the below Screenshot. Which has a text in the centre of the screen and a button and text in the bottom of the screen, but I got both in the centre of the screen. I include my expected design, my code and my result below. Anyone, please help me. how to place the text in the centre of the screen and the remaining part inthe bottom of the screen.
Expected Screen,
code:
body: new Container(
decoration: new BoxDecoration(
image: new DecorationImage(
image: new AssetImage("assets/images/home_page_background.png"),
fit: BoxFit.cover,
),
),
child: new Container(
child: new Column(
// crossAxisAlignment: CrossAxisAlignment.stretch,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Container(
// margin: new EdgeInsets.only(top: _MARGIN_JAHMAIKA),
child: new Text(
'JAHMAIKA',
style: style72,
),
),
new Container(
// margin: new EdgeInsets.only(top: _MARGIN_BUTTON),
child: new FlatButton(
child: new Container(
padding: new EdgeInsets.only(
left: _PADDING_LARGE,
right: _PADDING_LARGE,
top: _PADDING_SMALL,
bottom: _PADDING_SMALL),
decoration: new BoxDecoration(
shape: BoxShape.rectangle,
borderRadius: new BorderRadius.all(
new Radius.elliptical(40.0, 50.0)),
border: new Border.all(
color: Colors.white,
),
),
child: new Text(
'Create an account',
style: style19,
),
),
onPressed: () {
Navigator.push(
context,
new MaterialPageRoute(
builder: (context) => new SignUpPage()),
);
}),
),
new Container(
margin: new EdgeInsets.only(top: _MARGIN_SMALL),
child: new Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
new Container(
child: new Text(
'Already have an account?',
textAlign: TextAlign.center,
style: style15White,
),
),
new GestureDetector(
onTap: () {
Navigator.push(
context,
new MaterialPageRoute(
builder: (context) => new SignInPage()),
);
},
child: new Container(
margin: new EdgeInsets.only(left: _MARGIN_SMALL),
child: new Text('Login',
textAlign: TextAlign.center, style: style15Green),
),
),
],
),
),
],
),
),
),
);
result:
You could restructure you widgets inside the column in a different way.
You can use a column/container for all the buttons that has to be aligned to bottom and make the other widget as Expanded which takes up the remaining space, pushing the Row with the buttons to the bottom of the screen.
Wrap it in an Align widget wrapped with an Expanded widget to achieve width and height growth, like so:
Expanded(
child: Align(
alignment: Alignment.bottomCenter,
child: Containter(), // << Put your content here
),

How do I absolutely position a badge in a BottomNavigationBarItem

I am using BottomNavigationBarItem to display bottom navigation UI with icons and text. I would like to be able to add badges with numeric values on those. Here is my current attempt:
bottomNavigationBar:
new BottomNavigationBar(items: <BottomNavigationBarItem>[
new BottomNavigationBarItem(
icon: new Stack(
children: <Widget>[
const Icon(Icons.home),
new Positioned(
top: 0.0,
left: 0.0,
child: new Container(
decoration: new BoxDecoration(
borderRadius: new BorderRadius.circular(4.0),
color: Colors.red),
width: 16.0,
child: new Text(
"12",
style: const TextStyle(color: Colors.white),
),
))
],
),
title: new Text("Home")),
new BottomNavigationBarItem(
icon: const Icon(Icons.star), title: new Text("Star")),
],
type: BottomNavigationBarType.fixed),
However, the badge is positioned with the icon's bounding box, so it overlaps heavily with the icon:
What I would like, instead, is something like that:
Is it possible to achieve this using the BottomNavigationBarItem widget? If not, what would be a good workaround?
make sure that the badge position is right, and the overflowing children should be visible
icon: new Stack(
overflow: Overflow.visible,
children: <Widget>[
const Icon(Icons.home),
new Positioned(
top: -1.0,
right: -6.0,
child: new Container(
decoration: new BoxDecoration(
borderRadius: new BorderRadius.circular(4.0), color: Colors.red),
width: 16.0,
child: new Text(
"12",
style: const TextStyle(color: Colors.white),
),
))
],
),
If it is useful to anyone, I made one that works in the AppBar.
static Widget makeIconWithBadge(String badgeText, GestureTapCallback onTap) {
return Container(
padding: EdgeInsets.only(right: 16.0),
child: Center(
child: new Stack(
overflow: Overflow.visible,
children: <Widget>[
const Icon(Icons.inbox),
new Positioned(
top: -6.0,
right: -6.0,
child: Container(
padding: EdgeInsets.all(2.0),
decoration: new BoxDecoration(
borderRadius: new BorderRadius.circular(99.0),
color: Colors.white,
),
child: new Container(
padding: EdgeInsets.symmetric(vertical: 1.0, horizontal: 4.0),
decoration: new BoxDecoration(
borderRadius: new BorderRadius.circular(99.0),
color: Colors.red),
child: Center(
child: new Text(
"12",
textAlign: TextAlign.center,
style: TextStyle(color: Colors.white, fontSize: 12.0,),
),
),
),
),
),
Positioned.fill(
child: Material(
borderRadius: BorderRadius.all(Radius.circular(99.0)),
color: Colors.transparent,
child: InkWell(onTap: onTap),
),
)
],
),
),
);
}

Resources