将TabBar像SliverAppBar一样隐藏

时间:2019-05-29 17:10:26

标签: flutter dart

因此,在网络上有很多示例,您可以使用隐藏在滚动条上的SliverAppBar,并且下面的TabBar仍在显示。我找不到其他可以解决问题的方法:向上滚动时,我只想隐藏TabBar ,使AppBar始终保持显示状态。有人知道如何实现这一目标吗?

Here is a example with AppBar hiding(这不是我想要的,只是有助于更好地了解我想要的东西)。

3 个答案:

答案 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)

屏幕截图(Android)

enter image description here

屏幕截图(iPhone X)

enter image description here


您非常接近,我刚刚修改了几行。我没有使用GlobalKey和其他东西(postFrameCallback等)来做到这一点。这是非常简单直接的方法。

您需要做的就是用自己的小部件FlutterLogoMyScreen1MyScreen2替换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

             )

);