A RenderFlex overflowed by 141 pixels on the bottom - flutter

I added a bottom navigation bar on the bottom of the screen but it has interfered with the overflowed pixels. A part of my code which is the CartTotal() wasnt shown in the code. I tried using Listview but im not able to add both of the items in the column for both CartProducts() and CartTotal(). This was the suggestion:
Consider applying a flex factor (e.g. using an Expanded widget) to force the children of the RenderFlex to fit within the available space instead of being sized to their natural size.
This is considered an error condition because it indicates that there is content that cannot be seen. If the content is legitimately bigger than the available space, consider clipping it with a ClipRect widget before putting it in the flex, or using a scrollable container rather than a Flex, like a ListView.
import 'package:flutter/material.dart';
import '../../widgets/cart_products.dart';
import '../../widgets/cart_total.dart';
import 'package:grocery_shopping/widgets/widgets.dart';
import '../Home/components/bottom_bar.dart';
import '../Home/components/enum.dart';
class CartScreen extends StatelessWidget {
const CartScreen({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Your Cart")),
bottomNavigationBar: const CustomBottomBar(selectMenu: MenuState.cart),
body: Column(
children: [
CartProducts(),
CartTotal(),
],
),
);
}
}
this is my CartProducts()
import 'package:flutter/material.dart';
import 'package:grocery_shopping/controllers/cart_controller.dart';
import 'package:grocery_shopping/models/product_model.dart';
import 'package:get/get.dart';
class CartProducts extends StatelessWidget {
final CartController controller = Get.find();
CartProducts({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Obx(
() => SizedBox(
height: 600,
child: ListView.builder(
itemCount: controller.products.length,
itemBuilder: (BuildContext context, int index) {
return CartProductCard(
controller: controller,
product: controller.products.keys.toList()[index],
quantity: controller.products.values.toList()[index],
index: index,
);
}),
),
);
}
}
class CartProductCard extends StatelessWidget {
final CartController controller;
final Product product;
final int quantity;
final int index;
const CartProductCard({
Key? key,
required this.controller,
required this.product,
required this.quantity,
required this.index,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.symmetric(
horizontal: 20.0,
vertical: 10,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
CircleAvatar(
radius: 40,
backgroundImage: NetworkImage(
product.imageUrl,
),
),
SizedBox(
width: 20,
),
Expanded(
child: Text(product.name),
),
IconButton(
onPressed: () {
controller.removeProduct(product);
},
icon: Icon(Icons.remove_circle),
),
Text('$quantity'),
IconButton(
onPressed: () {
controller.addProduct(product);
},
icon: Icon(Icons.add_circle),
),
],
),
);
}
}
This is my CartTotal()
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:grocery_shopping/controllers/cart_controller.dart';
import 'package:get/get.dart';
class CartTotal extends StatelessWidget {
final CartController controller = Get.find();
CartTotal({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Obx(
() => Container(
padding: const EdgeInsets.symmetric(horizontal: 75),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'Total',
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
),
),
Text(
'\RM${controller.total}',
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
),
),
],
)),
);
}
}

Related

Getx not updating list of TextFormField correctly

