【发布时间】:2018-11-18 17:54:14
【问题描述】:
有谁知道我如何根据此处显示的材料指南创建具有多行标题的应用栏?
https://material.io/design/components/app-bars-top.html#anatomy
任何想法如何做到这一点?鉴于它是材料指南的一部分,它似乎应该很简单!值得指出的是,标题是用户定义的,所以我想让应用栏根据用户输入从单行扩展到多行(可能有限制)。
迈克
【问题讨论】:
有谁知道我如何根据此处显示的材料指南创建具有多行标题的应用栏?
https://material.io/design/components/app-bars-top.html#anatomy
任何想法如何做到这一点?鉴于它是材料指南的一部分,它似乎应该很简单!值得指出的是,标题是用户定义的,所以我想让应用栏根据用户输入从单行扩展到多行(可能有限制)。
迈克
【问题讨论】:
这还没有实现。
但是,您可以使用为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("..."),
);
}
【讨论】:
您可以使用富文本:
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
),
【讨论】:
这段代码将创建一个自定义Scaffold 和一个AppBar,它支持接收无标题、标题和标题和副标题。如果您不提供标题,它将显示给定文本(在示例中,应用程序的名称),而如果您设置标题和副标题,它将使用带有适当材质的两行样式设计文字样式。
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));
}
}
【讨论】: