因此,在网络上有很多示例,您可以使用隐藏在滚动条上的SliverAppBar
,并且下面的TabBar
仍在显示。我找不到其他可以解决问题的方法:向上滚动时,我只想隐藏TabBar
,使AppBar
始终保持显示状态。有人知道如何实现这一目标吗?
Here is a example with AppBar hiding(这不是我想要的,只是有助于更好地了解我想要的东西)。
答案 0 :(得分:4)
此处是您的操作方式,想法是是在postframecallback
的帮助下使用GlobalKey
来预先计算{ {1}}并添加如下所示的appBar height
exapandedHeight
编辑:
经过更多调查,我发现仅使用import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin {
TabController _tabController;
GlobalKey _appBarKey;
double _appBarHight;
@override
void initState() {
_appBarKey = GlobalKey();
_tabController = TabController(length: 3, vsync: this);
SchedulerBinding.instance.addPostFrameCallback(_calculateAppBarHeight);
super.initState();
}
_calculateAppBarHeight(_){
final RenderBox renderBoxRed = _appBarKey.currentContext.findRenderObject();
setState(() {
_appBarHight = renderBoxRed.size.height;
});
print("AppbarHieght = $_appBarHight");
}
@override
Widget build(BuildContext context) {
// 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,
expandedHeight: _appBarHight,
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(
key: _appBarKey,
child: Positioned(
top: 0.0,
left: 0.0,
right: 0.0,
child: AppBar(
backgroundColor: Colors.red,
iconTheme: IconThemeData(
color: Colors.red, //change your color here
),
automaticallyImplyLeading: true,
elevation: 0,
title: Text("My Title"),
centerTitle: true,
),
),
),
],
),
);
}
}
class MyScreen1 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
child: Center(
child: Text("My Screen 1"),
),
);
}
}
class MyScreen2 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
child: Center(
child: Text("My Screen 2"),
),
);
}
}
class MyScreen3 extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
child: Center(
child: Text("My Screen 3"),
),
);
}
}
Widget即可解决不包含键或MediaQuery“ stuff”的解决方案。请检查以下完整代码:
SafeArea
答案 1 :(得分:1)
您非常接近,我刚刚修改了几行。我没有使用GlobalKey
和其他东西(postFrameCallback
等)来做到这一点。这是非常简单直接的方法。
您需要做的就是用自己的小部件FlutterLogo
,MyScreen1
和MyScreen2
替换MyScreen3
。
void main() => runApp(MaterialApp(home: HomePage()));
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> with SingleTickerProviderStateMixin {
TabController _tabController;
@override
void initState() {
super.initState();
_tabController = TabController(length: 3, vsync: this);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: <Widget>[
NestedScrollView(
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
SliverAppBar(
floating: true,
snap: true,
pinned: true,
bottom: PreferredSize(
preferredSize: Size(0, kToolbarHeight),
child: TabBar(
controller: _tabController,
tabs: [
Tab(child: Text("1")),
Tab(child: Text("2")),
Tab(child: Text("3")),
],
),
),
),
];
},
body: TabBarView(
controller: _tabController,
children: [
FlutterLogo(size: 300, colors: Colors.blue), // use MyScreen1()
FlutterLogo(size: 300, colors: Colors.orange), // use MyScreen2()
FlutterLogo(size: 300, colors: Colors.red), // use MyScreen3()
],
physics: NeverScrollableScrollPhysics(),
),
),
Positioned(
top: 0.0,
left: 0.0,
right: 0.0,
child: MediaQuery.removePadding(
context: context,
removeBottom: true,
child: AppBar(
iconTheme: IconThemeData(color: Colors.red),
automaticallyImplyLeading: true,
elevation: 0,
title: Text("My Title"),
centerTitle: true,
),
),
),
],
),
);
}
}
答案 2 :(得分:0)
我认为使用嵌套脚手架非常容易。在这里您不需要计算任何高度。只需将标签栏放在SilverAppBar 内,而不在SilverAppBar下方。
如果不能解决您的问题,请随时发表评论。
示例:
return Scaffold(
appBar: AppBar(), //your appbar that doesnt need to hide
body: Scaffold(
appBar: SilverAppBar(
pinned: false,
floating: false,
flexibleSpace: new Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
new TabBar() //your tabbar that need to hide when scrolling
])
)
body: //your content goes here
)
);