I am using Getx and ListView.builder in a Flutter Web app to render a list of items with TextFormField. Each rendered item has a delete button. When I click to delete an item, the list containing the data seems to update correctly but the corresponding UI incorrectly removes the absolute last item displayed instead of the actual item that you clicked to delete. This problem seems to happen with TextFormField specifically.
I have included below a sample app that illustrates the problem. To test, just install Getx, then run the app (I run it as a Web app). Once the app is running, in the left column (named 'Using TextFormFields'), try to delete items and you'll see the problem -- it is always the last item displayed that deletes, even if you click to delete the first item. For comparison, I have included on right side a set up using ListTiles instead of TextFormFields and that works without a problem.
Does anyone know why this problem occurs with TextFormField specifically? Do you know how to solve this? Thanks in advance for any help!
import 'package:flutter/material.dart';
import 'package:get/get.dart';
class Item {
final int id;
final String name;
Item({
required this.id,
required this.name,
});
}
class OverviewPageController extends GetxController {
final itemsList = [
Item(id: 0, name: 'Item 1'),
Item(id: 1, name: 'Item 2'),
Item(id: 2, name: 'Item 3'),
Item(id: 3, name: 'Item 4'),
].obs;
void deleteItem(Item item) {
int index = itemsList.indexOf(item);
var itemRemoved = itemsList.removeAt(index);
print('item deleted: ${itemRemoved.name}');
itemsList.refresh();
}
}
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return const GetMaterialApp(
debugShowCheckedModeBanner: false,
home: OverviewPage(),
);
}
}
class OverviewPage extends StatelessWidget {
const OverviewPage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Padding(
padding: const EdgeInsets.all(40),
child: Row(
children: const [
Expanded(child: TextFormFieldsSection()),
SizedBox(width: 40),
Expanded(child: ListTilesSection()),
],
),
),
),
);
}
}
class ListTilesSection extends StatelessWidget {
const ListTilesSection({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
final controller1 = Get.put(OverviewPageController(), tag: '1');
return Column(
children: [
const Text('Using ListTiles', style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold)),
const SizedBox(height: 20),
Obx(
() => ListView.builder(
shrinkWrap: true,
itemCount: controller1.itemsList.length,
itemBuilder: (context, index) {
return Column(
children: [
ListTile(
title: Text(controller1.itemsList[index].name),
trailing: OutlinedButton(
onPressed: () => controller1.deleteItem(controller1.itemsList[index]),
child: const Icon(Icons.delete_forever),
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
side: const BorderSide(color: Colors.black12),
),
),
const SizedBox(height: 5),
],
);
},
),
),
],
);
}
}
class TextFormFieldsSection extends StatelessWidget {
const TextFormFieldsSection({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
final controller2 = Get.put(OverviewPageController(), tag: '2');
return Column(
children: [
const Text('Using TextFormFields', style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold)),
const SizedBox(height: 20),
Obx(
() => ListView.builder(
shrinkWrap: true,
itemCount: controller2.itemsList.length,
itemBuilder: (context, index) {
return Column(
children: [
Container(
padding: const EdgeInsets.symmetric(horizontal: 16),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
border: Border.all(color: Colors.black12)
),
child: Row(
children: [
Expanded(
child: TextFormField(
readOnly: true,
initialValue: controller2.itemsList[index].name,
decoration: const InputDecoration(border: InputBorder.none),
),
),
OutlinedButton(
onPressed: () => controller2.deleteItem(controller2.itemsList[index]),
child: const Icon(Icons.delete_forever),
),
],
),
),
const SizedBox(height: 5),
],
);
},
),
),
],
);
}
}
you're code is totally right and should work fine, it's Flutter that doesn't know which widget to exactly delete, I will explain:
when Flutter engine notices that an existent element in the tree is deleted from the tree ( which your code does ) it look to replace it with some other widget with it's same runtimeType, so when you wanna delete a TextFormField, Flutter mistaken the exact widget to remove even if your code is totally fine.
This behavior is really helpful for performance in most cases, to avoid extra necessary builds in the tree when it should.
The Answer of your problem is by telling Flutter that each TextFormField is unique from all others, by assigning a unique Key to the TextFormField, Here is your new code:
import 'package:flutter/material.dart';
import 'package:get/get.dart';
class Item {
final int id;
final String name;
Item({
required this.id,
required this.name,
});
}
class OverviewPageController extends GetxController {
final itemsList = [
Item(id: 0, name: 'Item 1'),
Item(id: 1, name: 'Item 2'),
Item(id: 2, name: 'Item 3'),
Item(id: 3, name: 'Item 4'),
].obs;
void deleteItem(Item item) {
int index = itemsList.indexOf(item);
var itemRemoved = itemsList.removeAt(index);
print('item deleted: ${itemRemoved.name}');
itemsList.refresh();
}
}
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return const GetMaterialApp(
debugShowCheckedModeBanner: false,
home: OverviewPage(),
);
}
}
class OverviewPage extends StatelessWidget {
const OverviewPage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Padding(
padding: const EdgeInsets.all(40),
child: Row(
children: const [
Expanded(child: TextFormFieldsSection()),
SizedBox(width: 40),
Expanded(child: ListTilesSection()),
],
),
),
),
);
}
}
class ListTilesSection extends StatelessWidget {
const ListTilesSection({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
final controller1 = Get.put(OverviewPageController(), tag: '1');
return Column(
children: [
const Text('Using ListTiles',
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold)),
const SizedBox(height: 20),
Obx(
() => ListView.builder(
shrinkWrap: true,
itemCount: controller1.itemsList.length,
itemBuilder: (context, index) {
return Column(
key: UniqueKey(), // add UniqueKey()
children: [
ListTile(
key: UniqueKey(),
title: Text(controller1.itemsList[index].name),
trailing: OutlinedButton(
onPressed: () =>
controller1.deleteItem(controller1.itemsList[index]),
child: const Icon(Icons.delete_forever),
),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
side: const BorderSide(color: Colors.black12),
),
),
const SizedBox(height: 5),
],
);
},
),
),
],
);
}
}
class TextFormFieldsSection extends StatelessWidget {
const TextFormFieldsSection({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
final controller2 = Get.put(OverviewPageController(), tag: '2');
return Column(
children: [
const Text('Using TextFormFields',
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold)),
const SizedBox(height: 20),
Obx(
() => ListView.builder(
shrinkWrap: true,
itemCount: controller2.itemsList.length,
itemBuilder: (context, index) {
return Column(
children: [
Container(
padding: const EdgeInsets.symmetric(horizontal: 16),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10),
border: Border.all(color: Colors.black12)),
child: Row(
children: [
Expanded(
child: TextFormField(
key: UniqueKey(), // add UniqueKey()
readOnly: true,
initialValue: controller2.itemsList[index].name,
decoration:
const InputDecoration(border: InputBorder.none),
),
),
OutlinedButton(
onPressed: () => controller2
.deleteItem(controller2.itemsList[index]),
child: const Icon(Icons.delete_forever),
),
],
),
),
const SizedBox(height: 5),
],
);
},
),
),
],
);
}
}
Note the UniqueKey() I assigned to widgets, now run your app again and it should work as you expect.
Please, refer also to those topics:
When to Use Keys - Flutter Widget
Key

