How to add a tab inside a column widget on flutter - flutter

My goal is to add a tab inside a colum, and add more widgets on this column.
But when i'm adding a tab, i'm getting an error of
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.
Any suggestions what i'm doing wrong? Thanks!
Here is my sample code
import 'package:flutter/material.dart';
import 'package:trip_finder/screens/home_screen.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Trip Finder',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primaryColor: Color(0xFF131415),
primaryColorLight: Color(0xFF8296ab),
highlightColor: Color(0xFF47bee1),
scaffoldBackgroundColor: Color(0xFFf0f1f1)
),
// home: HomeScreen(),
home: TestScreen(),
);
}
}
class TestScreen extends StatefulWidget {
#override
_TestScreenState createState() => _TestScreenState();
}
class _TestScreenState extends State<TestScreen> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
child: Column(
children: <Widget>[
_tabSection(),
],
),
)
);
}
}
Widget _tabSection() {
return DefaultTabController(
length: 3,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
child: TabBar(tabs: [
Tab(text: "Home"),
Tab(text: "Articles"),
Tab(text: "User"),
]),
),
Container(
child: TabBarView(children: [
Container(
child: Text("Home Body"),
),
Container(
child: Text("Articles Body"),
),
Container(
child: Text("User Body"),
),
]),
),
],
),
);
}

You can add height to your TabBarView. Code:
import 'package:flutter/material.dart';
class TestScreen extends StatefulWidget {
#override
_TestScreenState createState() => _TestScreenState();
}
class _TestScreenState extends State<TestScreen> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
child: Column(
children: <Widget>[
_tabSection(context),
],
),
));
}
}
Widget _tabSection(BuildContext context) {
return DefaultTabController(
length: 3,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
child: TabBar(tabs: [
Tab(text: "Home"),
Tab(text: "Articles"),
Tab(text: "User"),
]),
),
Container(
//Add this to give height
height: MediaQuery.of(context).size.height,
child: TabBarView(children: [
Container(
child: Text("Home Body"),
),
Container(
child: Text("Articles Body"),
),
Container(
child: Text("User Body"),
),
]),
),
],
),
);
}

You can also wrap inside Flexible.
Flexible(
child: Container(
child: TabBarView(
children: [
Container(
child: Text("Home Body"),
),
Container(
child: Text("Articles Body"),
),
Container(
child: Text("User Body"),
),
],
),
),
)

Related

ChoiceChip not expanding with IntrinsicWidth

