How to put scroll view inside stack widget in flutter - flutter

I am making a flutter application in which i uses body as a stack and in this stack i have two child.One is main body and other is back button which is at top of screen.The first child of stack is scrollview.Here is my build method.
Widget build(BuildContext context) {
return Scaffold(
//debugShowCheckedModeBanner: false,
key: scaffoldKey,
backgroundColor: Color(0xFF5E68A6),
body: Stack(
children: <Widget>[
Container(
margin: const EdgeInsets.fromLTRB(0.0, 10.0 , 0.0 , 0.0 ),
height: double.infinity,
child:CustomScrollView(
slivers: <Widget>[
new Container(
margin: EdgeInsets.all(15.0),
child:Text(getTitle(),
style: TextStyle(fontSize: 20.0,fontWeight: FontWeight.bold,color: Colors.white),
),
),
//middle section
_isLoading == false ?
new Expanded(child: GridView.builder(
itemCount: sub_categories_list.length,
physics: const NeverScrollableScrollPhysics(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
itemBuilder: (context, position){
return InkWell(
child: new Container(
//color: Colors.white,
padding: EdgeInsets.all(20),
margin: EdgeInsets.all(10),
height: 130,
width: 130,
child: new Center(
child :
Text(sub_categories_list[position].name,
style: TextStyle(fontSize: 18.0,fontWeight: FontWeight.bold),
)
),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(Radius.circular(16)),
// border: Border.all(color: Colors.black, width: 3),
),
),
onTap: () {
//write here
// Fluttertoast.showToast(msg: "You clicked id :"+sub_categories_list[position].cat_id.toString());
Navigator.pushNamed(context, '/advicemyself');
},
);
}
))
:
CircularProgressIndicator(),
Container(
margin: EdgeInsets.all(18.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
new Column(
children: <Widget>[
Image.asset('assets/bt1.png'),
Container(
margin: EdgeInsets.all(10.0),
child: Text("FIND HELP",
style: TextStyle(fontSize: 18.0,color: Colors.white),
),
)
],
),
new Column(
children: <Widget>[
Image.asset('assets/bt2.png'),
Container(
margin: EdgeInsets.all(10.0),
child: Text("HOME",
style: TextStyle(fontSize: 18.0,color: Colors.white),
),
)
],
),
new Column(
mainAxisAlignment:MainAxisAlignment.spaceEvenly,
children: <Widget>[
Image.asset('assets/bt3.png'),
Container(
margin: EdgeInsets.all(10.0),
child: Text("CALL 999",
style: TextStyle(fontSize: 18.0,color: Colors.white),
),
)
],
),
],
),
),
],
),
),
Positioned(
left: 10,
top: 30,
child: IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () => {
//go back
},
color: Colors.white,
iconSize: 30,
),
),
// makeview()
],
),
// This trailing comma makes auto-formatting nicer for build methods.
);
}
I have also tried using SingleChildScrollView but that also does not works.What i am doing wrong here ?
Here is link to the design which i want to make.
https://imgur.com/a/w7nLmKC
The back should be above scroll view so i used stack widget.

Running your sample code, there doesn't seem to be a need for overlapping widgets. Using Stack seems to be unnecessary. One way you could do is by using Column widget, and using Expanded as you see fit.
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
Widget(), // back button goes here
CustomScrollView(...),
],
),
);
}
Otherwise, if you really need to use Stack, the scroll function should work fine. I've tried this locally and the Stack widget doesn't interfere with scrolling of Slivers, ListView, and GridView.
Stack(
children: [
/// Can be GridView, Slivers
ListView.builder(),
/// Back button
Container(),
],
),

Related

How to make ExpansionTile scrollable when end of screen is reached?

