Animated container : RenderFlex overflowed by 154 pixels on the bottom - flutter

I have a problem when resizing an animated container while setting different content height.
It throws exception while resizing :
════════ Exception caught by rendering library ════════
The following assertion was thrown during layout:
A RenderFlex overflowed by 154 pixels on the bottom.
Here is a minimal example to reproduce the problem (much more complex in my real app but you get the point) :
bool expanded;
initState() {
super.initState();
expanded = false;
}
void _toggleMode() {
setState(() {
expanded = !expanded;
});
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Test")),
body: AnimatedContainer(
height: expanded ? 230 : 70,
duration: Duration(milliseconds: 800),
child: Column(
children: <Widget>[
Expanded(
child: PageView.builder(
itemBuilder: (context, position) {
return expanded
? Column(
children: <Widget>[
Container(height: 40, color: Colors.blue),
Container(height: 40, color: Colors.blue[400]),
Container(height: 40, color: Colors.blue[300]),
Container(height: 40, color: Colors.blue[200]),
Container(height: 40, color: Colors.blue[100]),
],
)
: Column(
children: <Widget>[
Container(height: 40, color: Colors.blue),
],
);
},
),
),
InkWell(onTap: _toggleMode, child: expanded ? Icon(Icons.keyboard_arrow_up) : Icon(Icons.keyboard_arrow_down))
],
),
),
);
}
In both mode (expanded or not), the content fits the container (no overflow), problem appears only during resizing.
Of course problem does not happen with a basic container without animation.
How can I deal with this ?

This happening because you check for expanded and then immediately return the containers before the container takes its final size
A workaround will be to change the bigger column with a ListView with NeverScrollableScrollPhysics()
Edit: you don't even need to check for expanded any more and you will get the correct animation
bool expanded;
initState() {
super.initState();
expanded = false;
}
void _toggleMode() {
setState(() {
expanded = !expanded;
});
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Test")),
body: AnimatedContainer(
height: expanded ? 230 : 70,
duration: Duration(milliseconds: 800),
child: Column(
children: <Widget>[
Expanded(
child: PageView.builder(
itemBuilder: (context, position) {
return ListView(
physics: NeverScrollableScrollPhysics(),
children: <Widget>[
Column(
children: <Widget>[
Container(height: 40, color: Colors.blue),
Container(height: 40, color: Colors.blue[400]),
Container(height: 40, color: Colors.blue[300]),
Container(height: 40, color: Colors.blue[200]),
Container(height: 40, color: Colors.blue[100]),
],
),
],
);
// : Column(
// children: <Widget>[
// Container(height: 40, color: Colors.blue),
// ],
// );
},
),
),
InkWell(onTap: _toggleMode, child: expanded ? Icon(Icons.keyboard_arrow_up) : Icon(Icons.keyboard_arrow_down))
],
),
),
);
}

Related

How to create animated gender selection page?