I'm wondering why ChoiceChip is not expanding like ElevatedButton does.
Here is an example: (look at dartpad)
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: MyWidget(),
),
);
}
}
class MyWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Column(children: [
IntrinsicWidth(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
Expanded(
child: ElevatedButton(
child: const Text('Larger Text'),
onPressed: () {},
)),
Expanded(
child: ElevatedButton(
child: const Text('Text'),
onPressed: () {},
)),
],
)),
IntrinsicWidth(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: const [
Expanded(
child: ChoiceChip(
label: Text('Larger Text'),
selected: false,
)),
Expanded(
child: ChoiceChip(
label: Text('Text'),
selected: false,
)),
],
))
]);
}
}
To solve this, let's start by enabling Flutter Inspector, we can see the second IntrinsicWidth width and its children don't fill their parent as the first one (two problems)
Solve 1st problem: IntrinsicWidth children don't fill their parent width
So, the problem is the size of the 2nd IntrinsicWidth's children is not wide/big enough so that it can be full of parent width. Try increasing its width manually by wrapping it in a Container with double.infinity width, like this:
ChoiceChip(
label: Container(width: double.infinity, child: Text('Larger Text')),
selected: false,
)
New result:
Solve 2nd problem: the 2nd IntrinsicWidth don't fill their parent width
Let's leave Column children can have the maximum width as it is (removing all IntrinsicWidth inside its children) and then wrap the Column by an IntrinsicWidth. Complete sample code:
Sample code
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
#override
Widget build(BuildContext context) {
return const MaterialApp(
home: Scaffold(
body: MyWidget(),
),
);
}
}
class MyWidget extends StatelessWidget {
const MyWidget({super.key});
#override
Widget build(BuildContext context) {
return IntrinsicWidth(
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
Expanded(
child: ElevatedButton(
child: const Text('Larger Text'),
onPressed: () {},
),
),
Expanded(
child: ElevatedButton(
child: const Text('Text'),
onPressed: () {},
),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
Expanded(
child: ChoiceChip(
label: Container(width: double.infinity, child: Text('Larger Text')),
selected: false,
),
),
Expanded(
child: ChoiceChip(
label: Container(width: double.infinity, child: Text('Text')),
selected: false,
),
),
],
),
],
),
);
}
}
Final result:
Because under the hood the widgets are designed differently (that's why the names).
I haven't checked the code in detail (you can do that by ctrl + click on Widget Name).
But best guess, visual density is lower in chips for being compact and higher in buttons.
More on technical difference to understand which to use : chips-vs-button

How to make the children in the stack equal in height in flutter?

How to make the children in the stack equal in height in flutter? The container below is the automatic height, I need to set the height of the upper container according to the height of the lower container.
Why do I need this?
Because I want to implement a background progress bar.
return Stack(
children: [,
Container(
//how to auto set this widget equal height to below.
height:?
),
Container(
child: Column(
children: [
Text("a"),
Text("b"),
Text("c"),
//maybe more widgets..
],
),
),
],
);
Just wrap your Stack widget with IntrinsicHeight widget.
This will make each of the children of the Stack widget occupy the height of the largest child. So. all children will be of equal height.
As per the example you shared:
return IntrinsicHeight(
child: Stack(
children: [,
Container(
child: SomeWidget(),
),
Container(
child: Column(
children: [
Text("a"),
Text("b"),
Text("c"),
//maybe more widgets..
],
),
),
],
)
);
I found the solution based on #JaisonThomas' comment.
return Stack(
children: [
Positioned.fill(
child: LayoutBuilder(builder: (BuildContext context, BoxConstraints constraints) {
return Container(
child: Row(
children: [
Container(
width: constraints.maxWidth * _progress,
color: statusColor,
),
],
),
);
}),
),
Container(
child: Column(
children: [
Text("a"),
Text("b"),
Text("c"),
//maybe more widgets..
],
),
),
],
);
Although there is a good solution that made by 'noveleven',
I implemented by using 'addPostFrameCallback' and 'key'.
(I added a background color for distinguish Widget.)
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
GlobalKey _key = GlobalKey();
double _sizeOfColumn = 0.0;
#override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
setState(() {
_sizeOfColumn = _key.currentContext.size.height;
});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: _buildBody(),
floatingActionButton: FloatingActionButton(
onPressed: () {},
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
Widget _buildBody() {
return Stack(
children: [
Container(
color: Colors.grey,
height: _sizeOfColumn,
),
Container(
key: _key,
color: Colors.yellow,
child: Column(
mainAxisSize: MainAxisSize.min,
// crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text("a"),
Text("b"),
Text("c"),
Text("a"),
Text("b"),
Text("c"),
//maybe more widgets..
],
),
),
],
);
}
}

Not being able to add vertical line in flutter

I have the following layout
Form(
onChanged: _updateFormProgress,
child: Row(
children: [
Expanded(
flex: 3,
child: Column(
children: [
....
],
),
),
Expanded(
flex: 2,
child: Column(
children: [
...
],
),
)
],
),
);
I need a vertical separator line beteen the two Expanded
I tried:
Form(
onChanged: _updateFormProgress,
child: Row(
children: [
Expanded(
flex: 3,
child: Column(
children: [
....
],
),
),
Container(
child: VerticalDivider(
color: Colors.red,
width: 1,
)
),
Expanded(
flex: 2,
child: Column(
children: [
...
],
),
)
],
),
);
And it compiles but I can't see the line. I also tried other options like wrapping the Expanded in a Container and make a border but have different issues with that
I changed code like tree you provide, and change it to work.
Please wrap 'Row' with 'IntrinsicHeight'.
I attached full code I tested.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Padding(
padding: EdgeInsets.all(10),
child: Center(
child: Column(
children: [
Container(
child: Form(
onChanged: () {},
child: IntrinsicHeight(
child: Row(
children: [
Expanded(
flex: 3,
child: Column(
children: [
Container(child: Text('a')),
Container(child: Text('a')),
Container(child: Text('a')),
],
),
),
Container(
child: VerticalDivider(
color: Colors.red,
width: 1,
),
),
Expanded(
flex: 2,
child: Column(
children: [
Container(child: Text('a')),
Container(child: Text('a')),
Container(child: Text('a')),
],
),
)
],
),
),
),
),
],
),
),
),
);
}
}

