I have a Stateful widget class with a card, the card has a dropdown and a text field. There is a Floatingactionbutton, I want to create an additional card when ever the floatingactionbutton is pressed. I guess I am supposed to create a list of this widget, but I am not too sure how to go about it.
Here is the code with the cards.
class CustomerCurrentSuppliers extends StatefulWidget {
const CustomerCurrentSuppliers({Key key}) : super(key: key);
#override
_CustomerCurrentSuppliersState createState() => _CustomerCurrentSuppliersState();
}
class _CustomerCurrentSuppliersState extends State<CustomerCurrentSuppliers> {
#override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.blue,
child: Icon(Icons.add),
onPressed: () {
//This is where the code to create additional cards come in ------>
},
),
body: Padding(
padding: const EdgeInsets.only(top: 38.0, right: 10, left: 10),
child: Column(
children: [
Container(
height: 170,
child: Card(
child:
Column(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: DropdownButtonHideUnderline(
child: FormBuilderDropdown(
name: 'dropdown',
hint: Text("Year"),
isExpanded: true,
items: [
"2018",
"2019",
"2020",
"2021",
].map((option) {
return DropdownMenuItem(
child: Text("$option"),
value: option,
);
}).toList(),
),
),
),
SizedBox(height: 20,),
Padding(
padding: const EdgeInsets.all(8.0),
child: FormBuilderTextField(
name: 'Region',
decoration: InputDecoration(
labelText: "Amount",
border: OutlineInputBorder()),
validator: FormBuilderValidators.compose([
FormBuilderValidators.required(context),
]),
),
),
],
),
elevation: 8,
),
),
],
),
),
);
}
}
You didn't provide the full code but I understand the logic you want.
Here is the code.
import 'package:flutter/material.dart';
class CustomerCurrentSuppliers extends StatefulWidget {
const CustomerCurrentSuppliers({Key key}) : super(key: key);
#override
_CustomerCurrentSuppliersState createState() => _CustomerCurrentSuppliersState();
}
class _CustomerCurrentSuppliersState extends State<CustomerCurrentSuppliers> {
int counter=1;
#override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.blue,
child: Icon(Icons.add),
onPressed: () {
setState(() { //setState is used to update the UI
counter++;
});
},
),
body: Padding(
padding: const EdgeInsets.only(top: 38.0, right: 20, left: 20),
child: ListView.builder(
itemCount: counter, //updating counter will update the UI with new card
itemBuilder: (context,index){
return Card(
child: Center(
child: Text(
"This is card ${index+1}"
),
),
);
}),
),
);
}
}
You can create List and increment the List when fab pressed.
class CustomerCurrentSuppliers extends StatefulWidget {
#override
_CustomerCurrentSuppliersState createState() =>
_CustomerCurrentSuppliersState();
}
class _CustomerCurrentSuppliersState extends State<CustomerCurrentSuppliers> {
int cardCount = 1;
List<int> cardList = [1];
#override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.blue,
child: Icon(Icons.add),
onPressed: () {
cardCount += 1;
cardList.add(cardCount);
setState(() {});
},
),
body: Padding(
padding: const EdgeInsets.only(top: 38.0, right: 10, left: 10),
child: ListView.builder(
itemCount: cardList.length,
itemBuilder: (content, index) {
return Container(
height: 170,
child: Card(
child: Column(
children: [
Text('FormBuilderDropdown'),
SizedBox(
height: 20,
),
Text('Region')
],
),
elevation: 8,
),
);
})),
);
}
}
Note: You have to handle errors/add more logics when pressing the button otherwise list will increment every time user press the button.
Related
I am using AutoRoute with AutoTabsRouter for navigation in my web app. I have a custom Drawer used for navigation. I want my current tab icon and text to be the primary color when on the selected index.
For mobile and tablet view, the drawer pops with every selection and when I open it again the current tab has the primary color as it should. On desktop view this works if I open the app in desktop view and do not resize the screen at all. If I do resize the screen at all, even if I'm still in desktop view after resizing, the selected does not work as expected and the current tab does not have the primary color.
Here is my code for the Drawer :
class CustomDrawer extends StatefulWidget {
final double width;
const CustomDrawer({
required this.width,
Key? key,
}) : super(key: key);
#override
State<CustomDrawer> createState() => _CustomDrawerState();
}
class _CustomDrawerState extends State<CustomDrawer> {
ScrollController scrollController = ScrollController();
#override
void dispose() {
scrollController.dispose();
super.dispose();
}
#override
Widget build(context) {
final tabsRouter = context.tabsRouter;
return Drawer(
elevation: 0,
backgroundColor: lightThemeCardColor,
child: SingleChildScrollView(
controller: scrollController,
child: Column(
children: [
DrawerHeader(
child: Column(
children: const [
SizedBox(
height: defaultMargin,
),
Icon(
Icons.architecture,
color: lightPrimaryColor,
size: 50,
),
Text(
'Drawer Header',
style: TextStyle(
fontSize: mobileTitleTextSize,
fontWeight: FontWeight.bold,
),
),
],
),
),
ListTile(
leading: const Icon(Icons.home),
title: const Text('H O M E'),
selected: tabsRouter.activeIndex == 0,
selectedColor: lightPrimaryColor,
onTap: () {
// Push to screen
tabsRouter.setActiveIndex(0);
if (widget.width < 1100) {
Navigator.pop(context);
}
},
),
ListTile(
leading: const Icon(Icons.edit),
title: const Text('S E C O N D'),
selected: tabsRouter.activeIndex == 1,
selectedColor: lightPrimaryColor,
onTap: () {
// Push to screen
tabsRouter.setActiveIndex(1);
if (widget.width < 1100) {
Navigator.pop(context);
}
},
),
ListTile(
leading: const Icon(Icons.check),
title: const Text('T H I R D'),
selected: tabsRouter.activeIndex == 2,
selectedColor: lightPrimaryColor,
onTap: () {
// Push to screen
tabsRouter.setActiveIndex(2);
if (widget.width < 1100) {
Navigator.pop(context);
}
},
),
ListTile(
leading: const Icon(Icons.settings),
title: const Text('F O U R T H'),
selected: tabsRouter.activeIndex == 3,
selectedColor: lightPrimaryColor,
onTap: () {
//Push to screen
tabsRouter.setActiveIndex(3);
if (widget.width < 1100) {
Navigator.pop(context);
}
},
),
],
),
),
);
}
}
Here is my code for the desktop home page where CustomDrawer is the first item in body row:
class DesktopHomePage extends StatelessWidget {
const DesktopHomePage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
final width = MediaQuery.of(context).size.width;
return Scaffold(
backgroundColor: lightThemeScaffoldColor,
body: Row(
children: [
// Always open drawer
CustomDrawer(width: width),
// Body contents
Expanded(
child: Container(
margin: const EdgeInsets.all(largeMargin),
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const MobileTabletTextHeadline(
text: 'Some widget',
),
SizedBox(
height: 300,
child: AspectRatio(
aspectRatio: 4,
child: SizedBox(
width: double.infinity,
child: GridView.builder(
physics: const NeverScrollableScrollPhysics(),
itemCount: 4,
gridDelegate:
const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 4,
),
itemBuilder: ((context, index) {
return Padding(
padding: const EdgeInsets.all(defaultPadding),
child: Container(color: lightThemeCardColor),
);
}),
),
),
),
),
// Some other widget
const MobileTabletTextHeadline(
text: 'Other Widget',
),
SizedBox(
height: 300,
child: AspectRatio(
aspectRatio: 4,
child: SizedBox(
width: double.infinity,
child: GridView.builder(
physics: const NeverScrollableScrollPhysics(),
itemCount: 4,
gridDelegate:
const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 4,
),
itemBuilder: ((context, index) {
return Padding(
padding: const EdgeInsets.all(defaultPadding),
child: Container(color: lightThemeCardColor),
);
}),
),
),
),
),
],
),
),
),
),
],
),
);
}
}
(All desktop views have the same layout)
And here is my code where I set up AutoTabsRouter:
class NavPage extends StatelessWidget {
const NavPage({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
final width = MediaQuery.of(context).size.width;
return AutoTabsRouter(
routes: const [
HomeRouter(),
SecondRouter(),
ThirdRouter(),
FourthRouter(),
],
builder: (context, child, animation) {
return Scaffold(
appBar:
MediaQuery.of(context).size.width < 1100 ? mobileAppBar : null,
backgroundColor: lightThemeScaffoldColor,
body: child,
drawer: CustomDrawer(width: width),
);
},
);
}
}
I've tried using using setState after setting the current index but that does not help. What can I change the Drawer in a way that reflects the changes in desktop view after window resize?
I am using flutter. I want to show different widgets when I tap on different options. On selecting option A, the option A widget is shown. On selecting option B, the option B widget is shown below the options bar and vice versa (like a tab bar). The code is attached below. I am glad if someone helps. ..
import 'package:flutter/material.dart';
class Cards extends StatefulWidget {
const Cards({Key? key}) : super(key: key);
#override
State<Cards> createState() => _CardsState();
}
class _CardsState extends State<Cards> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Cards"),
),
body: Padding(
padding: const EdgeInsets.only(top: 20),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
optionCards("A", "assets/icons/recycle.png", context, "1"),
optionCards("B", "assets/icons/tools.png", context, "2"),
optionCards("C", "assets/icons/file.png", context, "3"),
],
),
),
);
}
Widget optionCards(
String text, String assetImage, BuildContext context, String cardId) {
return Container(
width: 100,
height: 100,
decoration: ShapeDecoration(
color: Colors.grey,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(5),
),
),
),
child: SingleChildScrollView(
child: Column(
children: [
const Padding(
padding: EdgeInsets.only(top: 13),
child: IconButton(
onPressed: null,
icon: Icon(Icons.file_copy),
),
),
Text(
text,
style: const TextStyle(
fontSize: 14,
fontFamily: 'CeraPro',
color: Color.fromRGBO(0, 0, 0, 1),
),
),
],
),
),
);
}
Widget optiona() {
return Container();
}
Widget optionb() {
return Container();
}
Widget optionc() {
return Container();
}
}
class Cards extends StatefulWidget {
const Cards({Key? key}) : super(key: key);
#override
State<Cards> createState() => _CardsState();
}
class _CardsState extends State<Cards> {
Widget? selectedOption;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Cards"),
),
body: Padding(
padding: const EdgeInsets.only(top: 20),
child: Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
InkWell(
onTap: (){
setState(() {
selectedOption = optiona();
});
},
child: optionCards("A", "assets/icons/recycle.png", context, "1")
),
InkWell(
onTap: (){
setState(() {
selectedOption = optionb();
});
},
child: optionCards("B", "assets/icons/tools.png", context, "2")
),
InkWell(
onTap: (){
setState(() {
selectedOption = optionc();
});
},
child: optionCards("C", "assets/icons/file.png", context, "3")
),
],
),
// options
if(selectedOption != null) selectedOption!
],
),
),
);
}
Widget optionCards(
String text, String assetImage, BuildContext context, String cardId) {
return Container(
width: 100,
height: 100,
decoration: const ShapeDecoration(
color: Colors.grey,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(5),
),
),
),
child: SingleChildScrollView(
child: Column(
children: [
const Padding(
padding: EdgeInsets.only(top: 13),
child: IconButton(
onPressed: null,
icon: Icon(Icons.file_copy),
),
),
Text(
text,
style: const TextStyle(
fontSize: 14,
fontFamily: 'CeraPro',
color: Color.fromRGBO(0, 0, 0, 1),
),
),
],
),
),
);
}
Widget optiona() {
return Container();
}
Widget optionb() {
return Container();
}
Widget optionc() {
return Container();
}
}
You can use the Visibility widget to wrap the widgets which you want to hide or show and keep track of which one to show through a variable. Then you can set the visible property accordingly.
import 'package:flutter/material.dart';
class Cards extends StatefulWidget {
const Cards({Key? key}) : super(key: key);
#override
State<Cards> createState() => _CardsState();
}
class _CardsState extends State<Cards> {
var showOption = "";
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Cards"),
),
body: Padding(
padding: const EdgeInsets.only(top: 20),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
optionCards("A", "assets/icons/recycle.png", context, "1"),
optionCards("B", "assets/icons/tools.png", context, "2"),
optionCards("C", "assets/icons/file.png", context, "3"),
],
),
),
);
}
Widget optionCards(
String text, String assetImage, BuildContext context, String cardId) {
return Container(
width: 100,
height: 100,
decoration: ShapeDecoration(
color: Colors.grey,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(5),
),
),
),
child: SingleChildScrollView(
child: Column(
children: [
const Padding(
padding: EdgeInsets.only(top: 13),
child: IconButton(
onPressed: null,
icon: Icon(Icons.file_copy),
),
),
Text(
text,
style: const TextStyle(
fontSize: 14,
fontFamily: 'CeraPro',
color: Color.fromRGBO(0, 0, 0, 1),
),
),
],
),
),
);
}
Widget optiona() {
return Visibility(visible: showOption == "A", child: Container());
}
Widget optionb() {
return Visibility(visible: showOption == "B", child: Container());
}
Widget optionc() {
return Visibility(visible: showOption == "C", child: Container());
}
Now you can change the showOption variable whenever you want to show another option.
Above one is requirement. Actually requirement is that first widget (Vertical List header with below list view should take full height) means if list view has 18 items. It should show 18 items. Then below that it should show horizontal scroll.
I tried in my way but due to column list view taking same height as other element due to which its not showing all item all the way. It takes half of height of screen and user need to scroll in that height itself.
Need your help to sort out it. As first listview should take full height and second widget should come below that.
Please see below code.
import 'dart:math';
import 'package:flutter/material.dart';
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
"Flutter test",
style: TextStyle(color: Colors.black),
),
elevation: 5,
backgroundColor: Colors.white,
),
body: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.start,
children: [
ListHeader("Vertical List Header"),
VerticalList(),
ListHeader("Horizontal List Header"),
HorizontalList(),
ListHeader("Vertical List Header"),
VerticalList(),
ScrollUp()
],
),
);
}
}
class ScrollUp extends StatelessWidget {
const ScrollUp({
Key key,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return InkWell(
child: Container(
alignment: Alignment.bottomCenter,
width: double.infinity,
height: 50,
child: Center(
child: Text(
"Click to scroll up",
style: TextStyle(
fontSize: 18,
),
),
),
),
);
}
}
class ListHeader extends StatelessWidget {
final String title;
const ListHeader(String title) : title = title;
#override
Widget build(BuildContext context) {
return Text(
title,
style: TextStyle(fontSize: 18),
);
}
}
class HorizontalList extends StatelessWidget {
const HorizontalList({
Key key,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Expanded(
child: ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemCount: 30,
itemBuilder: (BuildContext context, int index) => Container(
margin:
const EdgeInsets.symmetric(vertical: 20, horizontal: 10),
width: 30,
height: 20,
color: Colors.grey,
)),
);
}
}
class VerticalList extends StatelessWidget {
const VerticalList({
Key key,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Expanded(
child: ListView.builder(
shrinkWrap: true,
itemBuilder: (ctx, int) {
return Container(
margin: const EdgeInsets.symmetric(vertical: 10, horizontal: 20),
width: double.infinity,
height: 50,
color: Colors.primaries[Random().nextInt(Colors.primaries.length)],
);
},
itemCount: 8,
),
);
}
}
Change the Column widget with a ListView widget.
And add shrinkWrap: true to its child ListView's'.
Remove the Expanded widget on both ListView.Builder
The horizontal ListView.Builder must have a Fixed height ( Link )
Add physics: NeverScrollableScrollPhysics() to the vertical ListView.Builder
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
"Flutter test",
style: TextStyle(color: Colors.black),
),
elevation: 5,
backgroundColor: Colors.white,
),
body: ListView(
children: [
ListHeader("Vertical List Header"),
VerticalList(),
ListHeader("Horizontal List Header"),
HorizontalList(),
ListHeader("Vertical List Header"),
VerticalList(),
ScrollUp()
],
),
);
}
}
class ScrollUp extends StatelessWidget {
const ScrollUp({
Key key,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return InkWell(
child: Container(
alignment: Alignment.bottomCenter,
width: double.infinity,
height: 50,
child: Center(
child: Text(
"Click to scroll up",
style: TextStyle(
fontSize: 18,
),
),
),
),
);
}
}
class ListHeader extends StatelessWidget {
final String title;
const ListHeader(String title) : title = title;
#override
Widget build(BuildContext context) {
return Text(
title,
style: TextStyle(fontSize: 18),
);
}
}
class HorizontalList extends StatelessWidget {
const HorizontalList({
Key key,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return Container(
height: 400,
child: ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemCount: 30,
itemBuilder: (BuildContext context, int index) => Container(
margin:
const EdgeInsets.symmetric(vertical: 20, horizontal: 10),
width: 30,
height: 20,
color: Colors.grey,
)),
);
}
}
class VerticalList extends StatelessWidget {
const VerticalList({
Key key,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return ListView.builder(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemBuilder: (ctx, int) {
return Container(
margin: const EdgeInsets.symmetric(vertical: 10, horizontal: 20),
width: double.infinity,
height: 50,
color: Colors.primaries[Random().nextInt(Colors.primaries.length)],
);
},
itemCount: 8,
);
}
}
This is my solution for same kind of problem.
import 'package:flutter/material.dart';
class MealDetailsScreen extends StatelessWidget {
Widget buildSectionTitle(BuildContext context, String title) {
return Container(
margin: EdgeInsets.symmetric(vertical: 10),
child: Text(
title,
style: Theme.of(context).textTheme.bodyText1,
),
);
}
Widget buildContainer({Widget child}) {
return Container(
decoration: BoxDecoration(
color: Colors.white,
border: Border.all(color: Colors.grey),
borderRadius: BorderRadius.circular(10)),
margin: EdgeInsets.all(10),
padding: EdgeInsets.all(10),
height: 300,
width: 300,
child: child,
);
}
#override
Widget build(BuildContext context) {
final mealId = ModalRoute.of(context).settings.arguments;
final selectedMeal =
DUMMY_MEALS.firstWhere((element) => element.id == mealId);
return Scaffold(
appBar: AppBar(
title: Text('${selectedMeal.title}'),
),
body: SingleChildScrollView(
child: Column(
children: [
Container(
height: 300,
width: double.infinity,
child: Image.network(
selectedMeal.imageUrl,
fit: BoxFit.cover,
),
),
buildSectionTitle(context, 'Ingredients'),
buildContainer(
child: ListView.builder(
itemBuilder: (ctx, index) => Card(
color: Theme.of(context).accentColor,
child: Padding(
padding:
const EdgeInsets.symmetric(vertical: 5, horizontal: 10),
child: Text(selectedMeal.ingredients[index]),
),
),
itemCount: selectedMeal.ingredients.length,
),
),
buildSectionTitle(context, 'Steps'),
buildContainer(
child: ListView.builder(
itemBuilder: (ctx, index) => Column(
children: [
ListTile(
leading: CircleAvatar(
child: Text('# ${(index + 1)}'),
),
title: Text(selectedMeal.steps[index]),
),
Divider(),
],
),
itemCount: selectedMeal.steps.length,
),
),
],
),
),
);
}
}
I added padding for transparent outside. But fixed height. How to change it?
padding: EdgeInsets.fromLTRB(20, 50, 20, 50),
Is it possible to remove above this line and flexible(center)?
I am expected like this flexible height alert. click here
onPressed: () {
showGeneralDialog(
context: context,
barrierColor: Palette.black.withOpacity(.3),
barrierDismissible: true,
transitionDuration: Duration(milliseconds: 400),
pageBuilder: (_, __, ___) {
return ChangePropertyPage(
propertyModel: propertyModel);
},
);
},
change Property Page
class ChangePropertyPage extends StatelessWidget {
final List<PropertyModel> propertyModel;
const ChangePropertyPage({Key key, this.propertyModel}) : super(key: key);
#override
Widget build(BuildContext context) {
final double width = CustomMediaQuery.width(context);
return Padding(
padding: EdgeInsets.fromLTRB(20, 50, 20, 50),
child: Material(
borderRadius: BorderRadius.all(Radius.circular(10)),
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
PropertyListTileWidget(
mainTitle: 'USER\'S Name', subTitle: 'USER\'S Email'),
VerticalSpacing(height: 10),
CustomLine(
height: 1,
width: (width - 40) - 20,
color: Palette.black.withOpacity(.2),
),
Expanded(
child: ListView.builder(
itemCount: propertyModel.length,//now length is 1
shrinkWrap: true,
itemBuilder: (BuildContext context, int index) {
return InkWell(
onTap: ()async{
},
child: PropertyListTileWidget(
mainTitle: '${propertyModel[index].propertyName}',
subTitle: '${propertyModel[index].ownerUId}'),
);
}),
)
],
),
),
),
);
}
}
if you are expecting this:
then
full code:
import 'package:flutter/material.dart';
class CustomDialogBox extends StatefulWidget {
#override
_CustomDialogBoxState createState() => _CustomDialogBoxState();
}
class _CustomDialogBoxState extends State<CustomDialogBox> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Custom Dialog Box"),
centerTitle: true,
),
body:Center(
child:FlatButton(
color: Colors.blue,
onPressed: (){
showDialog(
context: (context),
child: ShowCustomDialogBox()
);
},
child: Text("Show Dialog")
)
) ,
);
}
}
class ShowCustomDialogBox extends StatefulWidget {
#override
State<StatefulWidget> createState() => ShowCustomDialogBoxState();
}
class ShowCustomDialogBoxState extends State<ShowCustomDialogBox>with SingleTickerProviderStateMixin {
AnimationController controller;
Animation<double> scaleAnimation;
#override
void initState() {
super.initState();
controller = AnimationController(vsync: this, duration: Duration(milliseconds: 450));
scaleAnimation =CurvedAnimation(parent: controller, curve: Curves.decelerate);
controller.addListener(() {
setState(() {});
});
controller.forward();
}
#override
Widget build(BuildContext context) {
return Center(
child: Material(
color: Colors.transparent,
child: ScaleTransition(
scale: scaleAnimation,
child: Container(
margin: EdgeInsets.all(20.0),
padding: EdgeInsets.all(8.0),
height: MediaQuery.of(context).size.height/2.5, //Change height of dialog box.
width: MediaQuery.of(context).size.width,
decoration: ShapeDecoration(
color: Colors.white,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8.0))),
child: Column(
children: <Widget>[
Expanded(
flex: 4,
child: ListView.builder(
itemCount: 10,
itemBuilder: (context, index){
return Column(
// mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text((index+1).toString(),style: TextStyle(color:Colors.blue,fontSize:40),),
Divider()
],
);
}
)
),
Padding(
padding: const EdgeInsets.only(
left: 20.0, right: 10.0, top: 0.0,),
child: ButtonTheme(
height: 35.0,
minWidth: MediaQuery.of(context).size.width/3.5,
child: RaisedButton(
color: Colors.blue,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5.0)),
splashColor: Colors.white.withAlpha(40),
child: Text(
'Next',
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 13.0),
),
onPressed: () {
setState(() {
Navigator.pop(context);
});
},
)
)
),
],
)
),
),
),
);
}
}
I'm trying to improve my understanding of Flutter, and am struggling with an issue. I am trying to create an app that presents a list of cards which pull data from a list. There is a button on the bottom that creates a new card when the user clicks it.
I am trying to get each card to display a unique 'Round number'. So for example each time the user clicks the button, a card will be added that displays sequential numbers next to the word 'Round'. Round 1 > Round 2 > Round 3 and so on.
Right now everything works except that every time the button is pressed all the cards are updated with the latest number. And so instead of getting a sequential list of cards, every card is updated to the latest round number.
What am I doing wrong? Thank you.
Here is my code:
import 'package:flutter/material.dart';
class Round {
int roundNumber;
int firstNumber;
int secondNumber;
Round({ this.roundNumber, this.firstNumber, this.secondNumber, });
}
int uid = 1;
List<Round> roundsList = [
Round(roundNumber: uid, firstNumber: 1, secondNumber: 2),
];
class createLevels extends StatefulWidget {
#override
_createLevelsState createState() => _createLevelsState();
}
class _createLevelsState extends State<createLevels> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text("Create Rounds",)
),
body: Padding(
padding: const EdgeInsets.fromLTRB(20, 20, 20.0, 20),
child: Container(
child: Column(
children: <Widget>[
Expanded(
child: ListView.builder(
itemCount: roundsList.length,
itemBuilder: (BuildContext context, int whatIsThisVariable) {
return roundCard(Round(roundNumber: uid, firstNumber: 2, secondNumber: 3,));
}
),
),
Text("$roundsList"),
RaisedButton(
onPressed: () {
uid++;
roundsList.add(Round(roundNumber: uid));
setState(() {});
},
child: Text("Add Round"),
),
],
),
),
),
);
}
}
class roundCard extends StatelessWidget {
final Round round;
roundCard(this.round);
// roundsList.add(Round(roundNumber: 1));
#override
Widget build(BuildContext context) {
return Container(
child: Card(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Spacer(
flex: 1,
),
Expanded(
child: Text('Round ${round.roundNumber}:'),
flex: 12,
),
Expanded(
child: TextFormField(
textAlign: TextAlign.center,
decoration: InputDecoration(
hintText: '${round.firstNumber}',
),
),
flex: 3,
),
Spacer(
flex: 1,
),
Expanded(
child: TextFormField(
textAlign: TextAlign.center,
decoration: InputDecoration(
hintText: '${round.secondNumber}',
),
),
flex: 3,
),
],
),
)
),
);
}
}
You can copy paste run full code below
You need to pass index not uid
You can adjust first and second number you want
code snippet
itemBuilder: (BuildContext context, int index) {
return roundCard(roundsList[index]);
}),
...
onPressed: () {
uid++;
firstNumber++;
secondNumber++;
roundsList.add(
Round(roundNumber: uid, firstNumber: firstNumber, secondNumber: secondNumber));
setState(() {});
}
working demo
full code
import 'package:flutter/material.dart';
class Round {
int roundNumber;
int firstNumber;
int secondNumber;
Round({
this.roundNumber,
this.firstNumber,
this.secondNumber,
});
}
int uid = 1;
int firstNumber = 2;
int secondNumber = 3;
List<Round> roundsList = [
Round(roundNumber: uid, firstNumber: 1, secondNumber: 2),
];
class createLevels extends StatefulWidget {
#override
_createLevelsState createState() => _createLevelsState();
}
class _createLevelsState extends State<createLevels> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text(
"Create Rounds",
)),
body: Padding(
padding: const EdgeInsets.fromLTRB(20, 20, 20.0, 20),
child: Container(
child: Column(
children: <Widget>[
Expanded(
child: ListView.builder(
itemCount: roundsList.length,
itemBuilder: (BuildContext context, int index) {
return roundCard(roundsList[index]);
}),
),
Text("$roundsList"),
RaisedButton(
onPressed: () {
uid++;
firstNumber++;
secondNumber++;
roundsList.add(
Round(roundNumber: uid, firstNumber: firstNumber, secondNumber: secondNumber));
setState(() {});
},
child: Text("Add Round"),
),
],
),
),
),
);
}
}
class roundCard extends StatelessWidget {
final Round round;
roundCard(this.round);
// roundsList.add(Round(roundNumber: 1));
#override
Widget build(BuildContext context) {
return Container(
child: Card(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Spacer(
flex: 1,
),
Expanded(
child: Text('Round ${round.roundNumber}:'),
flex: 12,
),
Expanded(
child: TextFormField(
textAlign: TextAlign.center,
decoration: InputDecoration(
hintText: '${round.firstNumber}',
),
),
flex: 3,
),
Spacer(
flex: 1,
),
Expanded(
child: TextFormField(
textAlign: TextAlign.center,
decoration: InputDecoration(
hintText: '${round.secondNumber}',
),
),
flex: 3,
),
],
),
)),
);
}
}
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: createLevels(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.display1,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}