I'm trying to center the title text in an app bar that has both a leading and trailing actions.
#override
Widget build(BuildContext context) {
final menuButton = new PopupMenuButton<int>(
onSelected: (int i) {},
itemBuilder: (BuildContext ctx) {},
child: new Icon(
Icons.dashboard,
),
);
return new Scaffold(
appBar: new AppBar(
// Here we take the value from the MyHomePage object that
// was created by the App.build method, and use it to set
// our appbar title.
title: new Text(widget.title, textAlign: TextAlign.center),
leading: new IconButton(
icon: new Icon(Icons.accessibility),
onPressed: () {},
),
actions: [
menuButton,
],
),
body: new Center(
child: new Text(
'Button tapped $_counter time${ _counter == 1 ? '' : 's' }.',
),
),
floatingActionButton: new FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: new Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
This works well except the title is aligned on the left as is shown in this picture:
As I try to include the title in the center, it appears that it's too much to the left:
#override
Widget build(BuildContext context) {
final menuButton = new PopupMenuButton<int>(
onSelected: (int i) {},
itemBuilder: (BuildContext ctx) {},
child: new Icon(
Icons.dashboard,
),
);
return new Scaffold(
appBar: new AppBar(
// Here we take the value from the MyHomePage object that
// was created by the App.build method, and use it to set
// our appbar title.
title: new Center(child: new Text(widget.title, textAlign: TextAlign.center)),
leading: new IconButton(
icon: new Icon(Icons.accessibility),
onPressed: () {},
),
actions: [
menuButton,
],
),
body: new Center(
child: new Text(
'Button tapped $_counter time${ _counter == 1 ? '' : 's' }.',
),
),
floatingActionButton: new FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: new Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
I would love a solution to get the title text centered perfectly between the 2 icons.
Centering the title is the default on iOS. On Android, the AppBar's title defaults to left-aligned, but you can override it by passing centerTitle: true as an argument to the AppBar constructor.
Example:
AppBar(
centerTitle: true, // this is all you need
...
)
I had the same problem and it finally worked when I added the
mainAxisSize: MainAxisSize.min to my Row() widget:
return new Scaffold(
appBar: new AppBar(
// Here we take the value from the MyHomePage object that
// was created by the App.build method, and use it to set
// our appbar title.
title: Row(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text(
widget.title,
),
],
),
leading: new IconButton(
icon: new Icon(Icons.accessibility),
onPressed: () {},
),
actions: [
menuButton,
],
),
);
}
In my case I wanted to have a logo / image centered instead of a text. In this case, centerTitle is not enough (not sure why, I have an svg file, maybe that's the reason... ), so for example, this:
appBar: AppBar(centerTitle: true, title: AppImages.logoSvg)
will not really center the image (plus the image can be too big, etc.). What works well for me is a code like this:
appBar: AppBar(centerTitle: true,
title: ConstrainedBox(
constraints: BoxConstraints(maxHeight: 35, maxWidth: 200),
child: AppImages.logoSvg)),
You can just use the centerTitle property in the appBar section to center your title
using:
centerTitle: true
Here is how I make centerTitle on my appbar:
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: new AppBar(
centerTitle: true ,
title: new Text("Login"),
),
body: new Container(
padding: EdgeInsets.all(18.0),
key: formkey,
child: ListView(
children: buildInputs() + buildSubmitButton(),
),
)
);
}
Here is a different approach if you want to create a custom app bar title. For example you want an image and a text at the center of app bar then add
appBar: AppBar(
title: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.your_app_icon,
color: Colors.green[500],
),
Container(
padding: const EdgeInsets.all(8.0), child: Text('YourAppTitle'))
],
),
)
Here we have created a Row with MainAxisAlignment.center to center the children. Then we have added two children - An Icon and a Container with text. I wrapped Text widget in the Container to add the necessary padding.
You can center the title of an appBar by using centerTitle parameter.
centerTitle is Boolean Datatype, and default value is False.
centerTitle : true
Example :
import 'package:flutter/material.dart';
void main() {
runApp(
MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('App Title'),
backgroundColor: Colors.red,
centerTitle: true,
),
),
),
);
}
Yeah but in my case i used centertitle as well as axis alignment then it made it centre , if i am using only onw of it then it is is not making it centre , here is how i am doing it :
import 'package:flutter/material.dart';
import 'package:infintywalls/widgets/widget.dart';
class Home extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Row(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
appName(),
],
),
elevation: 0.0,
centerTitle: true,
),
);
}
}
and yeah btw appName() is my custom widget not a default builtin one.
home this is helpful to you
thanks
appBar has its own bool condition for title center show or not,
so,
if you set true,
appBar: AppBar(
title: Text(
"header Text",
style: TextStyle(color: Colors.black),
),
centerTitle: true,
),
then it will be centre,other then its default left align (in android)
ios set center(in default).
Try the following code:
AppBar(
centerTitle: true,
…
),
It can be done by using Center class.
appBar: AppBar(
title: const Center(
child: Text("I Am Rich"),
),
),
After trying many solutions this helped me centerTitle: true
adding sample code in addition to #Collin Jackson answer
Example
in build(BuildContext context)
do this
appBar: AppBar(
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: Text(widget.title),centerTitle: true
),
appbar:AppBar(
centerTitle: true,
title:Text("HELLO")
)
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Title'),
actions: <Widget> [
IconButton(icon: const Icon(Icons.file_upload), onPressed: _pressed),
],
leading: IconButton(icon: const Icon(Icons.list), onPressed: _pressed),
centerTitle: true,
)
body: Text("Content"),
);
}
This can help in making Appbar Title Text in Center.
You can choose to add your desired Styles using Style or comment it if not needed.
appBar: AppBar(
title: const Center(
child: Text(
"App Title",
style: TextStyle( color: Colors.white,fontSize: 20),
),
),
),
On App Display:
It my case this code works:-
appBar: AppBar(
centerTitle: true,
elevation: 2,
title: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
child: Text(" TINKLE"),
)
],
),
),
),
Hope this was helpful.
Use Center object
appBar: AppBar(
title: Center(
child: const Text('Title Centered')
)
)
Related
Is it possible we can add onPressed action on the logo and start another activity?
I am creating a simple flutter app where I have used AppBar and in leading icon I have used a custom logo. I am not sure how to perform onPressed method so that it starts another activity. Anyone please help me here. Below is my app bar code.
class SecondScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: Padding(
padding: const EdgeInsets.all(8.0),
child: Image.asset(
"assets/images/logo.png",
),
),
title: Text('Safe Outs Business'),
),
body: Center(
child: Text('Admin HomePage'),
),
);
}
}
Click here to see a sample Image of the layout I am trying to build in flutter
You can embed your logo inside a GestureDetector:
return Scaffold(
appBar: AppBar(
leading: Padding(
padding: const EdgeInsets.all(8.0),
child: GestureDetector(
onTap: () => print('TAPPED!'),
child: Image.asset(
"assets/images/logo.png",
),
),
),
title: Text('Safe Outs Business'),
),
body: Center(
child: Text('Admin HomePage'),
),
);
I want a popup menu or some kind of slide screen with options to come when i click on an icon in the app bar, however i dont want to use PopMenuButton as i dont want to use that icon. How can I do this?
My code
return new Scaffold(
appBar: new AppBar(
title: new Text("Home"),
leading: IconButton(
icon: Icon(
Icons.dehaze,
color: Colors.black,
),
onPressed: () {
// do something
},
),
),
body: new Center(...),
);
#Denise, you don't need to manually create a button and assign action for drawer menu. You can simply use drawer in Scaffold with Drawer widget like so,
class MyAppState extends State<MyApp> {
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Test'),
),
drawer: Drawer(
// Add a ListView to the drawer. This ensures the user can scroll
// through the options in the drawer if there isn't enough vertical
// space to fit everything.
child: ListView(
// Important: Remove any padding from the ListView.
padding: EdgeInsets.zero,
children: <Widget>[
DrawerHeader(
child: Text('Drawer Header'),
decoration: BoxDecoration(
color: Colors.blue,
),
),
ListTile(
title: Text('Item 1'),
onTap: () {
// Update the state of the app
// ...
// Then close the drawer
Navigator.pop(context);
},
),
ListTile(
title: Text('Item 2'),
onTap: () {
// Update the state of the app
// ...
// Then close the drawer
Navigator.pop(context);
},
),
],
),
),
body: Padding(
padding: EdgeInsets.all(20.0),
child: Center(
child: Column(
children: <Widget>[
Text('')
],
)
)
),
)
);
}
}
And if you wanna use different icon,
class MyAppState extends State<MyApp> {
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
key: _scaffoldKey,
appBar: AppBar(
title: Text('Test'),
leading: new IconButton(
icon: new Icon(Icons.dehaze),
onPressed: () => _scaffoldKey.currentState.openDrawer()),
),
drawer: Drawer(......
Hope this helps.
If the icon is the problem in PopMenuButton. You can change it by assigning icon attribute in PopMenuButton.
PopupMenuButton<Choice>(
onSelected: _select,
icon:Icon(
Icons.dehaze,
color: Colors.black,
),
itemBuilder: (BuildContext context) {
return choices.skip(2).map((Choice choice) {
return PopupMenuItem<Choice>(
value: choice,
child: Text(choice.title),
);
}).toList();
https://flutter.dev/docs/catalog/samples/basic-app-bar
I want to open a drawer after pushing on the custom button in BottomMenu I have trouble with Scaffold.of(context).openDrawer(), it doesn't work. My BottomMenu is a separate widget class. As I understand, it doesn't work because it's a separate context. How can I get the right context? Or perhaps someone knows another solution.
Here my code reproducer:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: MyHomePage(title: 'Flutter Drawer'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
bottomNavigationBar: BottomMenu(),
endDrawer: SizedBox(
width: double.infinity,
child: Drawer(
elevation: 16,
child: Container(
color: Colors.black,
child: ListView(
padding: EdgeInsets.zero,
children: <Widget>[
ListTile(
title: Text('Some context here',
style: TextStyle(color: Colors.white))),
ListTile(
title: Text('Some context here',
style: TextStyle(color: Colors.white))),
],
),
),
),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Call Drawer form menu reproducer',
)
],
),
),
);
}
}
class BottomMenu extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 15),
child: Wrap(
alignment: WrapAlignment.center,
children: <Widget>[
Divider(color: Colors.black, height: 1),
Padding(
padding: const EdgeInsets.symmetric(vertical: 2),
child: Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
InkWell(
borderRadius: new BorderRadius.circular(20.0),
customBorder: Border.all(color: Colors.black),
child: Container(
padding: EdgeInsets.only(
left: 3, right: 6, bottom: 15, top: 11),
child: Row(
children: <Widget>[
Icon(Icons.menu),
Text('Show menu', style: TextStyle(fontSize: 15, fontWeight: FontWeight.bold)),
],
),
),
onTap: () {
Scaffold.of(context).openDrawer();
},
),
],
),
),
],
),
);
}
}
In my case, this worked.
return Scaffold(
key: _scaffoldKey,
endDrawerEnableOpenDragGesture: false, // This!
appBar: AppBar(
iconTheme: IconThemeData(color: Colors.white),
leading: IconButton(
icon: Icon(Icons.menu, size: 36),
onPressed: () => _scaffoldKey.currentState.openDrawer(), // And this!
),
),
drawer: DrawerHome(),
....
and _scaffoldKey must be initialized as,
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
under the class.
The problem is that you specified endDrawer on Scaffold yet you're calling Scaffold.of(context).openDrawer().
openDrawer() documentation states:
If the scaffold has a non-null Scaffold.drawer, this function will cause the drawer to begin its entrance animation.
Since your drawer is null, nothing happens.
In contrast, openEndDrawer() informs us:
If the scaffold has a non-null Scaffold.endDrawer, this function will cause the end side drawer to begin its entrance animation.
Since your endDrawer is not null you should use openEndDrawer() method. Alternatively, if you don't care which side the drawer slides in from, you can use drawer instead of endDrawer when building Scaffold.
My problem solved that instead of
Scaffold.of(context).openEndDrawer()
I give key to Scaffold and then I call by state like below
_scaffoldkey.currentState.openEndDrawer()
It solved my problem I hope It also works for you
Scaffold.of(context).openEndDrawer()
The Problem
This issue can occur when you do not use the correct BuildContext when calling Scaffold.of(context).openDrawer() (or openEndDrawer()).
Easiest Solution
Simply wrap whatever calls openDrawer() (or openEndDrawer()) with a Builder widget. This will give it a working context.
Minimal Working Example
// your build method
#override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: Builder(builder: (context) { // this uses the new context to open the drawer properly provided by the Builder
return FloatingActionButton(onPressed: (() => Scaffold.of(context).openDrawer()));
}),
drawer: const Drawer(
child: Text("MY DRAWER"),
),
);
}
Similar problem here. Clicked on button and nothing happened. The problem is I was using the context of the widget that instantiated Scaffold. Not the context of a child of Scaffold.
Here is how I solved it:
// body: Column(
// children: <Widget>[
// Row(
// children: <Widget>[
// IconButton(
// icon: Icon(Icons.filter_list),
// onPressed: () => Scaffold.of(context).openEndDrawer(), (wrong context)
// ),
// ],
// ),
// ],
// )
To:
body: Builder(
builder: (context) => Column(
children: <Widget>[
Row(
children: <Widget>[
IconButton(
icon: Icon(Icons.filter_list),
onPressed: () => Scaffold.of(context).openEndDrawer(),
),
],
),
],
)),
),
Assign Drawer to drawer property in scaffold. Wrap your specific Widget/Button(where you want to open drawer on its click method) with Builder. Use below method on click property:
enter image description here
Scaffold.of(context).openDrawer();
If you have the appbar widget with an action button to launch the drawer and the drawer is never pushed please remember that you need to define after appbar: ... the endDrawer: YOURAppDrawerWIDGET(), or else using the Scaffold.of(context).openEndDrawer() will not work.
Scaffold(
appBar: AppBar(title: Text(_title)),
endDrawer: AppDrawer(), // <-- this is required or else it will not know what is opening
body: SingleChildScrollView(
///...
I get this curious error for following simple code:
The named parameter children isnt defined.
import 'package:flutter/material.dart';
class Test extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Welcome to Flutter'),
),
body: Center(
children: <Widget>[
Text('Hello World'),
RaisedButton(
onPressed: null,
child: const Text('Disabled Button'),
)
]),
);
}
}
Can anyone spot the mistake? I think I am blind...
Best Regards.
Center doesn't accept children, only child (one widget), you can add a Column inside your Center
Center(
child: Column(children: <Widget>[
Text('Hello World'),
RaisedButton(
onPressed: null,
child: const Text('Disabled Button'),
)
])
),
I've implemented a Drawer in my Flutter app.
Closed Drawer:
Opened Drawer:
As you can see, the Drawer is on top of the Appbar. Before I started the app on Flutter, we had a native Android app with a Drawer that used to look like this:
Closed Drawer:
Opened Drawer:
Here is my code:
class MyDrawer extends StatelessWidget {
#override
Widget build(BuildContext context) {
return _buildDrawer(context);
}
}
Widget _buildDrawer(BuildContext context) {
return new Drawer(
child: new ListView(
children: <Widget>[
_buildDrawerItem(context, EnumDrawerItem.PROJECT_SELECTION, Icons.home, Colors.transparent),
new Divider(height: 20.0),
_buildDrawerItem(context, EnumDrawerItem.TASK_LIST, Icons.home, Colors.transparent),
new Divider(),
_buildDrawerItem(context, EnumDrawerItem.GUIDED_TASKS, Icons.home, Colors.transparent),
new Divider(),
_buildDrawerItem(context, EnumDrawerItem.PHOTOS, Icons.home, Colors.transparent),
new Divider(),
_buildDrawerItem(context, EnumDrawerItem.DOCUMENTS, Icons.home, Colors.transparent),
new Divider(),
_buildDrawerItem(context, EnumDrawerItem.LOG_OUT, Icons.home, const Color(0x85bf0202)),
new Divider(),
],
),
);
}
Widget _buildDrawerItem(BuildContext context, EnumDrawerItem drawerItem, IconData iconData, Color color) {
return Container(
color: color,
child: new Padding(
padding: new EdgeInsets.all(7.0),
child: new Row(
children: <Widget>[
new Icon(iconData),
new Container(
margin: new EdgeInsets.fromLTRB(10.0, 0.0, 0.0, 0.0),
child: new Text(
drawerItem.toString(),
style: styleDrawerItem,
),
),
],
),
),
);
}
I know this is the standard Material Design style, but the client wants it as it was before.
Would it be possible to implemented it as in the 2 last screenshots? Do you have any idea?
Wrap your main Scaffold in another Scaffold and use the drawer of child Scaffold also make sure to set automaticallyImplyLeading to false so you don't get back icon in the AppBar
UPDATE :
i don't recommend this way because of this issue
return Scaffold(
primary: true,
appBar: AppBar(
title: Text("Parent Scaffold"),
automaticallyImplyLeading: false,
),
body: Scaffold(
drawer: Drawer(),
),
);
Final Result :
I use the key in scaffold and references in leading in scaffold principal how in the example
GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey();
return Scaffold(
appBar: AppBar(
title: Text('Draw'),
leading: IconButton(
icon: Icon(Icons.dehaze),
onPressed: () {
if (_scaffoldKey.currentState.isDrawerOpen == false) {
_scaffoldKey.currentState.openDrawer();
} else {
_scaffoldKey.currentState.openEndDrawer();
}
})),
body: Scaffold(
key: _scaffoldKey,
drawer: Drawer(),
body: Center(
child: Text('Drawer'),
),
),
);
Try this one:
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
var statusBarHeight = MediaQuery.of(context).padding.top;
var appBarHeight = kToolbarHeight; //this value comes from constants.dart and equals to 56.0
return Scaffold(
drawerScrimColor: Colors.transparent,
appBar: AppBar(),
drawer: Container(
padding: EdgeInsets.only(top: statusBarHeight+ appBarHeight + 1),//adding one pixel for appbar shadow
width: MediaQuery.of(context).size.width,
child: Drawer(),//write your drawer code
),
body: AnyBody(), //add your body
bottomNavigationBar: AnyNavigationBar(), //add your navigation bar
);
}
}
Simple and to the point:
drawer: Padding(
padding: const EdgeInsets.fromLTRB(0, 80, 0, 0),
child: Drawer(),