Getting 'Horizontal viewport was given unbounded height.' with TabBarView in flutter - 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,
),
],
),
)
],
),
)

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 ->

A RenderFlex overflowed by 1.9 pixels on the bottom

I am getting a A RenderFlex overflowed by 1.9 pixels on the bottom error in my flutter app.
I wrapped all the ROW's in Expanded and I wrapped the main Column in a SingleChildScrollView but still have the issue. As you can see from the screenshots the view on the bottom scrolls up. The item on the top squishes down as it goes off screen. I am not even sure which Row is causing the issue?
UPDATE:
Seeing this now.
The following assertion was thrown while applying parent data.:
Incorrect use of ParentDataWidget.
The ParentDataWidget Expanded(flex: 2) wants to apply ParentData of type FlexParentData to a RenderObject, which has been set up to accept ParentData of incompatible type ParentData.
Usually, this means that the Expanded widget has the wrong ancestor RenderObjectWidget. Typically, Expanded widgets are placed directly inside Flex widgets.
The offending Expanded is currently placed inside a Semantics widget.
The ownership chain for the RenderObject that received the incompatible parent data was:
Column ← Expanded ← Semantics ← Align ← ConstrainedBox ← Container ← LayoutBuilder ← DefaultTextStyle ← Align ← Transform ← ⋯
.enter image description here
CODE:
import 'package:animation_wrappers/animation_wrappers.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:qvid/BottomNavigation/Explore/explore_page.dart';
import 'package:qvid/Components/profile_page_button.dart';
import 'package:qvid/Components/row_item.dart';
import 'package:qvid/Components/sliver_app_delegate.dart';
import 'package:qvid/Components/tab_grid.dart';
import 'package:qvid/Locale/locale.dart';
import 'package:qvid/Routes/routes.dart';
import 'package:qvid/BottomNavigation/MyProfile/followers.dart';
import 'package:qvid/Theme/colors.dart';
import 'package:qvid/BottomNavigation/MyProfile/following.dart';
class UserProfilePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return UserProfileBody();
}
}
class UserProfileBody extends StatefulWidget {
#override
_UserProfileBodyState createState() => _UserProfileBodyState();
}
class _UserProfileBodyState extends State<UserProfileBody> {
bool isFollowed = false;
var followText;
final key = UniqueKey();
#override
Widget build(BuildContext context) {
var locale = AppLocalizations.of(context);
return Scaffold(
backgroundColor: darkColor,
body: DefaultTabController(
length: 2,
child: SafeArea(
child: NestedScrollView(
headerSliverBuilder:
(BuildContext context, bool innerBoxIsScrolled) {
return <Widget>[
SliverAppBar(
expandedHeight: 400.0,
floating: false,
actions: <Widget>[
PopupMenuButton(
color: backgroundColor,
icon: Icon(
Icons.more_vert,
color: secondaryColor,
),
shape: OutlineInputBorder(
borderRadius: BorderRadius.circular(12.0),
borderSide: BorderSide.none),
itemBuilder: (BuildContext context) {
return [
PopupMenuItem(
child: Text(locale!.report!),
value: locale.report,
textStyle: TextStyle(color: secondaryColor),
),
PopupMenuItem(
child: Text(locale.block!),
value: locale.block,
textStyle: TextStyle(color: secondaryColor),
),
];
},
)
],
flexibleSpace: FlexibleSpaceBar(
centerTitle: true,
title: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Column(
children: <Widget>[
Spacer(flex: 10),
FadedScaleAnimation(
child: CircleAvatar(
radius: 28.0,
backgroundImage:
AssetImage('assets/user/user1.png'),
),
),
Spacer(),
Expanded(
flex: 2,
child: Row(
children: [
Spacer(flex: 12),
Text(
'Emili Williamson',
style: TextStyle(fontSize: 16),
),
Spacer(),
Image.asset(
'assets/icons/ic_verified.png',
scale: 4,
),
Spacer(flex: 8),
],
),
),
Text(
'#emilithedancer',
style:
TextStyle(fontSize: 10, color: disabledTextColor),
),
Spacer(),
FadedScaleAnimation(
child: Expanded(
flex: 2,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ImageIcon(
AssetImage(
"assets/icons/ic_fb.png",
),
color: secondaryColor,
size: 10,
),
SizedBox(
width: 15,
),
ImageIcon(
AssetImage("assets/icons/ic_twt.png"),
color: secondaryColor,
size: 10,
),
SizedBox(
width: 15,
),
ImageIcon(
AssetImage("assets/icons/ic_insta.png"),
color: secondaryColor,
size: 10,
),
],
),
),
),
Spacer(),
Text(
locale!.comment7!,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 10, fontWeight: FontWeight.w500),
),
Spacer(),
Expanded(
flex: 2,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ProfilePageButton(
locale.message,
() => Navigator.pushNamed(
context, PageRoutes.chatPage)),
SizedBox(width: 16),
isFollowed
? ProfilePageButton(locale.following, () {
setState(() {
isFollowed = false;
});
})
: ProfilePageButton(
locale.follow,
() {
setState(() {
isFollowed = true;
});
},
color: mainColor,
textColor: secondaryColor,
),
],
),
),
Spacer(),
Expanded(
flex: 2,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
RowItem(
'1.2m',
locale.liked,
Scaffold(
appBar: AppBar(
title: Text('Liked'),
),
body: TabGrid(
food + lol,
),
)),
RowItem('12.8k', locale.followers, FollowersPage()),
RowItem('1.9k', locale.following, FollowingPage()),
],
),
),
],
)),
),
),
SliverPersistentHeader(
delegate: SliverAppBarDelegate(
TabBar(
labelColor: mainColor,
unselectedLabelColor: lightTextColor,
indicatorColor: transparentColor,
tabs: [
Tab(icon: Icon(Icons.dashboard)),
Tab(
icon: ImageIcon(AssetImage(
'assets/icons/ic_like.png',
)),
),
],
),
),
pinned: true,
),
];
},
body: TabBarView(
children: <Widget>[
FadedSlideAnimation(
child: TabGrid(dance),
beginOffset: Offset(0, 0.3),
endOffset: Offset(0, 0),
slideCurve: Curves.linearToEaseOut,
),
FadedSlideAnimation(
child: TabGrid(food + lol),
beginOffset: Offset(0, 0.3),
endOffset: Offset(0, 0),
slideCurve: Curves.linearToEaseOut,
),
],
),
),
),
),
);
}
}
The error is caused in this row. Remove this row and see if you still see the same problem in the Row above it. If you do then i guess it has something to do with the code below it. Is the code below this one also in singlechildscrollview or expanded? if its not then add it. i'm on phone so it's hard for me to clearly see the syntax.
Spacer(),
Expanded(
flex: 2,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
RowItem(
'1.2m',
locale.liked,
Scaffold(
appBar: AppBar(
title: Text('Liked'),
),
body: TabGrid(
food + lol,
),
)),
RowItem('12.8k', locale.followers, FollowersPage()),
RowItem('1.9k', locale.following, FollowingPage()),
],
),
),
],
)),
),
),
As document says, You cannot use the Expanded widget inside the child of FadedScaleAnimation
You should only use the Expanded Widget as the direct child of Row/Column/Flex because these are flex widgets
Try putting FadedScaleAnimation inside Expanded Widget in your Column widget, the Expanded widget should be the direct child of your Column