In the project I'm currently working on, I have a Scaffold that contains a SinlgeChildScrollView. Within this SingleChildScrollView the actual content is being displayed, allowing for the possibility of scrolling if the content leaves the screen.
While this makes sense for ~90% of my screens, however I have one screen in which I display 2 ExpansionTiles. Both of these could possibly contain many entries, making them very big when expanded.
The problem right now is, that I'd like the ExpansionTile to stop expanding at latest when it reaches the bottom of the screen and make the content within the ExpansionTile (i.e. the ListTiles) scrollable.
Currently the screen looks like this when there are too many entries:
As you can clearly see, the ExpansionTile leaves the screen, forcing the user to scroll the actual screen, which would lead to the headers of both ExpansionTiles disappearing out of the screen given there are enought entries in the list. Even removing the SingleChildScrollView from the Scaffold doesn't solve the problem but just leads to a RenderOverflow.
The code used for generating the Scaffold and its contents is the following:
class MembershipScreen extends StatefulWidget {
#override
State<StatefulWidget> createState() => _MembershipScreenState();
}
class _MembershipScreenState extends State<MembershipScreen> {
String _fontFamily = 'OpenSans';
Widget _buildMyClubs() {
return Container(
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(
color: Color(0xFFD2D2D2),
width: 2
),
borderRadius: BorderRadius.circular(25)
),
child: Theme(
data: ThemeData().copyWith(dividerColor: Colors.transparent),
child: ExpansionTile(
title: Text("My Clubs"),
trailing: Icon(Icons.add),
children: getSearchResults(),
),
)
);
}
Widget _buildAllClubs() {
return Container(
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(
color: Color(0xFFD2D2D2),
width: 2
),
borderRadius: BorderRadius.circular(25)
),
child: Theme(
data: ThemeData().copyWith(dividerColor: Colors.transparent),
child: SingleChildScrollView(
child: ExpansionTile(
title: Text("All Clubs"),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.add)
],
),
children: getSearchResults(),
),
)
)
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
extendBody: true,
body: AnnotatedRegion<SystemUiOverlayStyle>(
value: SystemUiOverlayStyle.light,
child: GestureDetector(
onTap: () => FocusScope.of(context).unfocus(),
child: Stack(
children: <Widget>[
Container(
height: double.infinity,
width: double.infinity,
decoration: BoxDecoration(
gradient: kGradient //just some gradient
),
),
Center(
child: Container(
height: double.infinity,
constraints: BoxConstraints(maxWidth: 500),
child: SingleChildScrollView(
physics: AlwaysScrollableScrollPhysics(),
padding: EdgeInsets.symmetric(horizontal: 40.0, vertical: 20.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'Clubs',
style: TextStyle(
fontSize: 30.0,
color: Colors.white,
fontFamily: _fontFamily,
fontWeight: FontWeight.bold),
),
SizedBox(
height: 20,
),
_buildMyClubs(),
SizedBox(height: 20,),
_buildAllClubs()
],
),
),
),
),
],
),
)
),
);
}
List<Widget> getSearchResults() {
return [
ListTile(
title: Text("Test1"),
onTap: () => print("Test1"),
),
ListTile(
title: Text("Test2"),
onTap: () => print("Test2"),
), //etc..
];
}
}
I hope I didn't break the code by removing irrelevant parts of it in order to reduce size before posting it here. Hopefully, there is someone who knows how to achieve what I intend to do here and who can help me with the solution for this.
EDIT
As it might not be easy to understand what I try to achieve, I tried to come up with a visualization for the desired behaviour:
Thereby, the items that are surrounded with dashed lines are contained with the list, however cannot be displayed because they would exceed the viewport's boundaries. Hence the ExpansionTile that is containing the item needs to provide a scroll bar for the user to scroll down WITHIN the list. Thereby, both ExpansionTiles are visible at all times.
Try below code hope its help to you. Add your ExpansionTile() Widget inside Column() and Column() wrap in SingleChildScrollView()
Refer SingleChildScrollView here
Refer Column here
You can refer my answer here also for ExpansionPanel
Refer Lists here
Refer ListView.builder() here
your List:
List<Widget> getSearchResults = [
ListTile(
title: Text("Test1"),
onTap: () => print("Test1"),
),
ListTile(
title: Text("Test2"),
onTap: () => print("Test2"),
), //etc..
];
Your Widget using ListView.builder():
SingleChildScrollView(
padding: EdgeInsets.all(20),
child: Column(
children: [
Card(
child: ExpansionTile(
title: Text(
"My Clubs",
),
trailing: Icon(
Icons.add,
),
children: [
ListView.builder(
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
return Column(
children: getSearchResults,
);
},
itemCount: getSearchResults.length, // try 50 length just testing
),
],
),
),
],
),
),
Your Simple Widget :
SingleChildScrollView(
padding: EdgeInsets.all(20),
child: Column(
children: [
Card(
child: ExpansionTile(
title: Text(
"My Clubs",
),
trailing: Icon(
Icons.add,
),
children:getSearchResults
),
),
],
),
),
Your result screen ->