setState() or markNeedsBuild() called during build. This QuoteList widget cannot be marked as needing to build because the framework in the process

i am learning flutter and i am taking demo in which a guy is calling a fucnction on button pressed. but i am getting an error : setState() or markNeedsBuild() called during build
please guide me what to do
below is my code
QuoteList.dart
import 'dart:ffi';
import 'quote.dart';
import 'package:flutter/material.dart';
import 'QuoteCard.dart';
void main() {
runApp(MaterialApp(home: QuoteList()));
}
class QuoteList extends StatefulWidget {
const QuoteList({Key? key}) : super(key: key);
#override
State<QuoteList> createState() => _QuoteListState();
}
class _QuoteListState extends State<QuoteList> {
List<Quote> quotes = [
Quote('Be yourself, Everyone else is already taken.','sana'),
Quote('I have nothing to declare except my genius','sana'),
Quote('The truth is rarely pure and never simple.', 'sana'),
];
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey[200],
appBar: AppBar(
title: Text(
"Awesome Quotes",
),
centerTitle: true,
backgroundColor: Colors.red,
),
body: Column(
children: quotes.map((quote) => QuoteCard(
quote: quote,
delete: () {
setState(() {
quotes.remove(quote);
});
}
)).toList()
)
);
}
}
and below is QuoteCard widget code. QuoteCard is a widget in seperate class and is called by main.dart file. The code is below for the quote card:
import 'dart:ffi';
import 'quote.dart';
import 'package:flutter/material.dart';
class QuoteCard extends StatelessWidget {
final Quote quote;
final Function delete;
QuoteCard( {required this.quote, required this.delete });
#override
Widget build(BuildContext context) {
return Card(
margin: EdgeInsets.fromLTRB(16, 16, 16, 0),
color: Colors.grey[100],
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Text(
quote.text,
style: TextStyle(
fontSize: 18,
color: Colors.grey[600],
),
),
SizedBox(height: 6.0),
Text (
quote.author,
style: TextStyle(
fontSize: 18,
color: Colors.grey[600],
),
),
SizedBox(height: 6.0),
FlatButton.icon(
onPressed: delete(),
icon: Icon(Icons.delete),
label: Text('delete')
)
]
),
),
);
}
}
It's coming from
onPressed: delete(),
which call the function every time the widget is built.
Try this instead
onPressed: delete,

