因此,网络上有很多示例,您可以SliverAppBar在滚动条上使用隐藏的内容,并且TabBar仍在下面显示。我找不到反过来做的任何事情:当我向上滚动时,我只想隐藏TabBar,AppBar始终保持持续显示。有谁知道如何实现这一目标?
这是一个隐藏AppBar的示例(这不是我想要的,只是有助于更好地了解我想要的东西)。
更新
到目前为止,这是我尝试过的,并且我认为它可以工作,但是问题是我无法AppBar在Positioned野外获得正确的高度(例如,iPhone X的高度更大并且与标签栏重叠)。
// this sliver app bar is only use to hide/show the tabBar, the AppBar
// is invisible at all times. The to the user visible AppBar is below
return Scaffold(
body: Stack(
children: <Widget>[
NestedScrollView(
headerSliverBuilder:
(BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
SliverAppBar(
floating: true,
snap: true,
pinned: false,
bottom: TabBar(
tabs: [
Tab(
child: Text(
"1",
textAlign: TextAlign.center,
),
),
Tab(
child: Text(
"2",
textAlign: TextAlign.center,
),
),
Tab(
child: Text(
"3",
textAlign: TextAlign.center,
),
),
],
controller: _tabController,
),
),
];
},
body: TabBarView(
children: [
MyScreen1(),
MyScreen2(),
MyScreen3(),
],
controller: _tabController,
physics: new NeverScrollableScrollPhysics(),
),
),
// Here is the AppBar the user actually sees. The SliverAppBar
// above will slide the TabBar underneath this one. However,
// I can´t figure out how to give it the correct height.
Container(
child: Positioned(
top: 0.0,
left: 0.0,
right: 0.0,
child: AppBar(
iconTheme: IconThemeData(
color: Colors.red, //change your color here
),
automaticallyImplyLeading: true,
elevation: 0,
title: Text("My Title"),
centerTitle: true,
),
),
),
],
),
);
Run Code Online (Sandbox Code Playgroud)
这是如何做到这一点的,想法是postframecallback在 a 的帮助下使用 aGlobalKey来预先计算appBar height并添加exapandedHeight如下所示的,
import \'package:flutter/material.dart\';\nimport \'package:flutter/scheduler.dart\';\n\nvoid main() => runApp(MyApp());\n\nclass MyApp extends StatelessWidget {\n // This widget is the root of your application.\n @override\n Widget build(BuildContext context) {\n return MaterialApp(\n title: \'Flutter Demo\',\n theme: ThemeData(\n\n primarySwatch: Colors.blue,\n ),\n home: MyHomePage(title: \'Flutter Demo Home Page\'),\n );\n }\n}\n\nclass MyHomePage extends StatefulWidget {\n MyHomePage({Key key, this.title}) : super(key: key);\n\n\n final String title;\n\n @override\n _MyHomePageState createState() => _MyHomePageState();\n}\n\nclass _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin {\n\n TabController _tabController;\n GlobalKey _appBarKey;\n double _appBarHight;\n @override\n void initState() {\n _appBarKey = GlobalKey();\n _tabController = TabController(length: 3, vsync: this);\n SchedulerBinding.instance.addPostFrameCallback(_calculateAppBarHeight);\n super.initState();\n }\n _calculateAppBarHeight(_){\n final RenderBox renderBoxRed = _appBarKey.currentContext.findRenderObject();\n setState(() {\n _appBarHight = renderBoxRed.size.height;\n});\n print("AppbarHieght = $_appBarHight");\n }\n\n @override\n Widget build(BuildContext context) {\n // this sliver app bar is only use to hide/show the tabBar, the AppBar\n // is invisible at all times. The to the user visible AppBar is below\n return Scaffold(\n body: Stack(\n children: <Widget>[\n NestedScrollView(\n headerSliverBuilder:\n (BuildContext context, bool innerBoxIsScrolled) {\n return <Widget>[\n SliverAppBar(\n floating: true,\n expandedHeight: _appBarHight,\n snap: true,\n pinned: false,\n bottom: TabBar(\n tabs: [\n Tab(\n child: Text(\n "1",\n textAlign: TextAlign.center,\n ),\n ),\n Tab(\n child: Text(\n "2",\n textAlign: TextAlign.center,\n ),\n ),\n Tab(\n child: Text(\n "3",\n textAlign: TextAlign.center,\n ),\n ),\n ],\n controller: _tabController,\n ),\n ),\n ];\n },\n body: TabBarView(\n children: [\n MyScreen1(),\n MyScreen2(),\n MyScreen3(),\n ],\n controller: _tabController,\n physics: new NeverScrollableScrollPhysics(),\n ),\n ),\n\n\n // Here is the AppBar the user actually sees. The SliverAppBar\n // above will slide the TabBar underneath this one. However,\n // I can\xc2\xa5t figure out how to give it the correct height.\n Container(\n key: _appBarKey,\n child: Positioned(\n top: 0.0,\n left: 0.0,\n right: 0.0,\n child: AppBar(\n\n backgroundColor: Colors.red,\n iconTheme: IconThemeData(\n color: Colors.red, //change your color here\n ),\n automaticallyImplyLeading: true,\n elevation: 0,\n title: Text("My Title"),\n centerTitle: true,\n\n ),\n ),\n ),\n\n ],\n\n ),\n );\n }\n\n}\n\nclass MyScreen1 extends StatelessWidget {\n @override\n Widget build(BuildContext context) {\n return Container(\n child: Center(\n child: Text("My Screen 1"),\n ),\n );\n }\n}\nclass MyScreen2 extends StatelessWidget {\n @override\n Widget build(BuildContext context) {\n return Container(\n child: Center(\n child: Text("My Screen 2"),\n ),\n );\n }\n}\nclass MyScreen3 extends StatelessWidget {\n @override\n Widget build(BuildContext context) {\n return Container(\n child: Center(\n child: Text("My Screen 3"),\n ),\n );\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n编辑:
\n\n经过更多调查后,我通过仅使用SafeAreaWidget 找到了一个没有键或 MediaQuery“东西”的解决方案。请检查以下完整代码:
import \'package:flutter/material.dart\';\n\nvoid main() => runApp(MyApp());\n\nclass MyApp extends StatelessWidget {\n // This widget is the root of your application.\n @override\n Widget build(BuildContext context) {\n return MaterialApp(\n title: \'Flutter Demo\',\n theme: ThemeData(\n\n primarySwatch: Colors.blue,\n ),\n home: MyHomePage(title: \'Flutter Demo Home Page\'),\n );\n }\n}\n\nclass MyHomePage extends StatefulWidget {\n MyHomePage({Key key, this.title}) : super(key: key);\n\n\n final String title;\n\n @override\n _MyHomePageState createState() => _MyHomePageState();\n}\n\nclass _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin {\n\n TabController _tabController;\n\n @override\n void initState() {\n\n _tabController = TabController(length: 3, vsync: this);\n\n super.initState();\n }\n\n\n @override\n Widget build(BuildContext context) {\n // this sliver app bar is only use to hide/show the tabBar, the AppBar\n // is invisible at all times. The to the user visible AppBar is below\n return Scaffold(\n body: Stack(\n children: <Widget>[\n NestedScrollView(\n\n headerSliverBuilder:\n (BuildContext context, bool innerBoxIsScrolled) {\n return <Widget>[\n SliverAppBar(\n primary: true,\n floating: true,\n backgroundColor: Colors.blue,//.withOpacity(0.3),\n snap: true,\n pinned: false,\n bottom: TabBar(\n tabs: [\n Tab(\n child: Text(\n "1",\n textAlign: TextAlign.center,\n ),\n ),\n Tab(\n child: Text(\n "2",\n textAlign: TextAlign.center,\n ),\n ),\n Tab(\n child: Text(\n "3",\n textAlign: TextAlign.center,\n ),\n ),\n ],\n controller: _tabController,\n ),\n ),\n ];\n },\n body: TabBarView(\n children: [\n MyScreen1(),\n MyScreen2(),\n MyScreen3(),\n ],\n controller: _tabController,\n physics: new NeverScrollableScrollPhysics(),\n ),\n ),\n\n\n // Here is the AppBar the user actually sees. The SliverAppBar\n // above will slide the TabBar underneath this one. \n // by using SafeArea it will.\n Positioned(\n top: 0.0,\n left: 0.0,\n right: 0.0,\n child: Container(\n child: SafeArea(\n top: false,\n child: AppBar(\n backgroundColor: Colors.blue,\n// iconTheme: IconThemeData(\n// color: Colors.red, //change your color here\n// ),\n automaticallyImplyLeading: true,\n elevation: 0,\n title: Text("My Title",),\n centerTitle: true,\n ),\n ),\n ),\n ),\n\n ],\n\n ),\n );\n }\n\n}\n\nclass MyScreen1 extends StatelessWidget {\n @override\n Widget build(BuildContext context) {\n return Container(\n color: Colors.yellow,\n child: Center(\n child: Text("My Screen 1"),\n ),\n );\n }\n}\nclass MyScreen2 extends StatelessWidget {\n @override\n Widget build(BuildContext context) {\n return Container(\n child: Center(\n child: Text("My Screen 2"),\n ),\n );\n }\n}\nclass MyScreen3 extends StatelessWidget {\n @override\n Widget build(BuildContext context) {\n return Container(\n child: Center(\n child: Text("My Screen 3"),\n ),\n );\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
449 次 |
| 最近记录: |