底部导航栏和标签栏导致底部溢出
Bottom overflow due to bottom navigation bar and tab Bar
@override
Widget build(BuildContext context) {
super.build(context);
SystemChrome.setEnabledSystemUIOverlays(SystemUiOverlay.values);
return AnnotatedRegion<SystemUiOverlayStyle>(
value: SystemUiOverlayStyle(
statusBarColor: Colors.transparent,
),
child: Scaffold(
key: _scaffoldKeyProfilePage,
body: DefaultTabController(
length: 2,
child:RefreshIndicator(
onRefresh: _onRefresh,
child: NestedScrollView(
headerSliverBuilder: (context, _) {
return [
SliverList(
delegate: SliverChildListDelegate(
[ BuildMainProfile(
....//
),
Padding(
...//another design
),
];
},
// You tab view goes here
body: Column(
children: <Widget>[
TabBar(
tabs: [
Tab(text: 'A'),
Tab(text: 'B'),
],
),
Expanded(
child: TabBarView(
children: [
BuildPost(,
),
BuildWings()
],
),
),
],
),
),),
),
}
以上是我得到的错误示例
error:A RenderFlex 在底部溢出 48 个像素。
如何解决这个问题?尝试在 TabBar 上使用 expanded 并将 flex 设置为 1 到 tab bar 并将 flex 设置为 10 到 tabView ,但是随着该选项卡栏在向下滚动时会缩小。
下面是 tabBar 视图 A 和 B 的代码甚至相似
class BuildPost extends StatefulWidget {
final String uid;
const BuildPost({
Key key,
@required this.uid,
}) : super(key: key);
@override
_BuildPostState createState() => _BuildPostState();
}
class _BuildPostState extends State<BuildPost> {
List<Post> _post = [];
getUsersPost() async {
final database = FirestoreDatabase();
List<Post> _postModel = await database.getUsersPost(widget.uid);
setState(() {
_post = _postModel.toList();
});
}
@override
void initState() {
getUsersPost();
super.initState();
}
@override
Widget build(BuildContext context) {
return _post.isEmpty
? Container(
height: 500,
width: double.infinity,
)
: GestureDetector(
child: Directionality(
textDirection: TextDirection.ltr,
child: AnimationLimiter(
child: StaggeredGridView.countBuilder(
padding: EdgeInsets.all(10),
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
crossAxisCount: 3,
itemCount: _post.length,
itemBuilder: (context, index) {
return AnimationConfiguration.staggeredGrid(
position: index,
duration: const Duration(milliseconds: 500),
columnCount: 3,
child: SlideAnimation(
verticalOffset: 50.0,
child: FadeInAnimation(
duration: Duration(milliseconds: 1000),
child: BuildData(
totalPost: _post.length,
postList: _post,
index: index,
post: _post[index],
)),
),
);
},
staggeredTileBuilder: (index) => StaggeredTile.count(
index % 7 == 0 ? 2 : 1,
index % 7 == 0 ? (2.1) : (1.05)),
mainAxisSpacing: 4.0,
crossAxisSpacing: 4.0,
),
)),
);
}
}
NestedScrollView
的 body
属性 得到严格的高度限制,等于 headerSliverBuilder
留下的 space(考虑到滚动位置)。在你的代码中,你有一个 Column
小部件,其中有一个固定高度(TabBar
)小部件。所以当 body 的高度约束小于 TabBar
高度时,它会溢出 Column
.
所以在body
中,必须有一个可以缩小到零高度的小部件,很可能是一个可滚动的(ListView
,CustomScrollView
)。在您的情况下,您可以将 TabBar
移动到 headerSliverBuilder
的底部,将其包裹起来:
SliverPersistentHeader(
pinned: true,
delegate: SimpleHeaderDelegate(
child: TabBar(...),
),
)
使用:
class SimpleHeaderDelegate extends SliverPersistentHeaderDelegate {
SimpleHeaderDelegate({@required this.child});
final PreferredSizeWidget child;
@override
Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) => child;
@override
double get maxExtent => child.preferredSize.height;
@override
double get minExtent => child.preferredSize.height;
@override
bool shouldRebuild(covariant SimpleHeaderDelegate oldDelegate) => oldDelegate.child != child;
}
是因为NestedScrollView
的body height是从0到MediaQuery.of(context).size.height,而你的TabBar里面该列使其布局 TabBar 的最小高度。
将 TabBar 移入构建器
从NestedScrollView的例子可以看出TabBar在headerSliverBuilder里面。您可以简单地将 TabBar 移动到其中(包装一个 SliverToBoxAdapter
或 SliverAppBar
使其变成条状)。
然后你可以删除 TabBarView
上方的 Column
和 Expand
小部件
child: NestedScrollView(
headerSliverBuilder: (context, _) {
return [
SliverList(
...
),
SliverAppBar(
pinned: true,
primary: false, // no reserve space for status bar
toolbarHeight: 0, // title height = 0
bottom: TabBar(
tabs: [
Tab(text: 'A'),
Tab(text: 'B'),
],
),
)
];
}
body: TabBarView(
children: [
...
查看 SingleChildScrollView class,扩展内容以适应视口:
https://api.flutter.dev/flutter/widgets/SingleChildScrollView-class.html
@override
Widget build(BuildContext context) {
super.build(context);
SystemChrome.setEnabledSystemUIOverlays(SystemUiOverlay.values);
return AnnotatedRegion<SystemUiOverlayStyle>(
value: SystemUiOverlayStyle(
statusBarColor: Colors.transparent,
),
child: Scaffold(
key: _scaffoldKeyProfilePage,
body: DefaultTabController(
length: 2,
child:RefreshIndicator(
onRefresh: _onRefresh,
child: NestedScrollView(
headerSliverBuilder: (context, _) {
return [
SliverList(
delegate: SliverChildListDelegate(
[ BuildMainProfile(
....//
),
Padding(
...//another design
),
];
},
// You tab view goes here
body: Column(
children: <Widget>[
TabBar(
tabs: [
Tab(text: 'A'),
Tab(text: 'B'),
],
),
Expanded(
child: TabBarView(
children: [
BuildPost(,
),
BuildWings()
],
),
),
],
),
),),
),
}
以上是我得到的错误示例
error:A RenderFlex 在底部溢出 48 个像素。
如何解决这个问题?尝试在 TabBar 上使用 expanded 并将 flex 设置为 1 到 tab bar 并将 flex 设置为 10 到 tabView ,但是随着该选项卡栏在向下滚动时会缩小。
下面是 tabBar 视图 A 和 B 的代码甚至相似
class BuildPost extends StatefulWidget {
final String uid;
const BuildPost({
Key key,
@required this.uid,
}) : super(key: key);
@override
_BuildPostState createState() => _BuildPostState();
}
class _BuildPostState extends State<BuildPost> {
List<Post> _post = [];
getUsersPost() async {
final database = FirestoreDatabase();
List<Post> _postModel = await database.getUsersPost(widget.uid);
setState(() {
_post = _postModel.toList();
});
}
@override
void initState() {
getUsersPost();
super.initState();
}
@override
Widget build(BuildContext context) {
return _post.isEmpty
? Container(
height: 500,
width: double.infinity,
)
: GestureDetector(
child: Directionality(
textDirection: TextDirection.ltr,
child: AnimationLimiter(
child: StaggeredGridView.countBuilder(
padding: EdgeInsets.all(10),
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
crossAxisCount: 3,
itemCount: _post.length,
itemBuilder: (context, index) {
return AnimationConfiguration.staggeredGrid(
position: index,
duration: const Duration(milliseconds: 500),
columnCount: 3,
child: SlideAnimation(
verticalOffset: 50.0,
child: FadeInAnimation(
duration: Duration(milliseconds: 1000),
child: BuildData(
totalPost: _post.length,
postList: _post,
index: index,
post: _post[index],
)),
),
);
},
staggeredTileBuilder: (index) => StaggeredTile.count(
index % 7 == 0 ? 2 : 1,
index % 7 == 0 ? (2.1) : (1.05)),
mainAxisSpacing: 4.0,
crossAxisSpacing: 4.0,
),
)),
);
}
}
NestedScrollView
的 body
属性 得到严格的高度限制,等于 headerSliverBuilder
留下的 space(考虑到滚动位置)。在你的代码中,你有一个 Column
小部件,其中有一个固定高度(TabBar
)小部件。所以当 body 的高度约束小于 TabBar
高度时,它会溢出 Column
.
所以在body
中,必须有一个可以缩小到零高度的小部件,很可能是一个可滚动的(ListView
,CustomScrollView
)。在您的情况下,您可以将 TabBar
移动到 headerSliverBuilder
的底部,将其包裹起来:
SliverPersistentHeader(
pinned: true,
delegate: SimpleHeaderDelegate(
child: TabBar(...),
),
)
使用:
class SimpleHeaderDelegate extends SliverPersistentHeaderDelegate {
SimpleHeaderDelegate({@required this.child});
final PreferredSizeWidget child;
@override
Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) => child;
@override
double get maxExtent => child.preferredSize.height;
@override
double get minExtent => child.preferredSize.height;
@override
bool shouldRebuild(covariant SimpleHeaderDelegate oldDelegate) => oldDelegate.child != child;
}
是因为NestedScrollView
的body height是从0到MediaQuery.of(context).size.height,而你的TabBar里面该列使其布局 TabBar 的最小高度。
将 TabBar 移入构建器
从NestedScrollView的例子可以看出TabBar在headerSliverBuilder里面。您可以简单地将 TabBar 移动到其中(包装一个 SliverToBoxAdapter
或 SliverAppBar
使其变成条状)。
然后你可以删除 TabBarView
上方的Column
和 Expand
小部件
child: NestedScrollView(
headerSliverBuilder: (context, _) {
return [
SliverList(
...
),
SliverAppBar(
pinned: true,
primary: false, // no reserve space for status bar
toolbarHeight: 0, // title height = 0
bottom: TabBar(
tabs: [
Tab(text: 'A'),
Tab(text: 'B'),
],
),
)
];
}
body: TabBarView(
children: [
...
查看 SingleChildScrollView class,扩展内容以适应视口:
https://api.flutter.dev/flutter/widgets/SingleChildScrollView-class.html