展开 Flutter 中的应用栏以允许 Multi-Line 标题?
Expand The App bar in Flutter to Allow Multi-Line Title?
有谁知道如何根据此处显示的 material 指南创建带有 multi-line 标题的应用栏?
https://material.io/design/components/app-bars-top.html#anatomy
有什么办法吗?鉴于它是 material 指南的一部分,它似乎应该很简单!值得指出的是,标题是用户定义的,所以我希望允许应用栏根据用户输入从单行扩展到多行(可能有限制)。
麦克
这还没有实现。
不过,您可以使用为 CustomScrollView
设计的 SliverAppBar
来获得类似的结果。
请记住,这并不是最佳选择。因为它需要硬编码图标和东西的大小。由于 FlexibleSpacebar
没有宽度限制。
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,),
),
),
);
}
}
AppBar 会让您接近这个,但是您必须根据您的文本长度指示底部 PreferredSize 小部件的高度,这并不理想。
@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("..."),
);
}
您可以使用 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的"title"属性换成"flexibleSpace"即可实现:
Scaffold(
appBar: AppBar(
flexibleSpace: Center(
child: Column(
children: [
Text('Title Line One'),
Text('Title Line Two'),
],
),
),
),
body: body
),
如果由于高度而发生溢出,只需用 PreferredSize 小部件包裹 AppBar 并将高度设置为比默认值更高的值:
Scaffold(
appBar: PreferredSize(
preferredSize: Size.fromHeight(100),
child: AppBar(...),
),
),
试试下面的代码。这将提供多行,您还可以在其中控制文本样式。
如果您不希望所有行都使用不同的样式,请使用 Text 而不是 RichText。
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
),
这段代码将创建一个带有 AppBar
的自定义 Scaffold
,支持接收无标题、有标题、有标题和副标题。如果您不提供标题,它将显示给定的文本(在示例中为应用程序的名称),而如果您设置了标题和副标题,它将使用带有适当 Material设计文字样式。
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));
}
}
有谁知道如何根据此处显示的 material 指南创建带有 multi-line 标题的应用栏?
https://material.io/design/components/app-bars-top.html#anatomy
有什么办法吗?鉴于它是 material 指南的一部分,它似乎应该很简单!值得指出的是,标题是用户定义的,所以我希望允许应用栏根据用户输入从单行扩展到多行(可能有限制)。
麦克
这还没有实现。
不过,您可以使用为 CustomScrollView
设计的 SliverAppBar
来获得类似的结果。
请记住,这并不是最佳选择。因为它需要硬编码图标和东西的大小。由于 FlexibleSpacebar
没有宽度限制。
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,),
),
),
);
}
}
AppBar 会让您接近这个,但是您必须根据您的文本长度指示底部 PreferredSize 小部件的高度,这并不理想。
@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("..."),
);
}
您可以使用 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的"title"属性换成"flexibleSpace"即可实现:
Scaffold(
appBar: AppBar(
flexibleSpace: Center(
child: Column(
children: [
Text('Title Line One'),
Text('Title Line Two'),
],
),
),
),
body: body
),
如果由于高度而发生溢出,只需用 PreferredSize 小部件包裹 AppBar 并将高度设置为比默认值更高的值:
Scaffold(
appBar: PreferredSize(
preferredSize: Size.fromHeight(100),
child: AppBar(...),
),
),
试试下面的代码。这将提供多行,您还可以在其中控制文本样式。 如果您不希望所有行都使用不同的样式,请使用 Text 而不是 RichText。
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
),
这段代码将创建一个带有 AppBar
的自定义 Scaffold
,支持接收无标题、有标题、有标题和副标题。如果您不提供标题,它将显示给定的文本(在示例中为应用程序的名称),而如果您设置了标题和副标题,它将使用带有适当 Material设计文字样式。
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));
}
}