[英]Flutter: TabBarView inside SingleChildScrollView
我的问题是我想要一个 TabBarView 在 SingleChildScrollView 中,但它给了我这个错误: RenderFlex
children have non-zero flex 但传入的高度约束是无限的。
如果我删除SingleChildScrollView
它可以工作,但我需要小部件,因为那时我想推送一个 ListView ,它与TabBar
一起滚动,比如 Instagram。
代码:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> with SingleTickerProviderStateMixin {
TabController tabController;
@override
void initState() {
super.initState();
tabController = new TabController(length: 2, vsync: this);
}
@override
void dispose() {
tabController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: SingleChildScrollView(
child: Column(
children: [
TabBar(
controller: tabController,
tabs: [
Tab(
icon: Icon(
Icons.photo_library,
size: 30,
),
),
Tab(
icon: Icon(
Icons.perm_media,
size: 30,
),
),
],
labelColor: Colors.deepOrange,
unselectedLabelColor: Colors.black,
indicatorColor: Colors.deepOrange,
),
Expanded(
child: TabBarView(controller: tabController, children: [
Expanded(child: Container()),
Expanded(child: Container())
]),
),
],
),
)));
}
}
变化:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> with SingleTickerProviderStateMixin {
TabController tabController;
@override
void initState() {
super.initState();
tabController = new TabController(length: 2, vsync: this);
}
@override
void dispose() {
tabController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Column(
mainAxisSize: MainAxisSize.min,
children: [
TabBar(
controller: tabController,
tabs: [
Tab(
icon: Icon(
Icons.photo_library,
size: 30,
),
),
Tab(
icon: Icon(
Icons.perm_media,
size: 30,
),
),
],
labelColor: Colors.deepOrange,
unselectedLabelColor: Colors.black,
indicatorColor: Colors.deepOrange,
),
Expanded(
child: SingleChildScrollView(child:TabBarView(controller: tabController, children: [
Container(),
Container()
]),
),)
],
),
));
}
}
您可以使用NestedScrollView
来解决此问题。
下面的代码帮助我解决了:
NestedScrollView(
headerSliverBuilder: (context, value) {
return [
SliverToBoxAdapter(
child: Header()
),
SliverToBoxAdapter(
child: TabBar(
controller: _controller,
tabs: [
Tab(icon: Icon(Icons.x)),
Tab(icon: Icon(Icons.y)),
Tab(icon: Icon(Icons.z)),
],
),
),
];
},
body: Container(
child: TabBarView(
controller: _controller,
children: <Widget>[
page1(),
page2(),
page3(),
],
),
),
)
如需进一步解释,请参阅此答案
TabBarView 需要 SingleChildScrollView 无法提供的有限高度。 问题是您在 SingleChildScrollView 内的列中使用扩展。
This answer from a similar question可能会对您有所帮助
答案就在错误本身。 当列在可滚动的视图内时,该列正在尝试收缩包装其内容,但由于您使用 Expanded 作为该列的子级,它的工作方式与尝试收缩其子级的列相反。 两者都试图完成一个完全相反的任务。 OG
这是导致此错误的原因,因为这两个指令彼此完全相反。 如错误日志中所述,请尝试以下操作:考虑将mainAxisSize
设置为MainAxisSize.min
(用于列)并使用FlexFit.loose
进行灵活拟合(使用 Flexible 而不是 Expanded)。
我遇到了类似的问题。 我的解决方案是使用容器而不是 TabBarView 来显示子项(选项卡)。
您可以根据通过 TabBar 选择的索引来切换此容器的内容。
当然,如果您需要滑动手势在选项卡之间移动,您也需要添加它,对我来说这不是必需的。 代码看起来像这样。
import 'package:flutter/material.dart';
class Screen extends StatefulWidget {
Screen({
Key key,
}) : super(key: key);
@override
_ScreenState createState() => _ScreenState();
}
class _ScreenState extends State<Screen> with TickerProviderStateMixin {
TabController _builderPageController;
List<Widget> _tabs;
List<Tab> _tabItems;
int selectedtabIndex = 0;
@override
void initState() {
super.initState();
_initTabController();
_setUpTabComponents();
_preprareTabItems();
}
Column _showWidgets() {
return Column(
children: [
Container(
// your non tab widgets goes here
height: 300,
color: Colors.blueAccent,
),
SizedBox(
height: 10,
),
Material(
elevation: 3,
child: TabBar(
tabs: _tabItems,
controller: _builderPageController,
unselectedLabelColor: Colors.grey,
labelColor: Colors.blueAccent,
indicatorColor: Colors.blueAccent,
labelStyle: TextStyle(
fontWeight: FontWeight.w500,
fontSize: 12.0,
),
unselectedLabelStyle: TextStyle(fontWeight: FontWeight.normal, fontSize: 12.0),
),
),
Container(
padding: EdgeInsets.symmetric(horizontal: 16.0),
child: Builder(
builder: (context) {
return _tabs[selectedtabIndex];
},
))
],
);
}
void _initTabController() {
// inits Tabcontroller for Tabview
_builderPageController = TabController(
length: 3,
vsync: this,
initialIndex: selectedtabIndex,
);
_builderPageController.addListener(() {
// updated index and calls the set state
// to switch the content of the tab based on the index clicked
selectedtabIndex = _builderPageController.index;
setState(() {
_builderPageController.index;
});
});
}
void _setUpTabComponents() {
// sets up Tab headers
_tabItems = [
Tab(child: Text('Tab1')),
Tab(child: Text('Tab2')),
Tab(child: Text('Tab3')),
];
}
List<Widget> _preprareTabItems() {
// views to show on each tab
// remove height once you add your contents
return _tabs = <Widget>[
Container(
// first tab content
height: 400,
color: Colors.white,
),
Container(
// second tab content
height: 600,
color: Colors.white,
),
Container(
// third tab content
height: 900,
color: Colors.white,
),
];
}
@override
Widget build(BuildContext context) {
return SingleChildScrollView(child: _showWidgets());
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.