Reputation: 1909
I have a SingleChildScrollView with a Column as child with a lots of children, two of them are a TabBar and a TabBarView. The TabBar renders ok but when I add a TabBarView I got the error:
======== Exception caught by rendering library =====================================================
The following assertion was thrown during performResize():
Horizontal viewport was given unbounded height.
Viewports expand in the cross axis to fill their container and constrain their children to match their extent in the cross axis. In this case, a horizontal viewport was given an unlimited amount of vertical space in which to expand.
The relevant error-causing widget was:
TabBarView file:///C:/Users/user/Documents/FlutterProjects/singlechildscrollview/lib/main.dart:83:13
When the exception was thrown, this was the stack:
#0 RenderViewport.computeDryLayout.<anonymous closure> (package:flutter/src/rendering/viewport.dart:1418:15)
#1 RenderViewport.computeDryLayout (package:flutter/src/rendering/viewport.dart:1430:6)
#2 RenderBox.performResize (package:flutter/src/rendering/box.dart:2332:12)
#3 RenderObject.layout (package:flutter/src/rendering/object.dart:1758:9)
#4 RenderProxyBoxMixin.performLayout (package:flutter/src/rendering/proxy_box.dart:116:14)
...
The following RenderObject was being processed when the exception was fired: RenderViewport#4db57 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
... needs compositing
... parentData: <none> (can use size)
... constraints: BoxConstraints(0.0<=w<=568.0, 0.0<=h<=Infinity)
... size: MISSING
... axisDirection: right
... crossAxisDirection: down
... offset: _PagePosition#05511(range: null..null, viewport: null, ScrollableState, _ForceImplicitScrollPhysics -> PageScrollPhysics -> PageScrollPhysics -> ClampingScrollPhysics -> ClampingScrollPhysics -> RangeMaintainingScrollPhysics, IdleScrollActivity#083c3, ScrollDirection.idle)
... anchor: 0.0
RenderObject: RenderViewport#4db57 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
needs compositing
parentData: <none> (can use size)
constraints: BoxConstraints(0.0<=w<=568.0, 0.0<=h<=Infinity)
size: MISSING
axisDirection: right
crossAxisDirection: down
offset: _PagePosition#05511(range: null..null, viewport: null, ScrollableState, _ForceImplicitScrollPhysics -> PageScrollPhysics -> PageScrollPhysics -> ClampingScrollPhysics -> ClampingScrollPhysics -> RangeMaintainingScrollPhysics, IdleScrollActivity#083c3, ScrollDirection.idle)
anchor: 0.0
... center child: _RenderSliverFractionalPadding#c51bd NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
... parentData: paintOffset=Offset(0.0, 0.0)
... constraints: MISSING
... geometry: null
... child: RenderSliverFillViewport#29be2 NEEDS-LAYOUT NEEDS-PAINT
... parentData: paintOffset=Offset(0.0, 0.0)
... constraints: MISSING
... geometry: null
... no children current live
====================================================================================================
======== Exception caught by rendering library =====================================================
The following assertion was thrown during performLayout():
RenderBox was not laid out: RenderViewport#4db57 NEEDS-LAYOUT NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE
'package:flutter/src/rendering/box.dart':
Failed assertion: line 1930 pos 12: 'hasSize'
I know that this error is related to the TabBarView doesn't have a height, I cannot set a specific height since the content from each tab will be dynamic or use any other ScrollView, I already tried to wrap it into a Flexible with fit: FlexFit.loose and set to all Column's mainAxisSize: MainAxisSize.min but it still doesn't work.
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin{
late TabController tabController;
@override
void initState() {
super.initState();
tabController = TabController(length: 2, vsync: this);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
child: Column(
children: [
/// Other widgets here...then
TabBar(
controller: tabController,
tabs: [
Tab(
child: Text(
"Tab 1",
style: TextStyle(
color: Colors.black
),
),
),
Tab(
child: Text(
"Tab 1",
style: TextStyle(
color: Colors.black
),
),
),
],
),
TabBarView(
controller: tabController,
children: [
/// Each content from each tab will have a dynamic height
Container(),
Container()
],
)
],
),
),
);
}
}
Upvotes: 2
Views: 5172
Reputation: 3326
You can use this sample app as example. In short, I'm nesting both TabBar
and TabBarView
within a NestedScrollView
that take full size of the screen. This way you can have a dynamic body within the TabBarView
import 'package:flutter/material.dart';
void main() {
runApp(MaterialApp(home: MyHomePage()));
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
late TabController tabController;
@override
void initState() {
super.initState();
tabController = TabController(length: 2, vsync: this);
}
@override
void dispose() {
tabController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: NestedScrollView(
headerSliverBuilder: (context, value) {
return [
SliverToBoxAdapter(
child: TabBar(
controller: tabController,
labelColor: Colors.redAccent,
isScrollable: true,
tabs: [
Tab(
child: Text(
"Tab 1",
style: TextStyle(color: Colors.black),
),
),
Tab(
child: Text(
"Tab 1",
style: TextStyle(color: Colors.black),
),
),
],
),
),
];
},
body: Container(
child: TabBarView(
controller: tabController,
children: [
/// Each content from each tab will have a dynamic height
Container(),
Container()
],
),
),
),
);
}
}
Upvotes: 4