I have built an app using Flutter. I want to create a gender selection page for it, currently I have a plain drop-down type button. I want to have an effect like this but I have no idea how to get this can anyone help?
GIF of Sample
#override
initState() {
pageController;
super.initState();
}
PageController? pageController =
PageController(initialPage: 1, viewportFraction: .5);
#override
Widget build(BuildContext context) {
var width = MediaQuery.of(context).size.width;
TabController tabController = TabController(length: 2, vsync:this);
List genders = [
Image.asset("assets/fitness_app/area1.png"),
Image.asset("assets/fitness_app/area3.png")];
return Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: () {
premiumDialogue();
},
backgroundColor: primary,
child: const Icon(
Icons.add,
),
),
backgroundColor: bgcolor,
appBar: AppBar(
toolbarHeight: 70,
leadingWidth: 65,
backgroundColor: Colors.transparent,
centerTitle: true,
title: const Text(
"Home Workouts",
style: h2black,
),
elevation: 0,
),
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(
child: PageView.builder(
controller: pageController,
clipBehavior: Clip.antiAlias,
physics: const BouncingScrollPhysics(),
itemCount: genders.length,
itemBuilder: (context, index) {
return genders[index];
},
),
),
),
],
);
I have implemented this code but I was able to achieve this only.
What I achieved
There are many approaches to achieving this you can your the pageview inside page view you can use the AnimatedContainer widget to animate the change in size and color of the selected image.
bool _isMaleSelected = false;
bool _isFemaleSelected = false;
void _selectMale() {
setState(() {
_isMaleSelected = true;
_isFemaleSelected = false;
});
}
void _selectFemale() {
setState(() {
_isMaleSelected = false;
_isFemaleSelected = true;
});
}
return Scaffold(
body: Container(
padding: padding as per your requirement,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
AnimatedContainer(
duration: Duration(milliseconds: as per your requirement),
height: _isMaleSelected ? height: height,
width: _isMaleSelected ? width: width:
decoration: BoxDecoration(
color: _isMaleSelected ? Colors as per your requirement: Colors as per your requirement,
and decoration as per your need
),
child: InkWell(
onTap: _selectMale,
child: Image.asset(
"your image path",
height: height as per your requirement,
width: width as per your requirement,
),
),
),
SizedBox(
height: height as per your requirement,
),
AnimatedContainer(
duration: Duration(milliseconds: as per your requirement),
height: _isFemaleSelected ? height as per your requirement: height as per your requirement,
width: _isFemaleSelected ? width as per your requirement: width as per your requirement,
decoration: BoxDecoration(
color: _isFemaleSelected ? Colors as per your requirement: Colors as per your requirement,
decoration as per your need
),
child: InkWell(
onTap: _selectFemale,

How to change position of Container inside Stack?

Im trying to displaying a button inside my stack but it not getting the correct position. The button is the reply Button . I added a foot how it looks at the moment you can check it what I want is displaying it on the right side of the window at the bottom with a bit of spacing between bottom and the button.
Hope anyone can help. if you need more information please leave a comment .
#override
Widget build(BuildContext context) {
var size = MediaQuery.of(context).size;
try {
return Scaffold(
body: StreamBuilder(
stream: mystreamofallvideos,
builder: (context, snapshot) {
if (snapshot.hasData &&
snapshot.connectionState != ConnectionState.waiting) {
return PageView.builder(
itemCount: snapshot.data.docs.length,
controller:
PageController(initialPage: 0, viewportFraction: 1),
scrollDirection: Axis.vertical,
itemBuilder: (context, index) {
DocumentSnapshot videos = snapshot.data.docs[index];
return Stack(children: [
Videoplayeritem(widget.videoid),
Column(children: [
Align(
alignment: Alignment.bottomLeft,
child: Container(
height: 100,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: [
IconButton(
icon: Icon(
Icons.close,
color: Colors.white,
size: 35,
),
onPressed: () {
Navigator.of(context).pop();
}),
SizedBox(
width: 190,
),
],
),
),
),
Container(
color: Colors.red,
width: 210,
height: 94,
//color: Colors.blue.withOpacity(0.5),
child: InkWell(
onTap: () => sharevideo(
widget.videoid, videos.data()['id']),
child: Icon(Icons.reply,
size: 55, color: Colors.white),
),
),
]),
//starssonthe right
]);
});
} else {
return Center(child: CircularProgressIndicator());
}
}),
);
} catch (e) {
e.toString();
}
}
}
This is how it looks
enter image description here
Wrap it in an align and add a padding to the bottom:
Align(
alignment: Alignment.bottomRight,
child: Container(
height: 40,
padding: const EdgeInsets.only(bottom: 16),
child: OutlinedButton(
onPressed: () {},
child: Text('mybutton'),
),
)
you can wrap your container with either Positioned or Align widgets
like :
Positioned(
top: 0.0,
left: 0.0,
child: Icon(Icons.message,
size: 128.0, color: Colors.greenAccent[400]), //Icon
),

RenderBox was not laid out, Flutter Listview Builder not Displaying

I'm New to this Framework, And I'm Unable to Display the ListViewBuilder Items. I'm Getting this error in Console
════════ Exception caught by rendering library ═════════════════════════════════
RenderBox was not laid out: RenderRepaintBoundary#f28ee relayoutBoundary=up14 NEEDS-PAINT
'package:flutter/src/rendering/box.dart':
Failed assertion: line 1785 pos 12: 'hasSize'
class _ViewCartState extends State<ViewCart> {
List<dynamic> cartData;
#override
void initState() {
super.initState();
APIService apiService = new APIService();
apiService.apiCall().then((value) async {
setState(() {
cartData = value.data.result.cartData;
print(cartData);
});
});
}
#override
Widget build(BuildContext context) {
loadData();
var veg;
return Scaffold(
appBar: AppBar(
iconTheme: IconThemeData(
color: kHintColor, //change your color here
),
title: Text("Cart Page", style: Theme.of(context).textTheme.bodyText1),
),
body: Stack(
children: <Widget>[
SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
// width: 500, //if this Height I'm Not giving Then List not Displaying.
padding: EdgeInsets.all(20.0),
color: Theme.of(context).cardColor,
child: Text("Your Cart Items",
style: Theme.of(context)
.textTheme
.headline6
.copyWith(
color: Color(0xff616161),
letterSpacing: 0.67)),
),
Divider(
color: Theme.of(context).cardColor,
thickness: 1.0,
),
Padding(
padding: const EdgeInsets.all(10),
child: ListView.builder(
itemCount: cartData.length,
itemBuilder: (context, index) => Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
cartItemListTile(context, cartData, index),
],
),
),
),
),
],
),
),
Align(
alignment: Alignment.bottomCenter,
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
BottomBar(
text: "go to next page"),
],
),
),
],
),
);
}
This is my ListView builder Return Function
ListTile cartItemListTile(
BuildContext context, List<dynamic> cartData, int index) {
int qty;
return ListTile(
title: Padding(
padding: EdgeInsets.only(top: 8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Image.network(
cartData[index].itemimage.image,
height: 40,
width: 40,
),
]),
),
);
}
}
Please help me with that. I cant Set the Container Height Because I have lots of Fields out of that List Also.
In the Listview.builder
Add these 2 lines ..
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,