Refresh ListView.builder On Button Click in Flutter

I am using the below code, where I have a ListView that had a switch.
I want to implement something like when I click on the RaisedButton - it will reload the ListView and all the values of switch.value should be changed to either true or false.
The user can either change the value of the switch from items in the ListView or from the button click.
I do not have an idea on how I should change the value or all the switches in the ListView.
return Column(
children: <Widget>[
Container(
width: MediaQuery.of(context).size.width / 2,
height: 100,
padding: EdgeInsets.all(20),
child: RaisedButton(
onPressed: () {
},
child: Text(
BTN_START_TRIP,
style: new TextStyle(
fontSize: 20.0,
),
),
textColor: buttonFontColor,
color: buttonColor,
shape: new RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(15.0))
),
),
Expanded(
child: ListView.builder(
padding: EdgeInsets.all(3.0),
// Let the ListView know how many items it needs to build.
itemCount: snapshot.data.results.length,
// Provide a builder function. This is where the magic happens.
// Convert each item into a widget based on the type of item it is.
itemBuilder: (context, index){
return Container(
height: 120,
child: Card(
elevation: 10,
child: InkWell(
splashColor: Colors.blue.withAlpha(30),
onTap: () {
print(snapshot.data.results[index].original_title);
},
child: Container(
height: 120,
child: Row(
children: <Widget>[
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
padding: EdgeInsets.fromLTRB(20, 0, 5, 0),
width: MediaQuery.of(context).size.width -90,
child: Align(
alignment: Alignment.topLeft,
child: Text(snapshot.data.results[index].original_title,
textAlign: TextAlign.left,
style: TextStyle(fontSize: defaultTitleFontsize, color: defaultFontColor),
maxLines: 5),
),
),
Container(
padding: EdgeInsets.fromLTRB(20, 0, 5, 0),
child: Align(
alignment: Alignment.topLeft,
child: Text(snapshot.data.results[index].original_language,textAlign: TextAlign.left,style: TextStyle(fontSize: defaultsubTitleFontsize, color: defaultFontColor)),
),
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
Container(
child: Switch(
value: false,
onChanged: (value){
setState(() {
print(value);
});
}
),
),
],
),
]
),
),
),
),
);
},
),
)
],
);
You'll need to have a variable to decide if the switch should be on or off. And during a certain event (click of button e.g) set the variable to appropriate value & re-trigger the build (re-painting of the UI) by calling setState. You'll need to have the above logic part of a stateful widget to accomplish that.

What is best way to remove overflowing by a lot of pixels in Flutter?

