因此,在Web上有许多示例,您可以使用滚动时隐藏的SliverAppBar,下面的TabBar仍然显示。我找不到任何相反的方法:当我向上滚动时,我只想隐藏TabBar,使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: [

NestedScrollView(

headerSliverBuilder:

(BuildContext context, bool innerBoxIsScrolled) {

return [

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,

),

),

),

],

),

);

最佳答案:

你可以这样做,我们的想法是在一个postframecallback的帮助下使用一个GlobalKey来预先计算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 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: [

NestedScrollView(

headerSliverBuilder:

(BuildContext context, bool innerBoxIsScrolled) {

return [

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"),

),

);

}

}

编辑:

经过更多的调查,我发现了一个没有键或MediaQuery“东西”的解决方案,只使用了SafeArea小部件。请检查以下完整代码:

import 'package:flutter/material.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 with SingleTickerProviderStateMixin {

TabController _tabController;

@override

void initState() {

_tabController = TabController(length: 3, vsync: this);

super.initState();

}

@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: [

NestedScrollView(

headerSliverBuilder:

(BuildContext context, bool innerBoxIsScrolled) {

return [

SliverAppBar(

primary: true,

floating: true,

backgroundColor: Colors.blue,//.withOpacity(0.3),

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.

// by using SafeArea it will.

Positioned(

top: 0.0,

left: 0.0,

right: 0.0,

child: Container(

child: SafeArea(

top: false,

child: AppBar(

backgroundColor: Colors.blue,

// 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(

color: Colors.yellow,

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"),

),

);

}

}

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