Flutter Layout: VerticalDividers not shown

I have a simple layout that consists of one Column with few children. Some of these are Rows which contain children either. I've added Dividers between the children of the Column and VerticalDividers between the children of the Rows. The (horizontal) Dividers are shown fine. However the VerticalDividers are not shown in the app.
I have already tried wrapping the Rows children in some other layout widget like Container, but nothing seems to work.
Screenshot
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Test App'),
),
body: Column(
children: <Widget>[
Expanded(
child: Center(
child: Text('Hello World'),
),
),
Divider(height: 1),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(40.0),
child: Text('Row 1.1'),
),
VerticalDivider(width: 1),
Padding(
padding: const EdgeInsets.all(40.0),
child: Text('Row 1.2'),
),
],
),
Divider(height: 1),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(40.0),
child: Text('Row 2.1'),
),
VerticalDivider(width: 1),
Padding(
padding: const EdgeInsets.all(40.0),
child: Text('Row 2.2'),
),
],
)
],
),
);
}
}
just wrap Rows with IntrinsicHeight widget
your example will looks like
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Test App'),
),
body: Column(
children: <Widget>[
Expanded(
child: Center(
child: Text('Hello World'),
),
),
Divider(height: 1),
IntrinsicHeight(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(40.0),
child: Text('Row 1.1'),
),
VerticalDivider(width: 1),
Padding(
padding: const EdgeInsets.all(40.0),
child: Text('Row 1.2'),
),
],
),
),
Divider(height: 1),
IntrinsicHeight(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(40.0),
child: Text('Row 2.1'),
),
VerticalDivider(width: 1),
Padding(
padding: const EdgeInsets.all(40.0),
child: Text('Row 2.2'),
),
],
),
)
],
),
);
}
}
Try this:
Container(
height: 20,
child: VerticalDivider(
width: 20
color: Colors.black,
),
),
It worked for me.

Table Alignment in Flutter?

I'm going to use a data table in my application.
In my page I have a background that this data table should be in a specific position (center maybe), but I don't know how to set alignment for that (data table).
Can anyone tell me how to solve this issue?
To align your text vertically in a table row you can wrap you Conent with TableCell and set the vertical Alignment parameter:
return TableRow(children: [
TableCell(
verticalAlignment: TableCellVerticalAlignment.middle,
child: Padding(
padding: const EdgeInsets.all(10),
child: Text('Hello World'),
),
),
child: Table(
children: [
TableRow(children: [
Center(child: Text("item 1"),),
Center(child: Text("item 2"),),
Center(child: Text("item 3"),),
Center(child: Text("item 4"),),
Center(child: Text("Edit"),),
]),
Working.
import 'package:flutter/material.dart';
void main() => runApp(new Demo());
class Demo extends StatefulWidget {
#override
_DemoState createState() => _DemoState();
}
class _DemoState extends State<Demo> with TickerProviderStateMixin {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: new Text("table demo"),
),
body: new Container(
child: Center(
child: new Table(
children: const <TableRow>[
TableRow(
children: <Widget>[
Center(child: Text('AAAAAA')), Center(child: Text('B')), Center(child: Text('C')),
],
),
TableRow(
children: <Widget>[
Center(child: Text('BBBB')), Center(child: Text('AAAAAA')), Center(child: Text('vdsvsdvs')),
],
),
TableRow(
children: <Widget>[
Center(child: Text('CCCCCC')), Center(child: Text('F')), Center(child: Text('CG')),
],
),
],
),
),
)
)
);
}
}