I have Stepper in my app, and I have problems with placing textfield on screen, when I want to text some text in textfield, appears keyboard and over it shows me that:
A RenderFlex overflowed by 139 pixels on the bottom.
I read some articles and understood, that I have to use FittedBox, but I dunno how to use it with best way. How can I reach my goal?
Code:
#override
Widget build(BuildContext context) {
globalHeight = (MediaQuery.of(context).size.height) * 0.85;
return Scaffold(
body: AnnotatedRegion<SystemUiOverlayStyle>(
value: SystemUiOverlayStyle.light,
child: Container(
decoration: BoxDecoration(color: colorsBackround[_currentPage]),
child: Padding(
padding: EdgeInsets.symmetric(vertical: 10.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Container(
height: globalHeight,
child: PageView(
physics: ClampingScrollPhysics(),
controller: _pageController,
onPageChanged: (int page) {
setState(() {
_currentPage = page;
});
},
children: <Widget>[
// some code
Padding(
padding: EdgeInsets.all(10.0),
child: Center(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Image(
image: AssetImage(
itemIcon[_currentPage],
),
height: 300.0,
width: 300.0,
),
Text(
'Укажите ваш возраст',
style: kTitleStyle,
),
SizedBox(
width: MediaQuery.of(context).size.width * 0.8,
height: 50.0,
child: Padding(
padding: EdgeInsets.only(
top: 20.0,
left: 20,
right: 20,
bottom: MediaQuery.of(context)
.viewInsets
.bottom),
child: TextField(
controller: ageController,
keyboardType: TextInputType.number,
onChanged: (text) {
setState(() {
if (text.isNotEmpty) {
inputs[1] = true;
} else {
inputs[1] = false;
}
});
},
decoration: InputDecoration(
labelText: 'Возраст',
),
style: TextStyle(fontSize: 18.5),
)),
),
],
),
),
),
//some code
],
),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: _buildPageIndicator(),
),
_currentPage != _numPages - 1
? Expanded(
child: Container(
child: Row(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Expanded(
child: Align(
alignment: FractionalOffset.bottomLeft,
child: FlatButton(
onPressed: () {
_pageController.previousPage(
duration: Duration(milliseconds: 500),
curve: Curves.ease,
);
},
child: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Icon(
Icons.arrow_back,
color: Colors.white,
size: 26.0,
),
SizedBox(width: 10.0),
Text(
'Назад',
style: TextStyle(
fontFamily: 'Century Gothic',
color: Colors.white,
fontSize: 14.5,
),
),
],
),
),
)),
Expanded(
child: Align(
alignment: FractionalOffset.bottomRight,
child: FlatButton(
onPressed: () {
_pageController.nextPage(
duration: Duration(milliseconds: 500),
curve: Curves.ease,
);
},
child: Row(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text(
'Дальше',
style: TextStyle(
fontFamily: 'Century Gothic',
color: Colors.white,
fontSize: 14.5,
),
),
SizedBox(width: 10.0),
Icon(
Icons.arrow_forward,
color: Colors.white,
size: 26.0,
),
],
),
),
)),
],
)))
: Text(''),
],
),
),
),
),
bottomSheet: _currentPage == _numPages - 1
? Container(
height: 75.0,
width: double.infinity,
color: Theme.of(context).scaffoldBackgroundColor,
child: GestureDetector(
onTap: () => print('Get started'),
child: Center(
child: Padding(
padding: EdgeInsets.only(bottom: 15.0),
child: Text(
'Начать',
style: TextStyle(
fontFamily: 'Century Gothic',
color: Colors.white,
fontSize: 21.0,
fontWeight: FontWeight.bold,
),
),
),
),
),
)
: Text(''),
);
}
}
There is no direct solution to prevent overflowing issues, it depends on your current code. So, here you use
Add to your Scaffold
resizeToAvoidBottomInset: false
Wrap your widget in SingleChildScrollView
SingleChildScrollView(
child: YourColumn(),
)
That happens because when opening the keyboard, the body is resized to avoid the keyboard appear over the text field, and since your content isn't scrollable the content of the body gets overflowed. Check this property of the Scaffold:
/// If true the [body] and the scaffold's floating widgets should size
/// themselves to avoid the onscreen keyboard whose height is defined by the
/// ambient [MediaQuery]'s [MediaQueryData.viewInsets] `bottom` property.
///
/// For example, if there is an onscreen keyboard displayed above the
/// scaffold, the body can be resized to avoid overlapping the keyboard, which
/// prevents widgets inside the body from being obscured by the keyboard.
///
/// Defaults to true.
final bool resizeToAvoidBottomInset;
If you put that to false, the body won't be resized so the content won't be overflowed.
If you leave it as default, you need to make the body scrollable. In your case, you could change the root Column for a ListView and you will need to remove the Expanded wrap of the third item of the column.
But I recommend you to try to simplify the structure of the widgets.
Wrap your widget with a SingleChildScroll widget and that should work and solve the overflow issue

