How can I simply set the height of the AppBar in Flutter?
The title of the bar should be staying centered vertically (in that AppBar).
You can use PreferredSize:
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Example',
home: Scaffold(
appBar: PreferredSize(
preferredSize: Size.fromHeight(50.0), // here the desired height
child: AppBar(
// ...
)
),
body: // ...
)
);
}
}
Use toolbarHeight:
There's no longer a need to use PreferredSize. Use toolbarHeight with flexibleSpace.
AppBar(
toolbarHeight: 120, // Set this height
flexibleSpace: Container(
color: Colors.orange,
child: Column(
children: [
Text('1'),
Text('2'),
Text('3'),
Text('4'),
],
),
),
)
You can use PreferredSize and flexibleSpace for it:
appBar: PreferredSize(
preferredSize: Size.fromHeight(100.0),
child: AppBar(
automaticallyImplyLeading: false, // hides leading widget
flexibleSpace: SomeWidget(),
)
),
This way you can keep the elevation of AppBar for keeping its shadow visible and have custom height, which is what I was just looking for. You do have to set the spacing in SomeWidget, though.
The easiest way is to use toolbarHeight property in your AppBar
Example :
AppBar(
title: Text('Flutter is great'),
toolbarHeight: 100,
),
You can add flexibleSpace property in your appBar for more flexibility
Output:
For more controls , Use the PreferedSize widget to create your own appBar
Example :
appBar: PreferredSize(
preferredSize: Size(100, 80), //width and height
// The size the AppBar would prefer if there were no other constraints.
child: SafeArea(
child: Container(
height: 100,
color: Colors.red,
child: Center(child: Text('Fluter is great')),
),
),
),
Don't forget to use a SafeArea widget if you don't have a safeArea
Output :
At the time of writing this, I was not aware of PreferredSize. Cinn's answer is better to achieve this.
You can create your own custom widget with a custom height:
import "package:flutter/material.dart";
class Page extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new Column(children : <Widget>[new CustomAppBar("Custom App Bar"), new Container()],);
}
}
class CustomAppBar extends StatelessWidget {
final String title;
final double barHeight = 50.0; // change this for different heights
CustomAppBar(this.title);
#override
Widget build(BuildContext context) {
final double statusbarHeight = MediaQuery
.of(context)
.padding
.top;
return new Container(
padding: new EdgeInsets.only(top: statusbarHeight),
height: statusbarHeight + barHeight,
child: new Center(
child: new Text(
title,
style: new TextStyle(fontSize: 20.0, fontWeight: FontWeight.bold),
),
),
);
}
}
In addition to #Cinn's answer, you can define a class like this
class MyAppBar extends AppBar with PreferredSizeWidget {
#override
get preferredSize => Size.fromHeight(50);
MyAppBar({Key key, Widget title}) : super(
key: key,
title: title,
// maybe other AppBar properties
);
}
or this way
class MyAppBar extends PreferredSize {
MyAppBar({Key key, Widget title}) : super(
key: key,
preferredSize: Size.fromHeight(50),
child: AppBar(
title: title,
// maybe other AppBar properties
),
);
}
and then use it instead of standard one
You can simply use toolbarHeight, as follows:
appBar: AppBar(
toolbarHeight: 70.0, // add this line
centerTitle: true, // add this line
title: Text('your title'),
),
but if you have any actions the code above doesn't work as you want
you can use this code
AppBar(
centerTitle: true,
title: Padding(
padding: const EdgeInsets.all(16.0),
child: Stack(
alignment: Alignment.center,
children: [
Row(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('Chats', style: TextStyle(color:Colors.black),),
Icon(Icons.add, color: Colors.black,),
],
),
Align(
alignment: Alignment.centerRight,
child: Icon(Icons.add, color: Colors.black,),
),
],
),
),
)
Cinn's answer is great, but there's one thing wrong with it.
The PreferredSize widget will start immediately at the top of the screen, without accounting for the status bar, so some of its height will be shadowed by the status bar's height. This also accounts for the side notches.
The solution: Wrap the preferredSize's child with a SafeArea
appBar: PreferredSize(
//Here is the preferred height.
preferredSize: Size.fromHeight(50.0),
child: SafeArea(
child: AppBar(
flexibleSpace: ...
),
),
),
If you don't wanna use the flexibleSpace property, then there's no need for all that, because the other properties of the AppBar will account for the status bar automatically.
simply use toolbar height ...
AppBar(
title: Text("NASHIR'S APP"),
toolbarHeight: 100,
),
You can use the toolbarHeight property of Appbar, it does exactly what you want.
class AppBarWidget extends StatelessWidget with PreferredSizeWidget {
final String title;
const AppBarWidget({Key? key, required this.title}) : super(key: key);
#override`enter code here`
Widget build(BuildContext context) {
return AppBar(
title: Text(title),
centerTitle: true,
elevation: 0,
actions: [
Padding(
padding: const EdgeInsets.only(right: 10),
child: IconButton(
icon: const FaIcon(FontAwesomeIcons.language),
onPressed: () {},
),
),
],
);
}
#override
Size get preferredSize => const Size.fromHeight(40);// change
}
You can use PreferredSize, by this use can set multiple children widget inside their
appBar: PreferredSize(
preferredSize: Size(MediaQuery.of(context).size.width, 75),
child: Column(children: [
AppBar(
centerTitle: true,
toolbarHeight: 74,
backgroundColor: Colors.white,
elevation: 0,
title: Column(
children: [
Text(
viewModel.headingText,
style: sfDisplay16500Text,
),
SizedBox(
height: 8.0,
),
Text(
viewModel.url.toString(),
style: sfDisplay10400LightBlackText,
maxLines: 1,
overflow: TextOverflow.ellipsis,
)
],
),
),
]),
),
or just directly use toolbarHeight property for only increase hight of appBar.
appBar: AppBar(
title: Text('AppBar Texr'),
toolbarHeight: 200.0, // double
),
Extend AppBar class and override preferredSize
class AppBarCustom extends AppBar {
#override
Size get preferredSize => Size.fromHeight(100);
}
then use it as you would use AppBar class
class MyHomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBarCustom(),
body:
),
);
}
}
This is simplest and easiest way to change appbar height without changing original theme.
class AppBarSectionView extends StatefulWidget implements PreferredSizeWidget {
const AppBarSectionView({Key? key}) : super(key: key);
#override
_AppBarSectionViewState createState() => _AppBarSectionViewState();
#override
Size get preferredSize => const Size.fromHeight(kToolbarHeight + 20);
}
class _AppBarSectionViewState extends State<AppBarSectionView> {
#override
Widget build(BuildContext context) {
return AppBar(
toolbarHeight: widget.preferredSize.height ,
backgroundColor: Colors.red,
leading: const Icon(Icons.arrow_back_ios_rounded),
title: const Text("This Is Title"),
);
}
}
If you are in Visual Code, Ctrl + Click on AppBar function.
Widget demoPage() {
AppBar appBar = AppBar(
title: Text('Demo'),
);
return Scaffold(
appBar: appBar,
body: /*
page body
*/,
);
}
And edit this piece.
app_bar.dart will open and you can find
preferredSize = new Size.fromHeight(kToolbarHeight + (bottom?.preferredSize?.height ?? 0.0)),
Difference of height!
Related
So I am trying to make a custom reusable appbar widget like this
class MyCustomAppBar extends StatelessWidget implements PreferredSizeWidget {
const MyCustomAppBar({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
final primaryColor = Theme.of(context).primaryColor;
return AppBar(
backgroundColor: primaryColor,
elevation: 0, // to remove drop shadow
titleSpacing: 0, // to remove extra padding on appbar left side
title: Text("This Is appbar Title"),
);
}
#override
Size get preferredSize => const Size.fromHeight(50.0);
}
and then I use it on my scaffold like this
class NotificationListPage extends StatelessWidget {
const NotificationListPage({Key? key}) : super(key: key);
#override
Widget build(context) {
return Scaffold(
appBar: MyCustomAppBar(),
body: Column(
children: [
Container(
width: double.infinity,
height: 100,
color: Theme.of(context).primaryColor,
child: Center(
child: Text(
"this is container that has the same color with appbar",
style: TextStyle(
fontSize: 10,
),
),
),
),
],
),
);
}
}
and here is the result:
as you can see, there is a white horizontal line between the appbar and the container inside the column. and it will only apppear on Android. how to remove this?
If I change the Scaffold background color to be red, then that horizontal line will turn to be red as well.
I need to make a custom reusable widget. If I implement directly (without widget separation) like the code below, that horizontal line will not appear
class NotificationListPage extends StatelessWidget {
const NotificationListPage({Key? key}) : super(key: key);
#override
Widget build(context) {
final primaryColor = Theme.of(context).primaryColor;
return Scaffold(
appBar: AppBar( // I don't want to implement it directly like this. I want separate Appbar widget
backgroundColor: primaryColor,
elevation: 0, // to remove drop shadow
titleSpacing: 0, // to remove extra padding on appbar left side
title: Text("This Is appbar Title"),
),
body: Column(
children: [
Container(
width: double.infinity,
height: 100,
color: Theme.of(context).primaryColor,
child: Center(
child: Text(
"this is container that has the same color with appbar",
style: TextStyle(
fontSize: 10,
),
),
),
),
],
),
);
}
}
It's because your Scaffold background color is white.
return Scaffold(
backgroundColor: primaryColor,
appBar: AppBar(...
I want to add a Drawer to the icon button but it's outside of appbar
here in this code, I tried to implement it by watching some tutorial but its not working for me maybe cuz I used endDraw anyone have idea how to do it?
here is my code
GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
#override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
endDrawer: Drawer2() ,
appBar: AppBar(
backgroundColor: MyColor.backgroud_primary_color,
leading: Icon(
Icons.chevron_left_rounded,
color: MyColor.icon_color,
),
centerTitle: true,
title: Container(
width: 100,
height: 100,
child: Image(
image: AssetImage("assets/logo.png"),
fit: BoxFit.contain,
),
),
actions: [
Padding(
padding: EdgeInsets.symmetric(horizontal: 5),
child: IconButton(
onPressed: () => _scaffoldKey.currentState!.openDrawer(),
icon: Icon(Icons.sort),
iconSize: 30,
color: MyColor.icon_color,
),
)
],
),
Drawer2() is a custom drawer that I have made I want to open the end drawer when I click on Icon button is there any way?
import 'package:flutter/material.dart';
class DemoScreen extends StatelessWidget {
const DemoScreen({ Key? key }) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Demo Screen"),),
endDrawer: Drawer2(),
body: Center(
child: Text("data")
),
);
}
}
class Drawer2 extends StatelessWidget {
const Drawer2({
Key? key,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Drawer( // Custom widget must be return Drawer
child: ListTile( //Implement any design on child property
title: Text("Demo tile"),
),
);
}
}
Use:
Scaffold.of(context).openEndDrawer()
and if you want to disable the drag behavior set this in Scaffold:
drawerEnableOpenDragGesture: false,
To open the drawer you need to use _scaffoldKey.currentState!.openEndDrawer(),
based on endDrawer docs, here
So, your code should be:
actions: [
Padding(
padding: EdgeInsets.symmetric(horizontal: 5),
child: IconButton(
onPressed: () => _scaffoldKey.currentState!.openEndDrawer(),
icon: Icon(Icons.sort),
iconSize: 30,
color: MyColor.icon_color,
),
)
],
class MyAppBar extends StatelessWidget implements PreferredSizeWidget {
#override
Widget build(BuildContext context) {
final double appBarHeight = MediaQuery.of(context).size.height * .3;
return AppBar(
brightness: Brightness.light,
automaticallyImplyLeading: false, // hides leading widget
title: Padding(
padding: const EdgeInsets.only(top: 15.0),
child: TyperAnimatedTextKit(
speed: Duration(milliseconds: 200),
isRepeatingAnimation: false,
text: [
"SANDRA",
],
textStyle: GoogleFonts.permanentMarker(
fontSize: 30.0, color: Colors.black),
textAlign: TextAlign.start,
alignment: AlignmentDirectional.topStart // or Alignment.topLeft
),
),
centerTitle: true,
backgroundColor: Colors.white,
);
}
#override
Size get preferredSize => Size.fromHeight(88);
}
this is my code, I want to use media queries to make the app responsive in different screens, how can I use media queries in this case instead of 88 at the end of the my code? any suggestions?
Instead of implementing PreferredSizeWidget, you could use PreferredSize:
Widget build(BuildContext context) {
return Scaffold(
appBar: PreferredSize(
preferredSize: Size.fromHeight(MediaQuery.of(context)...),
child: AppBar(...),
),
);
}
My appBar is overflowing when I try to add more widgets to it. It was okay till a certain point, then I wanted to add some upper and lower padding, and then it overflowed. Is there any way I can increase the app Bar Size?
I saw the property preferredSize in docs, however I am unable to use it.
I want my app bar to include a photo icon, some text and another icon in a row. I did in the following way. I know its probably a little crude but wasn't able to figure out any other way.
(p.s i tried leading however it didnt give the desired results )
My code :
return Scaffold(
appBar: AppBar(
// preferredSize
// ERROR: The named paramtere isnt defined
title: Column(
children: <Widget>[,
Row(
children: <Widget>[
SizedBox(width: 10.0),
Container(
width: 50.0,
height: 50.0,
decoration: new BoxDecoration(
shape: BoxShape.circle,
image: new DecorationImage(
fit: BoxFit.fitWidth,
image: new AssetImage('assets/jane.jpg')
)
)),
SizedBox(width: 15.0),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
SizedBox(height: 5.0),
Text('Good Morning!', style: TextStyle(color: Color(0XFF9c9c9c) , fontWeight: FontWeight.w400, fontSize: 16.0)),
Text('Jane Doe ', style: TextStyle(color: Color(0xFF2a2a2a),fontWeight: FontWeight.w700,fontSize: 25.0))
],
),
],
),
],
),
bottom: TabBar(
...),
),
body: (...)
,);
} }
create custom app bar, like this
import 'package:flutter/material.dart';
class CustomAppBar extends StatefulWidget implements PreferredSizeWidget {
CustomAppBar({Key key, this.title}) : preferredSize = Size.fromHeight(56.0), super(key: key);
#override
final Size preferredSize;
final String title;
#override
_CustomAppBarState createState() => _CustomAppBarState();
}
class _CustomAppBarState extends State<CustomAppBar>{
String get title => widget.title;
#override
Widget build(BuildContext context) {
return AppBar(
title: Text(title),
leading: IconButton(
icon: Icon(Icons.arrow_back_ios, size: 20),
onPressed: () => Navigator.pop(context),
),
elevation: 0,
backgroundColor: Colors.transparent,
titleSpacing: 0,
);
}
}
You can do it like this:
AppBar(
title: Text('Sized App Bar'),
bottom: PreferredSize(
child: Text('PreferredSize must have a child'),
preferredSize: Size.fromHeight(10), //Change 10 to which ever size you desire.
),
),
Use a PreferredSize widget on appBar property:
Scaffold(
appBar: PreferredSize(
preferredSize: const Size.fromHeight(150.0), // Change 150.0 for your header height
child: Header()), // Create your Header widget with the title content
body: ...
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(),