没有 AppBar 的 Flutter TabBar
Posted
技术标签:
【中文标题】没有 AppBar 的 Flutter TabBar【英文标题】:Flutter TabBar Without AppBar 【发布时间】:2018-11-09 13:53:13 【问题描述】:我正在尝试创建一个没有 AppBar 的选项卡式栏布局屏幕。我已经在此链接上提到了解决方案:how to create the tab bar without app bar in flutter? 但它对我不起作用。当我将 TabBar 放在 appbar:
参数中时,我的屏幕如下所示:
我的 TabBar 已移至状态栏下方的左上角,并且全部挤在一个角落。就好像它根本不存在一样。
当我使用 AppBar 类但只传递 bottom:
参数时,会发生以下情况:
TabBar 顶部有一个丑陋的空间,显然是为 AppBar 标题设计的。这是我的代码:
return new Scaffold(
appBar: new TabBar(
tabs: widget._tabs.map((_Page page)
return Text(page.tabTitle);
).toList(),
controller: _tabController,
isScrollable: true,
),
backgroundColor: Colors.white,
body: new TabBarView(
controller: _tabController,
children: widget._tabs.map((_Page page)
return new SafeArea(
top:false,
bottom: false,
child: (page.page == Pages.cart?new CartHomeScreen():_lunchesLayout())
);
).toList()
),
);
我怎样才能让 TabBar 顶部没有那个空间?是否可以让两个选项卡项及其指示器拉伸并填充侧面空间?
【问题讨论】:
你能发布预期的结果截图吗? 【参考方案1】:您的第一个屏幕截图实际上显示它运行良好 - 问题是“良好”并不是您所期望的。标签栏的默认文本颜色为白色,因此您的标签不会显示,而只是底线,这就是您在左上角看到的内容。此外,TabBar 已经是首选尺寸小部件,但它与 AppBar 的高度不同,因此如果您要这样做,它看起来不会像它。
这是一个使它看起来像应用栏的示例。 kToolbarHeight
与 AppBar 使用的常量相同。
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatefulWidget
@override
State<StatefulWidget> createState() => new MyAppState();
class MyAppState extends State<MyApp>
@override
Widget build(BuildContext context)
return new MaterialApp(
title: 'msc',
home: new DefaultTabController(
length: 2,
child: new Scaffold(
appBar: new PreferredSize(
preferredSize: Size.fromHeight(kToolbarHeight),
child: new Container(
color: Colors.green,
child: new SafeArea(
child: Column(
children: <Widget>[
new Expanded(child: new Container()),
new TabBar(
tabs: [new Text("Lunches"), new Text("Cart")],
),
],
),
),
),
),
body: new TabBarView(
children: <Widget>[
new Column(
children: <Widget>[new Text("Lunches Page")],
),
new Column(
children: <Widget>[new Text("Cart Page")],
)
],
),
),
),
);
结果如下:
编辑:
正如 cmets 和 this github issue 中所述,您还可以使用 AppBar 的 flexibleSpace 属性来保持标签栏的效果基本相同:
return new DefaultTabController(
length: 3,
child: new Scaffold(
appBar: new AppBar(
flexibleSpace: new Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
new TabBar(
tabs: [
new Tab(icon: new Icon(Icons.directions_car)),
new Tab(icon: new Icon(Icons.directions_transit)),
new Tab(icon: new Icon(Icons.directions_bike)),
],
),
],
),
),
),
);
【讨论】:
你能解释一下给tabbar一些提升或阴影效果看起来像一个appbar吗? @JayMungara 如果您查看the source code of appbar,您会发现他们使用Material
并设置了高程属性来显示阴影。你也可以这样做——用Material
替换容器并以相同的方式设置高度可能是最简单的。如果您对此有疑问,这似乎是一个新问题的候选者。
这个答案很好,但我更喜欢使用flexibleSpace
而不是 appBar (我的用例)。看看github.com/flutter/flutter/issues/17459#issuecomment-387984398
@Touch 感谢您的建议,我已将其添加到答案中,因为 cmets 有时会迷路 =D【参考方案2】:
按照下面的代码进行
import 'package:flutter/material.dart';
void main()
runApp(MyApp());
class MyApp extends StatelessWidget
@override
Widget build(BuildContext context)
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(),
);
class MyHomePage extends StatefulWidget
@override
_MyHomePageState createState() => _MyHomePageState();
class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin
TabController _tabController;
@override
void initState()
_tabController = new TabController(length: 2, vsync: this);
super.initState();
@override
Widget build(BuildContext context)
return Scaffold(
body: Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
height: MediaQuery.of(context).size.height / 2,
child: Center(
child: Text(
"Tabbar with out Appbar",
style: TextStyle(
color: Colors.white, fontWeight: FontWeight.bold),
),
),
color: Colors.blue,
),
TabBar(
unselectedLabelColor: Colors.black,
labelColor: Colors.red,
tabs: [
Tab(
text: '1st tab',
),
Tab(
text: '2 nd tab',
)
],
controller: _tabController,
indicatorSize: TabBarIndicatorSize.tab,
),
Expanded(
child: TabBarView(
children: [
Container(child: Center(child: Text('people'))),
Text('Person')
],
controller: _tabController,
),
),
],
),
),
);
查看结果
【讨论】:
这正是我所需要的。谢谢你。但记得处理掉tabController
谢谢!这就是 TabBar
没有 Scaffold
的答案。【参考方案3】:
我从 rmtmckenzie 获取代码,但只是为了创建一个没有材料应用程序的小部件
return new DefaultTabController(
length: 3,
child: new Scaffold(
appBar: new PreferredSize(
preferredSize: Size.fromHeight(kToolbarHeight),
child: new Container(
height: 50.0,
child: new TabBar(
tabs: [
Tab(icon: Icon(Icons.directions_car,color: Colors.grey,)),
Tab(icon: Icon(Icons.directions_transit,color: Colors.grey)),
Tab(icon: Icon(Icons.directions_bike,color: Colors.grey)),
],
),
),
),
body: TabBarView(
children: [
Icon(Icons.directions_car),
Icon(Icons.directions_transit),
Icon(Icons.directions_bike),
],
),
),
);
【讨论】:
我得到“底部溢出 2 个像素” 没有scaffold()有没有办法使用tabbar?【参考方案4】:您不需要使用appBar
属性:
Scaffold(
body: Column(
children: [
TabBar( // <-- Your TabBar
tabs: [
Tab(icon: Icon(Icons.camera)),
Tab(icon: Icon(Icons.settings)),
],
),
Expanded(
child: TabBarView( // <-- Your TabBarView
children: [
Container(color: Colors.blue),
Container(color: Colors.red),
],
),
),
],
),
)
【讨论】:
【参考方案5】:只使用flexiblespace 道具而不是appBar 的底部道具。 全部在 safeArea 小部件中,您可以添加一些垂直填充。
home: SafeArea(
top: true,
child: Padding(
padding: const EdgeInsets.only(top: 10.0),
child: DefaultTabController(
length: 3,
child: Scaffold(
appBar: AppBar(
flexibleSpace: TabBar(
tabs: [
Tab(icon: Icon(Icons.1)),
Tab(icon: Icon(Icons.2)),
Tab(icon: Icon(Icons.3)),
],
),
),
body: TabBarView(
children: [
Icon(Icons.1),
Icon(Icons.2),
Icon(Icons.3),
],
),
),
),
),
)
【讨论】:
【参考方案6】:只需在AppBar
小部件中使用toolbarHeight
属性和kMinInteractiveDimension
值,如下所示:
Scaffold(
appBar: AppBar(
toolbarHeight: kMinInteractiveDimension,
bottom: TabBar(
controller: _tabController,
tabs: [], // your tab bars
),
),
body: TabBarView(
controller: _tabController,
children: [], // your tab views
),
);
【讨论】:
【参考方案7】:在appBar
属性中直接使用TabBar
:
@override
Widget build(BuildContext context)
return DefaultTabController(
length: 2,
child: Scaffold(
appBar: TabBar(
tabs: [
Tab(icon: Icon(Icons.call)),
Tab(icon: Icon(Icons.message)),
],
),
body: TabBarView(
children: [
Center(child: Text('Call')),
Center(child: Text('Message')),
],
),
),
);
【讨论】:
非常感谢,这非常有效。而且很简单【参考方案8】:很简单,您只需提供height
到您的TabView
。
这是一个简单的例子。您可以使用DefaultTabController
或TabController
。为了完全可定制,我将使用TabController
。
_getTabBar
函数返回选项卡列表。
TabBar _getTabBar()
return TabBar(
tabs: <Widget>[
Tab(icon: Icon(Icons.home, color: Colors.redAccent)),
Tab(icon: Icon(Icons.settings, color: Colors.redAccent)),
],
controller: tabController,
);
_getTabBarView
将小部件列表作为输入参数并创建一个选项卡视图。
TabBarView _getTabBarView(tabs)
return TabBarView(
children: tabs,
controller: tabController,
);
SafeArea
用于将内容移动到状态栏下方。 _getTabBarView
被 Container
包裹,这样我们就可以分配一个高度。这是分配高度的一种方式,您也可以使用其他方式。
这里是完整的代码,包裹在MaterialApp
中,你就有了一个完全可定制的标签栏和视图。生命周期方法用于创建和处置TabController
import 'package:flutter/material.dart';
class TabControllerScreen extends StatefulWidget
@override
_TabControllerScreenState createState() => _TabControllerScreenState();
class _TabControllerScreenState extends State<TabControllerScreen> with SingleTickerProviderStateMixin
TabController tabController;
@override
void initState()
super.initState();
tabController = TabController(length: 2, vsync: this);
@override
void dispose()
tabController.dispose();
super.dispose();
TabBar _getTabBar()
return TabBar(
tabs: <Widget>[
Tab(icon: Icon(Icons.home, color: Colors.redAccent)),
Tab(icon: Icon(Icons.settings, color: Colors.redAccent)),
],
controller: tabController,
);
TabBarView _getTabBarView(tabs)
return TabBarView(
children: tabs,
controller: tabController,
);
@override
Widget build(BuildContext context)
return Scaffold(
body: SafeArea(
child: Column(
children: <Widget>[
_getTabBar(),
Container(
height: 100,
child: _getTabBarView(
<Widget>[
Icon(Icons.home),
Icon(Icons.settings),
],
),
)
],
),
),
);
【讨论】:
【参考方案9】:根据 CopsOnRoad 的回答,我创建了一个隐藏的 TabBar,如下所示:
Scaffold(
body: Column(
children: [
TabBar( // <-- Hidden TabBar
indicator: BoxDecoration(),
tabs: [
SizedBox.shrink(),
SizedBox.shrink(),
],
),
Expanded(
child: TabBarView( // <-- Your TabBarView
children: [
Container(color: Colors.blue),
Container(color: Colors.red),
],
),
),
],
),
)
【讨论】:
【参考方案10】:尝试将TabBar
放入AppBar
的flexibleSpace
属性中。
【讨论】:
以上是关于没有 AppBar 的 Flutter TabBar的主要内容,如果未能解决你的问题,请参考以下文章