Button with column for child not using align

I'm attempting to layout some buttons in a flutter app towards the bottom of the screen as seen here:
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
centerTitle: true,
),
body: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('images/foo.jpeg'),
fit: BoxFit.cover),
),
child: Column(
children: <Widget>[
Padding(
padding: EdgeInsets.only(top: 10),
child: _buttonsOne(),
),
Expanded(
child: Text(''),
),
Padding(
padding: EdgeInsets.only(bottom: 10),
child: _buttonsTwo(),
),
],
),
),
);
Counter buttons is setup thusly:
Widget _buttonsTwo() {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
_oneButton(),
_twoButton(),
_threeButton(),
_fourButton()
],
);
}
My problem is two of the buttons are using glyphs that cause them to be just right of center. Prior to attempting this layout I structured raised buttons with columns so that I could use an Align to pull these icons to the left a bit, as seen here for one of the buttons:
Widget _threeButton() {
return RaisedButton(
onPressed: () {},
elevation: 10,
color: Colors.red,
textColor: Colors.white,
padding: EdgeInsets.all(10.0),
child: Column(
children: <Widget>[
Align(
alignment: Alignment(-0.4, 0),
child: Icon(
Class.icon_name,
size: 30,
),
),
Text(
_fooCount.toString(),
style: TextStyle(fontSize: 25),
)
],
),
);
}
And here's the result I'm getting:
As you can see, the icons for the two rightmost buttons are still a little to the right. I've tried using RaisedButton.icon to no avail as it causes the icons to overlap the text, even restructuring them in a row to try and make wider buttons. What am I missing?
Try using Transform widget instead of Align and translate the X axis:
Transform(
transform: Matrix4.identity()..translate(-7.0),
child: Icon(
FiveRingsDB.conflict_political,
size: 30,
),
),
Text(
_militaryCount.toString(),
style: TextStyle(fontSize: 25),
)

Getting 'Horizontal viewport was given unbounded height.' with TabBarView in flutter