flutter 2 SliverPersistentHeader - avoid overlap during scroll

Here is my code :
import 'package:all_in_one/cooking/pages/recipe/header/search_bar_header.dart';
import 'package:all_in_one/cooking/pages/recipe/header/welcome_header.dart';
import 'package:flutter/material.dart';
class MyRecipePage extends StatefulWidget {
final String title;
MyRecipePage({Key? key, required this.title}) : super(key: key);
#override
_MyRecipePageState createState() => _MyRecipePageState();
}
class _MyRecipePageState extends State<MyRecipePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: CustomScrollView(
slivers: <Widget>[
WelcomeHeader(),
SearchBarHeader(),
SliverGrid.count(),
],
) ,
);
}
}
class WelcomeHeader extends StatelessWidget {
#override
Widget build(BuildContext context) {
return
SliverPersistentHeader(
floating: true,
delegate: SliverAppBarDelegate(
minHeight: 0,
maxHeight: 100,
child: Container(
color: Colors.white,
child: _MyWelcomingHeader(),
),
),
);
}
}
class _MyWelcomingHeader extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Column(
children: [
Flexible(
child: CircleAvatar(
radius: 57,
backgroundColor: Colors.grey.shade50,
child: Image.asset("assets/emoji-food.jpg"),
),
),
Flexible(
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Text(
'Enjoy the recipes',
style: TextStyle(
color: Colors.black,
fontSize: 26.0,
fontWeight: FontWeight.bold,
),
),
),
),
],
);
}
}
class SearchBarHeader extends StatelessWidget {
#override
Widget build(BuildContext context) {
return SliverPersistentHeader(
pinned: true,
delegate: SliverAppBarDelegate(
minHeight: 50,
maxHeight: 50,
child: Container(
color: Colors.white,
child: _MySearchBar(),
),
),
);
}
}
class _MySearchBar extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
const SizedBox(width: 10),
const Icon(Icons.search, color: Colors.grey, size: 30),
const SizedBox(width: 5),
Text("Search product",
style: TextStyle(
color: Colors.grey.shade500, fontSize: 12, fontWeight: FontWeight.w200))
],
);
}
}
The code of the silver bar Delegate is from this stackoverflow post
import 'package:flutter/material.dart';
import 'dart:math' as math;
class SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
final double minHeight;
final double maxHeight;
final Widget child;
SliverAppBarDelegate({
required this.minHeight,
required this.maxHeight,
required this.child,
});
#override
double get minExtent => minHeight;
#override
double get maxExtent => math.max(maxHeight, minHeight);
#override
Widget build(
BuildContext context, double shrinkOffset, bool overlapsContent) {
return SizedBox.expand(child: child);
}
#override
bool shouldRebuild(SliverAppBarDelegate oldDelegate) {
return maxHeight != oldDelegate.maxHeight ||
minHeight != oldDelegate.minHeight ||
child != oldDelegate.child;
}
}
My goal is to have 2 SliverPersistentHeader, one pinned and one floating.
The one floating (the 1st one) should resize the text and the image while scrolling..
In the following screenshot, we can see that the 2nd SliverPersistentHeader is overlapping the 1st one.
How can I do to make the Text resize itself. I try to use Flexible like I did for the CircleAvatar but I can't succeed :/
Thanks
I found a solution using the opacity, so my WelcomeHeader becomes :
import 'package:flutter/material.dart';
import 'dart:math' as math;
class WelcomeHeader extends StatelessWidget {
#override
Widget build(BuildContext context) {
return SliverAppBar(
backgroundColor: Colors.white,
pinned: false,
floating: false,
snap: false,
expandedHeight: 120,
flexibleSpace: _MyWelcomingHeader()
);
}
}
class _MyWelcomingHeader extends StatelessWidget {
#override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (context, c) {
final settings = context
.dependOnInheritedWidgetOfExactType<FlexibleSpaceBarSettings>();
final deltaExtent = settings!.maxExtent - settings.minExtent;
final t =
(1.0 - (settings.currentExtent - settings.minExtent) / deltaExtent)
.clamp(0.0, 1.0);
final fadeStart = math.max(0.0, 1.0 - kToolbarHeight / deltaExtent);
const fadeEnd = 1.0;
final opacity = 1.0 - Interval(fadeStart, fadeEnd).transform(t);
return Padding(
padding: const EdgeInsets.all(8.0),
child: Opacity(
opacity: opacity,
child: Column(
children: [
Flexible(
child: CircleAvatar(
radius: 57,
backgroundColor: Colors.grey.shade50,
child: Image.asset("assets/emoji-food.jpg"),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'Enjoy the recipes !',
style: TextStyle(
color: Colors.black,
fontSize: 26.0,
fontWeight: FontWeight.bold,
),
),
),
],
),
),
);
});
}
}

