I'm trying to create an app containing tabs beneath the AppBar
.
appBar: AppBar(
bottom: TabBar(
labelColor: Color(0xFF1778f2),
unselectedLabelColor: Colors.black87,
indicatorColor: Color(0xFF1778f2),
tabs: <Widget>[
Tab(icon: Icon(Icons.home)),
],
),
),
Which works. But the problem is residing when creating its contents in a TabBarView
. The documentation shows an example showing a simple Icon
for each tab, and that's it. I'm trying to create many more widgets with Image
, TextField
, Column
s, etc. But things aren't as simple as the documentation expresses it to be.
This is my HomeScreen
, placed as at the top of TabBarView
:
body: TabBarView(
children: <Widget>[
HomeScreen(),
,
),
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
child: Column(
children: <Widget>[
Row(
children: <Widget>[
CircleAvatar(),
TextField(),
],
);
],
),
);
}
}
And then, errors like
RRenderBox was not laid out: _RenderDecoration#f0d71 relayoutBoundary=up6 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE 'package:flutter/src/rendering/box.dart':
Failed assertion: line 1687 pos 12: 'hasSize'
which are many, all pointing to my HomeScreen
. What's missing that the documentation doesn't show?
A screenshot with many of the errors.
I have a code demo as below. Your problem may be that you didn't set size for widget and set tabcontroller for tabbar
and tabview
. I hope that it can help you
class TabBarDemo extends StatefulWidget {
@override
State<StatefulWidget> createState() {
// TODO: implement createState
return TabBarDemoState();
}
}
class TabBarDemoState extends State<TabBarDemo> with TickerProviderStateMixin {
TabController _controller; ///<-- fixed here
@override
void initState() {
super.initState();
_controller = TabController(length: 1, vsync: this);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
bottom: TabBar(
controller: _controller, ///<-- fixed here
labelColor: Color(0xFF1778f2),
unselectedLabelColor: Colors.black87,
indicatorColor: Color(0xFF1778f2),
tabs: <Widget>[
Tab(icon: Icon(Icons.home)),
],
),
title: Text('Tabs Demo'),
),
body: TabBarView(
controller: _controller,
children: [
HomeScreen(),
],
),
);
}
}
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
Size screenSize = MediaQuery.of(context).size;
return Container(
height: screenSize.height, // <--fixed here
width: screenSize.width, // <--fixed here
child: ListView(
children: <Widget>[
Row(
children: <Widget>[
CircleAvatar(),
Container( // <--fixed here
width: screenSize.width / 2, // <--fixed here
child: TextField(),
),// <--fixed here
],
),
],
),
);
}
}
It's simple. You can use any widget inside TabBarView
. But to change the page according to Tab
change, you have to use TabBarController
or wrap with DefaultTabBarController
.
Here is a bare minimal cleaner example with DefaultTabBarController
:
import 'package:flutter/material.dart';
class SimpleTabBar extends StatefulWidget {
@override
_SimpleTabBarState createState() => _SimpleTabBarState();
}
class _SimpleTabBarState extends State<SimpleTabBar> {
List<Widget> tabs;
@override
void initState() {
tabs = [
buildTab("Dart", Icons.favorite),
buildTab("Flutter", Icons.thumb_up)
];
super.initState();
}
@override
Widget build(BuildContext context) {
return DefaultTabController(
initialIndex: 0,
length: 2,
child: Scaffold(
appBar: AppBar(
title: Text("Title"),
bottom: buildTabBar(context),
),
body: TabBarView(
children: <Widget>[
buildTabView(Colors.redAccent),
buildTabView(Colors.greenAccent)
],
),
),
);
}
Container buildTabView(Color color) {
return Container(
color: color,
child: Column(
children: List.generate(20, (index) => Text("$index")),
),
);
}
Widget buildTab(String title, IconData icon) =>
Column(children: <Widget>[Icon(icon), Text(title)]);
TabBar buildTabBar(BuildContext context) => TabBar(tabs: tabs);
}
Screenshot:
Checkout how the rows and columns are managed inside TabBarView, The problem is with your defining TextField.
class NetworkDiagnosis extends StatefulWidget {
@override
_NetworkDiagnosisState createState() => _NetworkDiagnosisState();
}
class _NetworkDiagnosisState extends State<NetworkDiagnosis> {
@override
Widget build(BuildContext context) {
return DefaultTabController(
length: 3,
child: Scaffold(
appBar: AppBar(
title: Text("Tabs"),
bottom: TabBar(
tabs: <Widget>[
Tab(text: 'One'),
Tab(text: 'Two'),
Tab(text: 'Three'),
],
),
),
body: TabBarView(
children: <Widget>[
Center(child: HomeScreen()),
Center(child: Text('Two')),
Center(child: Text('Three')),
],
),
),
);
}
}
class HomeScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
child: Column(
children: <Widget>[
Text('One'),
Text('Two'),
Row(
children: <Widget>[
Container(
width: 300,
height: 100,
child: TextField(
// controller: new TextEditingController(text: 'Enter data'),
keyboardType: TextInputType.text,
decoration: InputDecoration(
border: InputBorder.none,
hintText: "Enter Password",
hintStyle: TextStyle(fontSize: 16.0)),
),
)
],
)
],
),
);
}
}
The issue is the TextField()
. It needed to be wrapped around Expanded()
. Solved.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.