I'm trying to make a profile page, where the users info is at the top. And then have a tab view below that for different views.
This is the code I'm using at the moment, when I take the TabBarView out it doesn't through an error, and if I wrap the TabBarView in an Expanded the error RenderFlex children have non-zero flex but incoming height constraints are unbounded. comes up.
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(''),
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Padding(
padding: EdgeInsets.all(10.0),
child: Row(
children: <Widget>[
CircleAvatar(
minRadius: 45.0,
backgroundImage: NetworkImage(
'https://www.ienglishstatus.com/wp-content/uploads/2018/04/Anonymous-Whatsapp-profile-picture.jpg'),
),
Padding(
padding: EdgeInsets.only(left: 10.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'Testing Name',
style: TextStyle(
fontSize: 22.0,
color: Colors.grey.shade800,
),
),
Text(
'#testing_username',
style: TextStyle(
fontSize: 13.0,
color: Colors.grey.shade800,
),
),
],
),
),
],
),
),
DefaultTabController(
length: 3,
child: Column(
children: <Widget>[
TabBar(
tabs: <Widget>[
Tab(
icon: Padding(
padding: EdgeInsets.all(6.0),
child: Image.asset(
"assets/images/icons/butterlike.png",
color: Colors.grey.shade800,
),
),
),
Tab(
icon: Padding(
padding: EdgeInsets.all(6.0),
child: Image.asset(
"assets/images/icons/butterlike.png",
color: Colors.grey.shade800,
),
),
),
Tab(
icon: Padding(
padding: EdgeInsets.all(6.0),
child: Image.asset(
"assets/images/icons/butterlike.png",
color: Colors.grey.shade800,
),
),
),
],
),
TabBarView(
children: <Widget>[
Container(
color: Colors.grey,
),
Container(
color: Colors.green,
),
Container(
color: Colors.purple,
),
],
),
],
),
)
],
),
);
}
I did try a variation of this but couldn't get it to work.
The error description is clear, the TabBarView doesn't have a bounded height. the parent widget also doesn't have a bounded height. So, the Expanded widget will not solve this issue.
EDIT: below solutions are for above question(with columns).In general cases, use a ListView with shrinkWrap: true.(Or any other widgets with shrinkWrap) As #Konstantin Kozirev mentioned correctly, the shrinkWrap causes some performance issues. look for a better updated solution.
There are some options:
1st Solution:
Wrap the parent widget(Column) with a limited height widget like SizedBox or AspectRatio. Then use the Expanded widget like this:
Expanded(
child: TabBarView(...),
)
2nd Solution:
Use a bounded widget like SizedBox or AspectRatio on the TabBarView itself:
SizedBox(
height: 300.0,
child: TabBarView(...),
)
Note Your can also calcuate the height dynamicly if the height is not static.
I solved it by adding TabBar inside Container and TabBarView inside Expanded:
DefaultTabController(
length: 3,
child: Column(
children: <Widget>[
Container(child: TabBar(..)),
Expanded(child: TabBarView(..)),
],
),
);
try to use IndexedStack instead of TabBarView
i tried Expanded, shrinkWrap = true , ...
but no one work's fine
just try example.
Example:
class Product extends StatefulWidget {
#override
_ProductState createState() => _ProductState();
}
class _ProductState extends State<Product> with SingleTickerProviderStateMixin {
TabController tabController;
int selectedIndex = 0;
#override
void initState() {
super.initState();
tabController = TabController(length: 5, vsync: this, initialIndex: 0);
}
#override
void dispose() {
tabController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: 3,
initialIndex: 0,
child: Scaffold(
body: ListView(
shrinkWrap: true,
children: [
TabBar(
tabs: <Widget>[
Tab(
text: 'one',
),
Tab(
text: 'two',
),
Tab(
text: 'three',
),
],
controller: tabController,
onTap: (index) {
setState(() {
selectedIndex = index;
tabController.animateTo(index);
});
},
),
IndexedStack(
children: <Widget>[
Visibility(
child: Text('test1'),
maintainState: true,
visible: selectedIndex == 0,
),
Visibility(
child: Text('test2'),
maintainState: true,
visible: selectedIndex == 1,
),
Visibility(
child: Text('test3'),
maintainState: true,
visible: selectedIndex == 2,
),
],
index: selectedIndex,
),
],
),
),
);
}
}
special thank's to #arbalest
based on #Yamin answer I used SizeBox Like below to get full page
SizedBox.expand(
child: TabBarView(),
)
or any other size :
SizedBox(
height: height:MediaQuery.of(context).size.height // or every other size ,
child: TabBarView(),
)
The error message in console mentions this: "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".
Clearly, the horizontal viewport here is referring to the TabBarView widget which is not given a height constraint.
So wrap both the TabBar and TabBarView widgets in Expanded widgets and give appropriate flex values to them to let them share their parent's height.
Concretely,
DefaultTabController(
length: 3,
child: Column(
children: <Widget>[
Expanded(
flex: 1,
child: TabBar(
tabs: <Widget>[
Tab(
icon: Padding(
padding: EdgeInsets.all(6.0),
child: Image.asset(
"assets/images/icons/butterlike.png",
color: Colors.grey.shade800,
),
),
),
Tab(
icon: Padding(
padding: EdgeInsets.all(6.0),
child: Image.asset(
"assets/images/icons/butterlike.png",
color: Colors.grey.shade800,
),
),
),
Tab(
icon: Padding(
padding: EdgeInsets.all(6.0),
child: Image.asset(
"assets/images/icons/butterlike.png",
color: Colors.grey.shade800,
),
),
),
],
),
),
Expanded(
flex: 9,
child: TabBarView(
children: <Widget>[
Container(
color: Colors.grey,
),
Container(
color: Colors.green,
),
Container(
color: Colors.purple,
),
],
),
)
],
),
)