Flutter - make scrollable a page that contains a DefaultTabController

I am developing an app and I have a page in which I show a block of data and below that I show the tabBars and TabBarView containing additional data. The problem I am struggling with is that if I try to wrap the widget "DefaultTabController" with "SingleChildScrollView" it throws an error and the page does not work.
I need to find a way to show the tabBars and TabBarView at the bottom of the page and make the entire page scrollable
I put the code:
In the build method I put 4 widgets inside the column
_showEventHeader shows a single image with a title
_showUserAndEventData shows plain text
_showTabs shows the tab headers
_showTabsContent shows the content of the tabs (images and comments)
#override
Widget build(BuildContext context) {
return DefaultTabController(
length: 2,
child: Scaffold(
backgroundColor: Theme.of(context).primaryColor,
body: Column(
children: [
..._showEventHeader(),
Container(
padding: EdgeInsets.all(15),
child: _showUserAndEventData()),
_showTabs(),
_showTabsContent(),
],
)
));
}
List<Widget> _showEventHeader() {
return [
SizedBox(
height: 20,
),
GestureDetector(
onTap: () {
if (Val.valStr(widget.evento.bannerUrl).isNotEmpty) {
Navigator.of(context).push(MaterialPageRoute(builder: (ctx) {
return FlypperFullImage(
imgURL: widget.evento.bannerUrl,
);
}));
}
},
child: Stack(
alignment: Alignment.bottomRight,
children: [
FlypperCustomImageNetWork(
imageURL: widget.evento.bannerUrl,
height: 200,
width: 200,
showAsRectangle: true,
fillWidth: true,
),
Container(
child: FlypperQrImage(
qrData: widget.evento.code,
size: 65,
),
)
],
),
),
SizedBox(
height: 20,
),
!_ticketsAvailable
? Text('$_noTicketAvailableMessage',
style: Theme.of(context).textTheme.headline2)
: SizedBox(
height: 1,
),
Card(
color: Theme.of(context).primaryColor,
elevation: 5,
child: Padding(
padding: const EdgeInsets.all(5),
child: Text(
Val.valStr(widget.evento.name).isNotEmpty
? Val.valStr(widget.evento.name)
: 'Sin nombre',
textAlign: TextAlign.justify,
style: Theme.of(context)
.textTheme
.headline1 /*FlypperStyleHelper.eventTitle(context)*/),
),
),
SizedBox(
height: 10,
),
];
}
Widget _showUserAndEventData() {
return SingleChildScrollView(
child: Container(
color: Theme.of(context).primaryColor,
child: Column(
children: [
SizedBox(height: 10),
Row(mainAxisAlignment: MainAxisAlignment.start, children: [
this.user != null
? /*FlypperCustomImageBase64(
imageBase64: this.user.profileImageUrl)*/
FlypperCustomImageNetWork(
imageURL: this.user.profileImageUrl,
keepImageCached: true,
height: 65,
width: 65,
)
: SizedBox(height: 1),
SizedBox(
height: 10,
),
Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
this.user != null
? this.user.userName.isEmpty
? this.user.email
: this.user.userName
: '',
style: Theme.of(context).textTheme.headline1,
/* FlypperStyleHelper.eventUserData(context, 18),*/
),
Text(
this.user != null
? Val.valInt(this.user.followers).toString() +
' seguidores'
: '',
style: Theme.of(context).textTheme.bodyText1
/*FlypperStyleHelper.eventUserData(context, 15),*/
)
],
),
)
]),
_getEventDetailInfo(),
SizedBox(
height: 20,
),
_showBuyButton(),
SizedBox(
height: 10,
),
FlypperIconButton(
icon: Icons.location_on,
width: 150,
handlerFunction: () => _openMapWithCalculatedRoute(context),
),
Divider(
color: Colors.grey,
thickness: 2,
)
],
),
),
);
}
Widget _showTabs() {
return TabBar(
isScrollable: true,
labelStyle: Theme.of(context).textTheme.headline2,
tabs: [
Tab(
text: 'Fotos, videos...',
/*icon: Icon(Icons.event, color: Theme.of(context).buttonColor)*/
),
Tab(
text: 'Comentarios',
/*icon: Icon(Icons.attach_file, color: Theme.of(context).buttonColor),*/
),
],
);
}
Widget _showTabsContent() {
return Flexible(
child: TabBarView(
children: [
SingleChildScrollView(
child: Column(
children: [
Container(
color: Theme.of(context).primaryColor,
child: Column(children: [_getDetailImage()]),
),
],
),
),
Container(child: Text('Comments section')) //comentarios, pendiente
// SingleChildScrollView(
// child: Container(
// color: Theme.of(context).primaryColor,
// child: Column(children: [_getDetailImage()]),
// ),
// ),
// Container(child: Text('Comments section')) //comentarios, pendiente
],
),
);
}
I also attached an screenshot so you can understand better what I am saying
Try this i have a give example and edit it some value :-
TabBar(
isScrollable: true,
unselectedLabelColor: Colors.white.withOpacity(0.3),
indicatorColor: Colors.white,
tabs: [
Tab(
child: Text('Tab 1'),
),
Tab(
child: Text('Investment'),
),
Tab(
child: Text('Your Earning'),
),
]),
And all Widget vale call in a List view Like this:-
_showEventHeader() {
return new Container(
height: 20,
child: ListView(
shrinkWrap: true,
scrollDirection: Axis.vertical,
Column(
children: [])));}

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

How to put scroll view inside stack widget in 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(),
],
),