Flutter: Expanded IconButton still shows under the Container

AnimatedContainer(
...
child: Container(
child: Column(
children: [
Row(
children: [
Container(
width:60,
height:50,
color: Colors.black,
),
],
),
Expanded(
child: GestureDetector(
onTap: () {
print('what');
},
child: Container(
height: 50,
child: Column(
children: [
Expanded(
child: Text('asdf'),
),
Expanded(
child: IconButton(
icon: Icon(Icons.ac_unit),
onPressed: () {},
),
I have this AnimatedContainer widget here. My Text() widget and RaisedButton widget are hidden inside the box. They appear as the AnimatedContainer expand. However, my IconButton doesn't.
Also, Icon widget also stays like IconButton widget. How can I make it appear when the AnimatedContainer is stretched like the Text widget?
I've modified your code, hope this is what u want.
class _RowStructureState extends State<RowStructure> {
bool pressed = false;
#override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
setState(() {
pressed = !pressed;
});
print(pressed);
},
child: Column(children: <Widget>[
AnimatedContainer(
height: pressed ? 120 : 50,
color: Colors.green,
duration: Duration(seconds: 1),
child: Stack(
children: [
Container(
height: 50,
width: 50,
color: Colors.black,
),
Positioned(
bottom:0,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text('asd'),
IconButton(
padding: EdgeInsets.all(0),
icon: Icon(Icons.ac_unit,),
onPressed: pressed?(){}:null,
),
],
),
)
],
),
)
]),
);
}
}

onTap function not working for Align widgets in Flutter

I have a widget with a GestureDetector inside of Stack having Align as a child(where onTap is registered)
The layout code is,
body: Stack(
children: [
Padding(
padding: EdgeInsets.only(top: 28.0.vs),
child: PageView.builder(
controller: _pageController,
onPageChanged: _changeCurrentSlide,
itemCount: 2,
itemBuilder: (context, index) => Align(
alignment: Alignment.topCenter,
child: Container(
height: 700.h,
child: Card(
elevation: 20,
color: AppColors.black,
child: Container(
width: 350.w,
child: Stack(
overflow: Overflow.visible,
children: [
Text('Hai'),
GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () { print('hello'); },
child: Align(
alignment: Alignment(0, 1.1),
child: Material(
elevation: 20,
color: AppColors.transparent,
child: Container(
width: 70,
height: 40,
color: AppColors.goldenYellow,
child: Center(
child: Text(
'Next'
),
),
),
),
),
),
],
),
),
),
),
),
),
),
],
),
I need to call a function on tap of Align widget but only half the area of GestureDetector is working and on other half, onTap is not detected
Image for GestureDector, not working
This behavior occurs because the stack checks whether the pointer is inside its bounds before checking whether a child got hit:
If you notice the part of the button which is overflowing or not within the constraints of the Stack does not receive the tap. This is because the Stack widgets first checks whether the hit was inside its bounds before checking whether its child got tapped.
As a workaround you may wrap the parent widget of the Stack with Gesture detector and then check if the hit was within the bounds of your button or the intended widget. Please check the code below, I had to make some changes to your code in order to make my code work. Note if 'clipBehavior: Clip.none,' in my code gives you an error then you may comment it out and use 'overflow: Overflow.visible,' instead. Please check if this code works for you.
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
final Color darkBlue = const Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(
MaterialApp(
theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
debugShowCheckedModeBanner: false,
home: MyApp(),
),
);
}
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
final List<GlobalKey> _key = <GlobalKey>[];
final PageController _controller = PageController();
int _currentPage = 0;
void onTapDown(
BuildContext context,
TapDownDetails details,
) {
final RenderBox box = context.findRenderObject();
final Offset localOffset = box.globalToLocal(details.globalPosition);
final RenderBox containerBox =
_key[_currentPage].currentContext.findRenderObject();
final Offset containerOffset = containerBox.globalToLocal(localOffset);
final onTap = containerBox.paintBounds.contains(containerOffset);
if (onTap) {
print("hello");
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: GestureDetector(
onTapDown: (TapDownDetails details) {
onTapDown(context, details);
},
child: Container(
width: 500,
height: MediaQuery.of(context).size.height,
color: Colors.white,
child: Stack(
children: [
Padding(
padding: EdgeInsets.only(
top: 28.0), // EdgeInsets.only(top: 28.0.vs),
child: PageView.builder(
controller: _controller, //_pageController,
onPageChanged: (val) {
_currentPage = val;
//_changeCurrentSlide();
},
itemCount: 2,
itemBuilder: (context, index) {
_key.add(GlobalKey());
return Align(
alignment: Alignment.topCenter,
child: Container(
height: 600, //700.h,
child: Card(
elevation: 20,
color: Colors.white, // AppColors.black,
child: Container(
width: 350, //350.w,
child: Stack(
//overflow: Overflow.visible,
clipBehavior: Clip.none,
children: [
Text('Hai'),
//GestureDetector(
// behavior: HitTestBehavior.opaque,
// onTap: () { print('hello'); },
// child:
Align(
alignment: Alignment(0, 1.1),
child: Material(
elevation: 20,
color: Colors
.transparent, // AppColors.transparent,
child: Container(
key: _key[index],
width: 70,
height: 40,
color: Colors
.black, //AppColors.goldenYellow,
child: Center(
child: Text('Next'),
),
),
),
),
//),
],
),
),
),
),
);
},
),
),
],
),
),
),
);
}
}