[英]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.