Flutter: call parent function from child widget

hi there 👋🏼 i would like to call a function from a child widget (customappbar) for example to open the drawer.
there is my code:
home_page.dart
import 'package:fahrschuleapp/widget/appbar_widget.dart';
import 'package:fahrschuleapp/widget/sidebar_widget.dart';
import 'package:flutter/material.dart';
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
drawerEnableOpenDragGesture: false,
body: SafeArea(
child: Center(
child: Column(
children: [
CustomAppBar(
pFunction: CustomAppBarFunction.menu,
pContext: context,
pTitle: 'test',
),
],
),
),
),
drawer: SideBar(),
);
}
}
i tried to say with the parameter "pFunction" which function should be called
for example navigator pop or open menu etc inside the _callFunction
appbar_widget.dart
import 'package:flutter/material.dart';
enum CustomAppBarFunction {
menu,
back,
exit,
}
class CustomAppBar extends StatelessWidget {
CustomAppBar({
Key? key,
required this.pTitle,
required this.pContext,
required this.pFunction,
}) : super(key: key);
CustomAppBarFunction pFunction;
String pTitle;
BuildContext pContext;
final List<IconData> _iconList = [
Icons.menu,
Icons.arrow_back,
Icons.close,
];
_callFunction(int index) {
switch (index) {
case 0:
Scaffold.of(pContext).openDrawer();
break;
default:
break;
}
}
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(
left: 20,
right: 20,
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Container(
margin: const EdgeInsets.all(8),
child: IconButton(
onPressed: _callFunction(pFunction.index),
icon: Icon(
_iconList[pFunction.index],
),
),
decoration: BoxDecoration(
borderRadius: const BorderRadius.all(Radius.circular(15)),
color: Theme.of(context).colorScheme.primary,
),
),
Container(
padding: const EdgeInsets.only(left: 15, right: 15),
child: Text(
pTitle,
style: const TextStyle(
fontFamily: 'Hellix',
fontSize: 20,
),
),
),
const SizedBox(
width: 50.4,
),
],
),
);
}
}
i tried to call inside the widget the _callFunction but this doesnt work
error output:
Scaffold.of() called with a context that does not contain a Scaffold.
how can i solve it? or is there a better way to do that?
Change you IconButton as below code,
Builder(builder: (context) {
return IconButton(
onPressed:() => _callFunction(pFunction.index, context),
icon: Icon(
_iconList[pFunction.index],
),
) ;
})
And change your _callFunction,
_callFunction(int index, BuildContext mContext) {
switch (index) {
case 0:
Scaffold.of(mContext).openDrawer();
break;
default:
break;
}
}
Scaffold.of() called with a context that does not contain a Scaffold.
This message appears when you try to access a Scaffold from a context that does not have a Scaffold above it. You can use a Key for that purpose. Create a GlobalKey and assign it to the Scaffold, then pass the Key to the AppBar from where you can access the Scaffold.

