Does anyone know how I can create an app bar with a multi-line title, as per the material guidelines show here?
https://material.io/design/components/app-bars-top.html#
You can use RichText:
SliverAppBar(
flexibleSpace: FlexibleSpaceBar(
background: Container(
color: Colors.indigoAccent,
),
title: RichText(
text: TextSpan(children: [
TextSpan(
text: Constants.homePageTitle,
style: textTheme.headline,
),
TextSpan(text: "\n"),
TextSpan(
text: Constants.homePageSubtitle,
style: textTheme.subtitle,
)
]),
),
titlePadding: EdgeInsets.only(left: 10, bottom: 20),
),
floating: true,
backgroundColor: Colors.greenAccent,
expandedHeight: 150.0,
),
AppBar will let you get close to this, however you do have to indicate the height of the bottom PreferredSize widget, according to your text length, which isn't ideal.
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.deepPurple,
leading: IconButton(icon: Icon(Icons.menu), onPressed: () {}),
actions: <Widget>[
IconButton(icon: Icon(Icons.search), onPressed: () {}),
IconButton(icon: Icon(Icons.more_vert), onPressed: () {}),
],
bottom: PreferredSize(
child: Padding(
padding: const EdgeInsets.fromLTRB(80.0, 0.0, 80.0, 16.0),
child: Text(
"Summer Trip to Tokyo and Kyoto",
style: TextStyle(
color: Colors.white,
fontSize: 24.0,
),
),
),
preferredSize: Size(0.0, 80.0),
),
),
body: Text("..."),
);
}
This can be achieved by replacing the "title" property of AppBar with "flexibleSpace":
Scaffold(
appBar: AppBar(
flexibleSpace: Center(
child: Column(
children: [
Text('Title Line One'),
Text('Title Line Two'),
],
),
),
),
body: body
),
If overflow occurs due to height, just wrap AppBar with a PreferredSize widget and set the height to a higher value than the default one:
Scaffold(
appBar: PreferredSize(
preferredSize: Size.fromHeight(100),
child: AppBar(...),
),
),
This is not implemented yet.
However you can achieve similar results by using SliverAppBar
designed for CustomScrollView
.
Bear in mind that this is not optimal though. As it required hard coding the size of the icons and stuff. Due to FlexibleSpacebar
not having width constraint.
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter_project/materialSheet.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(
slivers: <Widget>[
SliverMultilineAppBar(
title: "Summer Trip to Tokyo and Kyoto",
leading: IconButton(
onPressed: () {},
icon: Icon(Icons.menu),
),
actions: <Widget>[
IconButton(
onPressed: () {},
icon: Icon(Icons.search),
),
IconButton(
onPressed: () {},
icon: Icon(Icons.more_vert),
),
],
),
],
),
);
}
}
class SliverMultilineAppBar extends StatelessWidget {
final String title;
final Widget leading;
final List<Widget> actions;
SliverMultilineAppBar({this.title, this.leading, this.actions});
@override
Widget build(BuildContext context) {
final mediaQuery = MediaQuery.of(context);
double availableWidth = mediaQuery.size.width - 160;
if (actions != null) {
availableWidth -= 32 * actions.length;
}
if (leading != null) {
availableWidth -= 32;
}
return SliverAppBar(
expandedHeight: 120.0,
forceElevated: true,
leading: leading,
actions: actions,
flexibleSpace: FlexibleSpaceBar(
title: ConstrainedBox(
constraints: BoxConstraints(
maxWidth: availableWidth,
),
child: Text(title, textScaleFactor: .8,),
),
),
);
}
}
This piece of code will create a custom Scaffold
with an AppBar
that supports receiving no title, a title, and a title and a subtitle. In case you don't provide a title, it will show a given text (in the example, the name of the app), while in case you set a title and a subtitle, it will use a two lines style with the proper Material Design text style.
import 'package:flutter/material.dart';
class TwoLinesAppBarScaffold extends StatelessWidget {
final Widget body;
final String title;
final String subtitle;
TwoLinesAppBarScaffold({this.body, this.title = "QuitNow!", this.subtitle});
@override
Widget build(BuildContext context) {
Widget widget;
if (subtitle == null) {
widget = Text(title);
} else {
widget = RichText(
textAlign: TextAlign.start,
text: TextSpan(
text: title,
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.w500,
),
children: <TextSpan>[
TextSpan(
text: '\n$subtitle',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.normal,
),
),
]),
);
}
return Scaffold(
appBar: AppBar(
title: widget,
),
body: Center(child: body));
}
}
Try below code. This will give multi-line where you can also control the text styling. Use Text instead of RichText if you do not want different style for all the lines.
AppBar(
title: RichText(
textAlign: TextAlign.center,
text: TextSpan(
text: "Developer Developer",
style: TextStyle(fontSize: 20),
children: <TextSpan>[
TextSpan(
text: '\nTrip List',
style: TextStyle(
fontSize: 16,
),
),
]
),
),
backgroundColor: MissionGPSTheme.themeBlueColor
),