我的问题是我想要在SingleChildScrollView中使用TabBarView,但是它给了我这个错误:
products
子代的flex值非零,但传入的高度限制不受限制。
如果我删除了RenderFlex
可以使用,但是我需要该小部件,因为那样的话,我想推送一个与SingleChildScrollView
一起滚动的ListView,例如Instagram。
代码:
TabBar
更改:
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())
]),
),
],
),
)));
}
}
答案 0 :(得分:0)
TabBarView需要SingleChildScrollView无法提供的有限高度。问题在于您正在使用SingleChildScrollView内的一列中的expand。
这个来自similar question的答案可能会对您有所帮助
答案出在错误本身中。当列位于可滚动视图中时,该列将尝试收缩其内容,但是由于您使用Expanded作为该列的子级,因此它与试图收缩其子级的列相反。两者都试图实现完全相反的任务。 Og
这是导致此错误的原因,因为这两个指令彼此完全相反。
如错误日志中所述,请尝试以下操作:
考虑将mainAxisSize
设置为MainAxisSize.min
(用于列),并使用FlexFit.loose
适合灵活(使用Flexible而不是Expanded)。
答案 1 :(得分:0)
您可以使用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(),
],
),
),
)
有关更多说明,请参见this answer
答案 2 :(得分:0)
我遇到了类似的问题。我的解决方案是使用容器而不是 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());
}
}