I need to set many items into a grid view. But I need to write something above the grid view and that's why I need a column which contains the texts and the grid view. But If I set some text and below the grid view then it doesn't work. Here is my code:
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Hamim Shop',
home: Scaffold(
body: Container(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
Text('Hamim Shop'),
GridView.count(
crossAxisCount: 3,
children: List.generate(choices.length, (index) {
return Center(
child: ChoiceCard(choice: choices[index]),
);
}),
),
],
),
),
),
);
}
}
Edited from Here:
Choice Card:
class ChoiceCard extends StatelessWidget {
const ChoiceCard({Key key, this.choice}) : super(key: key);
final Choice choice;
#override
Widget build(BuildContext context) {
return Card(
color: Colors.white,
child: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(child: Icon(choice.icon, size: 150)),
Text(choice.title),
]),
));
}
}
...
class Choice {
const Choice({this.title, this.icon});
final String title;
final IconData icon;
}
const List<Choice> choices = const [
const Choice(title: 'Car', icon: Icons.directions_car),
.....
];
Use shrinkwrap:true & physics:NeverScrollableScrollPhysics()
physics:
Scroll physics that does not allow the user to scroll. Means only Column+SingleChildScrollView Scrolling work.
shrinkwrap:
If you do not set the shrinkWrap property, your GridView will be as big as its parent.
If you set it to true, the GridView will wrap its content and be as big as its children allow it to be.
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Hamim Shop',
home: Scaffold(
body: Container(
padding: const EdgeInsets.all(8.0),
child: SingleChildScrollView(
child: Column(
children: [
Text('Hamim Shop'),
GridView.count(
shrinkWrap: true,
physics: NeverScrollableScrollPhysics(),
crossAxisCount: 3,
children: List.generate(choices.length, (index) {
return Center(
child: ChoiceCard(choice: choices[index]),
);
}),
),
],
),
),
),
),
);
}
}
class ChoiceCard extends StatelessWidget {
const ChoiceCard({Key key, this.choice}) : super(key: key);
final Choice choice;
#override
Widget build(BuildContext context) {
return Card(
color: Colors.white,
child: Center(
child: Column(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Expanded(child: Icon(choice.icon, size: 150)),
Text(choice.title),
]),
));
}
}
class Choice {
const Choice({this.title, this.icon});
final String title;
final IconData icon;
}
const List<Choice> choices = const [
const Choice(title: 'Car', icon: Icons.directions_car),
....
];
Related
I have an app that shows its content in a SingleChildScrollView. There is Container with a transparent color that I'd like to change the color of to red when the SingleChildScrollView is scrolled to any other position than the start position and then change the color back to transparent when the SingleChildScrollView is scrolled back to its starting position. Code:
class App extends StatefulWidget {
const App({Key? key}) : super(key: key);
#override
State<App> createState() => _AppState();
}
class _AppState extends State<App> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: [
Column(
children: [
Flexible(
child: ScrollConfiguration(
behavior: RemoveScrollGlow(),
child: SingleChildScrollView(
child: Column(
children: [
Stack(...) //This is the top section of the page
],
),
),
),
),
],
),
Container(
color: Colors.transparent, //This is the Color I want to change based on the position of the SingleChildScrollView
height: 120,
child: Column(...)
),
],
),
backgroundColor: Colors.white,
);
}
}
EDIT: I managed to make it work by wrapping the SingleChildScrollView in a NotificationListener and updating the color based on the notification like this:
class _AppState extends State<App> {
Color bannercolor = Colors.transparent;
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: [
Column(
children: [
Flexible(
child: ScrollConfiguration(
behavior: RemoveScrollGlow(),
child: NotificationListener<ScrollUpdateNotification>(
onNotification: (scrollEnd) {
final metrics = scrollEnd.metrics;
if (metrics.pixels != 0) {
setState(() {
bannercolor = Colors.white;
});
} else {
setState(() {
bannercolor = Colors.transparent;
});
}
return true;
},
child: SingleChildScrollView(
child: Column(
children: [
Column(...),
],
),
),
),
),
),
],
),
Container(
color: bannercolor,
height: 120,
child: Column(...),
),
],
),
backgroundColor: Colors.white,
);
}
}
You can try listening to the scroll controller offset like this
class App extends StatefulWidget {
const App({Key? key}) : super(key: key);
#override
State<App> createState() => _AppState();
}
class _AppState extends State<App> {
final ScrollController _scrollController = ScrollController ();
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: [
Column(
children: [
Flexible(
child: ScrollConfiguration(
behavior: RemoveScrollGlow(),
child: SingleChildScrollView(
controller: _scrollController, //add controller here
child: Column(
children: [
Stack(...) //This is the top section of the page
],
),
),
),
),
],
),
AnimatedBuilder(
animation: _scrollController,
builder: (context, _content) {
return Container (
(_scrollController.offset>20)? Colors.blue: Colors.transparent,
height: 120,
child: Column(...)
);
}
),
],
),
backgroundColor: Colors.white,
);
}
}
I'm aware that MediaQuery solutions exist to problems, however, I want to limit the size of my Scaffold so that it can be used for web-based apps as well. Similar to what Instagram has, can anyone help me with it?
Have you tried wrapping your Scaffold in SafeArea with a minimum property of EdgeInsets.all(32.0)?
For me, this recreates your mockup on any screen
Example code:
//...
return SafeArea(
minimum: const EdgeInsets.all(32.0),
child: Scaffold(
//...
),
);
//...
I used sizedboxes to create layers for a single page look. The gridview does not shrink to the size of the window. Instead it activates scrolling. My solution works for chrome web.
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.purple,
buttonTheme: const ButtonThemeData(
textTheme:ButtonTextTheme.primary,
buttonColor:Colors.yellow,
)
),
home: Test_SinglePage(),
);
}
}
class DataRecord{
String name;
String number;
DataRecord(this.name,this.number);
}
class Test_SinglePage extends StatefulWidget {
Test_SinglePage({Key? key}) : super(key: key);
#override
State<Test_SinglePage> createState() => _Test_SinglePageState();
}
class _Test_SinglePageState extends State<Test_SinglePage> {
List<DataRecord> lstData=[
DataRecord("A","1"), DataRecord("B","2"), DataRecord("C","3"), DataRecord("D","4"),
DataRecord("E","5"), DataRecord("F","6"), DataRecord("G","7"), DataRecord("H","8"),
DataRecord("I","9"), DataRecord("J","10"), DataRecord("K","11"), DataRecord("L","12"),
DataRecord("M","13"), DataRecord("N","14"), DataRecord("O","15"), DataRecord("P","16"),
DataRecord("Q","17"), DataRecord("R","18"), DataRecord("S","19"), DataRecord("T","20"),
DataRecord("V","21"), DataRecord("X","22"), DataRecord("Y","23"), DataRecord("Z","24"),
];
Widget _dialogBuilder(BuildContext context, String name)
{
return SimpleDialog(
contentPadding:EdgeInsets.zero,
children:[
Container(width:80,height:80,child:
Column(children:[
Text(name),
SizedBox(height:20),
Expanded(child:Row(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.end,
children: [ElevatedButton(onPressed:(){ Navigator.of(context).pop();}, child:
Text("Close"))
],))
])
)]);
}
Widget _itemBuilder(BuildContext context,int index)
{
return
GestureDetector(
onTap:()=>showDialog(context:context,builder:(context)=>_dialogBuilder(context,lstData[index].name)),
child:Container(color:Colors.grey,child:GridTile(child: Center(child:
Column(children:[
Text(lstData[index].name,style:Theme.of(context).textTheme.headline2),
Text(lstData[index].number,style:Theme.of(context).textTheme.headline4)
])
))));
}
#override
Widget build(BuildContext context) {
return Scaffold(appBar: AppBar(title:Text("Single Page")),body:
Container(
margin: const EdgeInsets.only(top:20.0, left: 20.0, right: 20.0, bottom:10.0),
child:
Flex(
direction: Axis.vertical,
mainAxisAlignment: MainAxisAlignment.start,
children: [
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child:Row(
mainAxisAlignment: MainAxisAlignment.start,
children:[
FittedBox(
fit:BoxFit.fitHeight,
child:SizedBox(
width:200,
height:200,
child: Image.asset("assets/images/apple.jpg"),
)),
Column(
mainAxisAlignment:MainAxisAlignment.start,
children:[
Row(
children: [
SizedBox(height:100,width:200,child:Container(color:Colors.red,child:Text("reached"))),
SizedBox(height:100,width:200,child:Container(color:Colors.blue,child:Text("reached2"))),
SizedBox(height:100,width:200,child:Container(color:Colors.green,child:Text("reached3")))
],),
Row(children: [
SizedBox(width:600, child:ElevatedButton(
onPressed:(){
},child:Text("Press Me")))],)
])
])),
Expanded(child:SizedBox(
height:400,
width:MediaQuery.of(context).size.width,child:
GridView.builder(
gridDelegate: const SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 300,
childAspectRatio: 3 / 2,
crossAxisSpacing: 20,
mainAxisSpacing: 20),
itemCount: lstData.length,
itemBuilder: _itemBuilder
)))],)
,));
}
}
I want to create a generic Layout which accepts a child Widget as a parameter, that lays out the content as follows:
I have an AppBar at the Top, a Title (headline), and below that the Content (could be anything). At the bottom, I have a Column with a few buttons. If the content is too big for the screen, all those widgets, except the AppBar, are scrollable. If the content fits the screen, the title and content should be aligned at the top, and the buttons at the bottom.
To showcase what I mean, I created a drawing:
It is easy to create to scrollable content functionality. But I struggle with laying out the content so that the buttons are aligned at the bottom, if the content does NOT need to be scrollable.
It is important to say that I don't know the height of the content widget or the buttons. They are dynamic and can change their height. Also, the title is optional and can have two different sizes.
What I tried is the following:
import 'package:flutter/material.dart';
class BaseScreen extends StatelessWidget {
final String? title;
final bool bigHeader;
final Widget child;
final Widget bottomButtons;
const BaseScreen({
Key? key,
required this.child,
required this.bottomButtons,
this.bigHeader = true,
this.title,
}) : super(key: key);
#override
Widget build(BuildContext context) {
final AppBar appBar = AppBar(
title: Text("AppBar"),
);
double minChildHeight = MediaQuery.of(context).size.height -
MediaQuery.of(context).viewInsets.bottom -
MediaQuery.of(context).viewInsets.top -
MediaQuery.of(context).viewPadding.bottom -
MediaQuery.of(context).viewPadding.top -
appBar.preferredSize.height;
if (title != null) {
minChildHeight -= 20;
if (bigHeader) {
minChildHeight -= bigHeaderStyle.fontSize!;
} else {
minChildHeight -= smallHeaderStyle.fontSize!;
}
}
final Widget content = Column(
mainAxisSize: MainAxisSize.min,
children: [
if (title != null)
Text(
title!,
style: bigHeader ? bigHeaderStyle : smallHeaderStyle,
textAlign: TextAlign.center,
),
if (title != null)
const SizedBox(
height: 20,
),
ConstrainedBox(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
child,
bottomButtons,
],
),
constraints: BoxConstraints(
minHeight: minChildHeight,
),
),
],
);
return Scaffold(
appBar: appBar,
body: SingleChildScrollView(
child: content,
),
);
}
TextStyle get bigHeaderStyle {
return TextStyle(fontSize: 20);
}
TextStyle get smallHeaderStyle {
return TextStyle(fontSize: 16);
}
}
The scrolling effects work perfectly, but the Buttons are not aligned at the bottom. Instead, they are aligned directly below the content. Does anyone know how I can fix this?
DartPad you can check here
customscrollview tutorial
Scaffold(
// bottomNavigationBar: ,
appBar: AppBar(
title: Text(" App Bar title ${widgets.length}"),
),
//============
body: CustomScrollView(
slivers: [
SliverFillRemaining(
hasScrollBody: false,
child: Column(
// controller: _mycontroller,
children: [
title,
...contents,
// ---------------------This give Expansion and button get down --------
Expanded(
child: Container(),
),
// ---------------------This give Expansion and button get down --------
Buttons
],
),
)
],
))
We can Achieve with the help of CustomScrollView widget and Expanded widget.here Expanded widget just expand between the widget
Sample Code
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
void main() {
runApp(
MaterialApp(debugShowCheckedModeBanner: false, home: MyApp()),
);
}
class MyApp extends StatefulWidget {
#override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
var widgets = [];
var _mycontroller = ScrollController();
#override
Widget build(BuildContext context) {
var title = Center(
child: Text(
"Scrollable title ${widgets.length}",
style: TextStyle(fontSize: 30),
));
var contents = [
...widgets,
];
var Buttons = Row(
children: [
Expanded(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
height: 100,
child: ElevatedButton(
onPressed: () {
setState(() {
widgets.add(Container(
height: 100,
child: ListTile(
title: Text(widgets.length.toString()),
subtitle: Text("Contents BTN1"),
),
));
});
// _mycontroller.jumpTo(widgets.length * 100);
},
child: Text("BTN1"),
),
),
)),
Expanded(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
height: 100,
child: ElevatedButton(
onPressed: () {
setState(() {
if (widgets.length > 0) {
widgets.removeLast();
}
});
// _mycontroller.jumpTo(widgets.length * 100);
},
child: Text("BTN2"),
),
),
))
],
);
return MaterialApp(
debugShowCheckedModeBanner: false,
home: SafeArea(
child: Scaffold(
// bottomNavigationBar: ,
appBar: AppBar(
title: Text(" App Bar title ${widgets.length}"),
),
body: CustomScrollView(
slivers: [
SliverFillRemaining(
hasScrollBody: false,
child: Column(
// controller: _mycontroller,
children: [
title,
...contents,
Expanded(
child: Container(),
),
Buttons
],
),
)
],
)),
),
);
}
}
Try this:
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp();
#override
Widget build(BuildContext context) {
return MaterialApp(
home: BaseScreen(
bottomButtons: [
ElevatedButton(onPressed: () {}, child: const Text('Button 1')),
ElevatedButton(onPressed: () {}, child: const Text('Button 2')),
],
content: Container(
color: Colors.lightGreen,
height: 200,
),
title: 'Title',
),
);
}
}
class BaseScreen extends StatelessWidget {
final bool bigHeader;
final List<Widget> bottomButtons;
final String? title;
final Widget content;
const BaseScreen({
this.bigHeader = true,
required this.bottomButtons,
required this.content,
this.title,
});
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('AppBar'),
),
body: CustomScrollView(
slivers: [
SliverFillRemaining(
hasScrollBody: false,
child: Column(
children: [
if (title != null)
Padding(
padding: const EdgeInsets.symmetric(vertical: 12),
child: Text(
title!,
style: bigHeader ? _bigHeaderStyle : _smallHeaderStyle,
textAlign: TextAlign.center,
),
),
content,
const Spacer(),
...bottomButtons,
],
),
),
],
),
);
}
TextStyle get _bigHeaderStyle => const TextStyle(fontSize: 20);
TextStyle get _smallHeaderStyle => const TextStyle(fontSize: 16);
}
Screenshots:
without_scrolling
scrolled_up
scrolled_down
In a grid view, since I have similar card items, I decided to create a custom widget containing each card item. The custom widget is a stateless widget. The problem I have is in passing an onTap property to the class. In fact, I do pass and no errors are there, but the onTap property does not propagate properly and it does not display the SnackBar I want. Here's the code:
import 'package:flutter/material.dart';
const _padding = EdgeInsets.all(8.0);
const _splashColor = Colors.amber;
class HomeScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Main Page'),),
drawer: Drawer(
elevation: 8.0,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: [
DrawerHeader(
child: Column(
children: [
Image(image: AssetImage('assets/images/top_picture.png'), fit: BoxFit.scaleDown, width: 100, height: 100),
Text('Home', style: Theme.of(context).textTheme.headline6)
],
)),
ListTile(leading: Icon(Icons.settings), title: Text('Settings')),
ListTile(leading: Icon(Icons.exit_to_app), title: Text('Quit')),
AboutListTile(icon: Icon(Icons.info), aboutBoxChildren: [Text('Copyright (C) 2020'), Text('Design And Programming: me')],)
],
)),
body: HomeScreenBody(),
);
}
}
class HomeScreenBody extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Padding (
padding: const EdgeInsets.all(8.0),
child: GridView (
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
children: [
ItemCard(title: 'Balance', icon: 'assets/images/coins-balance.png', onTap: _comingSoon),
ItemCard(title: 'Add Funds', icon: 'assets/images/add-money.png', onTap: _comingSoon,),
ItemCard(title: 'Restaurant', icon: 'assets/images/restaurant.png', onTap: _comingSoon),
],
),
);
}
void _comingSoon(BuildContext context) {
print('Showing snackbar...');
final snack = SnackBar(content: Text('Coming soon...'));
Scaffold.of(context).showSnackBar(snack);
}
}
class ItemCard extends StatelessWidget{
final String icon;
final String title;
final ValueChanged<BuildContext> onTap;
const ItemCard({this.title, this.icon, this.onTap});
#override
Widget build(BuildContext context){
return Builder(builder:(context) {
return Card(
child: InkWell(
splashColor: _splashColor,
onTap: ()=> this.onTap,
child: Column (
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image(image: Image.asset(this.icon).image, ),
Padding(
padding: _padding,
child: Text(this.title),
)
],
),
),
);
},
);
}
}
I tried changing the type of onTap field to ValueChanged, ValueChanged, ValueChanged<BuildContext), but none of them worked. Any idea why my callback is not called?
Try this
class ItemCard extends StatelessWidget{
final String icon;
final String title;
final void Function(BuildContext) onTap; //your function expects a context
const ItemCard({this.title, this.icon, this.onTap});
#override
Widget build(BuildContext context){
return Builder(builder:(ctx) { //changed to ctx so that contexts don't clash
return Card(
child: InkWell(
splashColor: _splashColor,
onTap: ()=> this.onTap(context), //pass context here
child: Column (
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image(image: Image.asset(this.icon).image, ),
Padding(
padding: _padding,
child: Text(this.title),
)
],
),
),
);
},
);
}
}
Let me know if this doesn't work.. there is other simple way too.
Use a VoidCallback for your onTap variable.
Wrap the HomeScreen widget tree with a Builder widget so a context to be used in the SnackBar can be available.
I added a demo using your code as an example:
This works:
class ItemCard extends StatelessWidget{
final String icon;
final String title;
final VoidCallback onTap; // use a VoidCallback instead
const ItemCard({this.title, this.icon, this.onTap});
#override
Widget build(BuildContext context){
return Builder(builder:(context) {
return Card(
child: InkWell(
splashColor: _splashColor,
onTap: onTap, // assign the onTap property
child: Column (
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image(image: Image.asset(this.icon).image, ),
Padding(
padding: _padding,
child: Text(this.title),
)
],
),
),
);
},
);
}
class HomeScreenBody extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Builder(
builder: (context){,
child: Padding (
padding: const EdgeInsets.all(8.0),
child: GridView (
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(crossAxisCount: 2),
children: [
ItemCard(title: 'Balance', icon: 'assets/images/coins-balance.png', onTap: () => _comingSoon(context)),
ItemCard(title: 'Add Funds', icon: 'assets/images/add-money.png', onTap: () => _comingSoon(context),),
ItemCard(title: 'Restaurant', icon: 'assets/images/restaurant.png', onTap: () => _comingSoon(context)),
],
),
);
},
);
}
void _comingSoon(context) {
print('Showing snackbar...');
final snack = SnackBar(content: Text('Coming soon...'));
Scaffold.of(context).showSnackBar(snack);
}
}
Change widget's onTap parameter to be a final Function(BuildContext) and then in onTap: change ()=> this.onTap to onTap(). That should do it.
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.