Listviewbuilder implementation inside Column won't work

I want to have a scrollable list on my home screen. I tried to implement my Listviewbuilder called Cardslist() into the home screen, but I always get this exception thrown: RenderFlex children have non-zero flex, incoming height constraints are unbounded. Heres the code for the home screen:
import 'package:biminda_app/Components/cards_list.dart';
import 'package:biminda_app/Components/real_new_finished_card.dart';
import 'package:flutter/material.dart';
import 'package:biminda_app/Components/custom_Buttons.dart';
import 'package:biminda_app/Components/constants.dart';
import 'package:flutter/rendering.dart';
import 'package:biminda_app/Screens/new_card_screen1.dart';
import 'package:biminda_app/Screens/settings.dart';
import 'package:biminda_app/Components/card_data.dart';
import 'package:biminda_app/Components/cards_list.dart';
class HomeScreen extends StatefulWidget {
static const String id = 'home_screen';
#override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
String individualsName;
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
Container(
padding: EdgeInsets.fromLTRB(
20,
40,
20,
0,
),
child: TextField(
style: TextStyle(
color: Colors.black,
),
decoration: kTextFieldInputDecoration,
onChanged: (value) {
individualsName = value;
// TODO: Der Input muss das Individum in der Liste
// TODO: erkennen und anzeigen
},
),
),
//TODO HIER
Expanded(
child: Column(
children: <Widget>[
CardsList(),
],
)),
Center(
child: Container(
child: MainButton(
functionality: 'New',
onPressed: () {
Navigator.pushNamed(context, NewCard.id);
}),
),
),
Padding(
padding: const EdgeInsets.all(16.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: <Widget>[
SideButton(
functionality: 'Settings',
onPressed: () {
Navigator.pushNamed(context, Settings.id);
}),
SideButton(
functionality: 'Calendar',
onPressed: () {
Navigator.pushNamed(context, Settings.id);
}),
],
),
),
],
),
);
}
}
And here's the code for Cardslist():
class CardsList extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Consumer<CardData>(builder: (context, cardData, child) {
return ListView.builder(
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemBuilder: (context, index) {
final card = cardData.cards[index];
return FinalCardCreation(
finalname: card.cname,
finalbirthday: card.cbirthday,
);
});
});
}
}
The code for the created card FinalCardCreation():
class CardFinish extends StatefulWidget {
#override
CardFinishState createState() => CardFinishState();
}
class CardFinishState extends State<CardFinish> {
#override
Widget build(BuildContext context) {
return SizedBox(
height:
MediaQuery.of(context).size.height * 0.5, //<-- set height of the card
child: FinalCardCreation(),
);
}
}
class FinalCardCreation extends StatelessWidget {
String finalname;
String finalbirthday;
FinalCardCreation({
Key key,
#required this.finalname,
#required this.finalbirthday,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Card(
color: Color(0xFFef9a9a),
margin: EdgeInsets.all(2),
elevation: 8,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(22)),
child: Column(
children: <Widget>[
SizedBox(height: 8),
Expanded(
child: FinalCardContent(
name: finalname,
birthday: finalbirthday,
),
)
],
),
);
}
}
class FinalCardContent extends StatelessWidget {
String name;
String birthday;
FinalCardContent({Key key, #required this.name, #required this.birthday})
: super(key: key);
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'$name',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 50.0,
color: Colors.black,
),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'$birthday',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 50.0,
color: Colors.black,
),
),
),
],
),
);
}
}
I tried to wrap my Cardslist() multiple ways but I always got this exception. Thank you for your time and answer.
Column is a widget that can grow infinitely in height. It does not impose any height constraints to its children. Expanded are a smart way to include ListViews in Column since they fit all the possible space of the Column on screen, but impose a constraint to their children.
You can either remove the Column wrapping your CardList or, if you really need that Column for other stuff later, try wrapping CardList in another Expanded.