gpt4 book ai didi

flutter - 像 SliverAppBar 一样隐藏 TabBar

转载 作者:IT老高 更新时间:2023-10-28 12:34:26 27 4
gpt4 key购买 nike

所以网上有很多例子,你可以使用在滚动时隐藏的 SliverAppBar,而下面的 TabBar 仍然显示。我找不到任何相反的方法:当我向上滚动 我只想隐藏 TabBar,保留 AppBar一直持续显示。有谁知道如何做到这一点?

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

更新

这是我迄今为止尝试过的,我认为它有效,但问题是我无法让 Positioned 字段中的 AppBar 获得正确的高度(例如 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,

),
),
),

],

),
);

最佳答案

这里是如何做到这一点的,想法是使用postframecallbackGlobalKey 的帮助下预先计算 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"),
),
);
}
}

编辑:

经过更多调查,我发现了一个没有键或 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<MyHomePage> 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: <Widget>[
NestedScrollView(

headerSliverBuilder:
(BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
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"),
),
);
}
}

关于flutter - 像 SliverAppBar 一样隐藏 TabBar,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56365534/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com