How to solve problem with null values in column? - flutter

This is the problem:
Column's children must not contain any null values, but a null value was found at index 0
I think it has something to do with the map, but i am not sure.
I am quite new to coding with dart so any help would be appreciated.
And here is the code:
import 'package:flutter/material.dart';
void main() => runApp(MaterialApp(
home: Main(),
));
int counter = 0;
class Main extends StatefulWidget {
#override
_MainState createState() => _MainState();
}
class _MainState extends State<Main> {
static List<String> names = [
'name1',
'name2',
];
static List<String> difficulty = [
'easy',
'normal',
];
String currentDifficulty = difficulty[counter];
var count = names.length;
#override
Widget build(BuildContext context) {
return Container(
child: Column(
children: names.map((name) {
Container(
child: Column(
children: <Widget>[
Text(
name
),
Text(
'currentDifficulty'
),
],
),
);
counter += 1;
}).toList(),
),
);
}
}

If you want to know the index of each widget you are creating on a map function from a list I would suggest to use List.asMap().map((index, string)=> MapEntry(index, widget())).values.toList() since the map function alone does not allow to get the index
Try substituting your children code for:
names.asMap().map((index, name)=> MapEntry(index, Container(
child: Column(
children: <Widget>[
Text(
name
),
Text(
difficulty[index]
),
],
),
))).values.toList();

You are getting the errors because:
1) You are accessing the elements of your List wrongly. To access elements in a List, use the elementAt method
2) The children property of your Column is missing a return statement .
3) Instead of using a counter to iterate through the second list. You can map through the two lists using the IterableZip.
Check the code below: It solves the errors and it works fine
int counter = 0;
class MyHomePage extends StatelessWidget {
static List<String> names = [
'name1',
'name2',
];
static List<String> difficulty = [
'easy',
'normal',
];
// access elements in a list using the elementAt function
String currentDifficulty = difficulty.elementAt(counter);
#override
Widget build(BuildContext context) {
names.map((e) => print(e));
return Scaffold(
body: Center(
child: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
// map the two lists using IterableZip and passing the two lists
children: IterableZip([names, difficulty]).map(
(element) {
// missing return statement
return Container(
child: Column(
children: <Widget>[
// access elements of your first list here
Text(element[0]),
// access elements of your second list here
Text(element[1]),
],
),
);
},
).toList(),
),
),
),
);
}
}
OUTPUT
I hope this helps.

Related

Flutter/Dart: Create/assign dynamic List

A list "options" is generated from json file as below and no issue:
For simplicity, some parts were removed
Future getidea(String subject) async {
List ideaList = [];
for (var idea in ideaListTemp) {
List options = [];
options.add(idea["A"]);
options.add(idea["B"]);
options.add(idea["C"]);
ideaList.add(ideaItem(
idea["ideaText"],
idea["ideaMedia"],
idea[options],
));
}
return (ideaList);
}
class ideaItem {
final String ideaText;
final String ideaMedia;
List? options;
ideaItem(
this.ideaText,
this.ideaMedia,
this.options,
);
}
However, when I use "options" to create a Widget, this error occur.
error: The argument type 'List?' can't be assigned to the parameter type 'List'.
Widget build(BuildContext context) {
return Expanded(
child: SingleChildScrollView(
padding: const EdgeInsets.all(_horizontalMargin),
physics: const AlwaysScrollableScrollPhysics(),
child: Column(
children: [
_buildOptions(widget.fromJSON.options), // this will have the error message
],
),
),
);
}
Widget _buildOptions(List option) {
List<Widget> listElevatedButton = [];
for (var i = 0; i < option.length; i++) {
//print(allOptions[i]);
listElevatedButton.add(
Builder(
builder: (context) => Padding(
padding: const EdgeInsets.all(8.0),
child: ElevatedButton(
onPressed: () {
print('Use the update function');
},
child: Text(
option[i],
),
),
),
),
);
}
return Column(children: listElevatedButton);
}
What is the best practice to solve the issue?
The variable options is being used carelessly, You need to make sure that the options has value before using it, To do this you can put a null check like so:
_buildOptions(widget.fromJSON.options) -> _buildOptions(widget.fromJSON.options ?? [])
This will give an empty list to _buildOptions function as long as options is empty and It won't build any widgets in _buildOptions function.
I hope you understand the concept here.
Your properties 'options' has type (optional) ?List, which mean it can contain List or null value. And you try use 'options' like argument in '_buildOptions' function, which need type List, not (optional) ?List.
Rewrite code like this:
Column(
children: [
_buildOptions(widget.fromJSON.options ?? []),
],
),
If the "widget.fromJSON.options" value is null, the _buildOptions will have the empty List, otherwise, it will have the value of the "widget.fromJSON.options" value.
Good luck ;)

How to use a variable parameter in a Flutter callback?

I have a simplified flutter control, think of a row of 'radio' buttons or a menu bar. The parent passes in a list of 'captions' for each button and a callback. The control then hits the callback passing the index of the button tapped. The issue is, the 'buttons' are created dynamically and the quantity may vary by the parent. When I set the callback for the onTap function in GestureDetector, it will always hit the callback with the last value of the parameter (idx) in the loop. So if there are 4 buttons, the doCallback is always called with a 4, no matter which button is tapped. It appears like doCallback is being called with a reference to idx, rather than the value of idx. Is there a way to make each button send it's own index to the callback?
class CtrlRadioSelector extends StatelessWidget {
CtrlRadioSelector({Key? key, required this.captions, required this.onTapItem})
: super(key: key);
final List<String> captions;
final ValueSetter<int> onTapItem;
#override
Widget build(BuildContext context) {
List<Widget> selectorItems = [];
int idx = 0;
for (var caption in captions) {
selectorItems.add(Expanded(
flex: 10,
child: GestureDetector(
onTap: () => doCallback(idx),
child: Text(caption,
textAlign: TextAlign.center,
style: TextStyle(fontSize: 18)))));
idx++;
}
return Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: selectorItems);
}
void doCallback(int idx) {
onTapItem(idx);
}
}
One fix would be use a for loop that iterates with an index, which you need anyway:
for (var idx = 0; idx < captions.length; i += 1) {
selectorItems.add(Expanded(
flex: 10,
child: GestureDetector(
onTap: () => doCallback(idx),
child: Text(captions[idx],
textAlign: TextAlign.center,
style: TextStyle(fontSize: 18)))));
}
This is because Dart specifically makes closures capture a for-loop's index (and not the values of all in-scope variables). Per the Dart Language Tour:
Closures inside of Dart’s for loops capture the value of the index, avoiding a common pitfall found in JavaScript. For example, consider:
var callbacks = [];
for (var i = 0; i < 2; i++) {
callbacks.add(() => print(i));
}
callbacks.forEach((c) => c());
The output is 0 and then 1, as expected. In contrast, the example would print 2 and then 2 in JavaScript.
More generally, you also can just make sure that your closure refers to a variable that's local to the loop's body, which would avoid reassigning the referenced variable on each iteration. For example, the following also would work (although it would be unnecessarily verbose in your particular case):
int idx = 0;
for (var caption in captions) {
var currentIndex = idx;
selectorItems.add(Expanded(
flex: 10,
child: GestureDetector(
onTap: () => doCallback(currentIndex),
child: Text(caption,
textAlign: TextAlign.center,
style: TextStyle(fontSize: 18)))));
idx++;
}
This is the correct way to create a dynamic row with buttons, where the actual index of the children is preserved:
import 'package:flutter/material.dart';
class CtrlRadioSelector extends StatelessWidget {
const CtrlRadioSelector({Key? key, required this.captions, required this.onTapItem})
: super(key: key);
final List<String> captions;
final ValueSetter<int> onTapItem;
#override
Widget build(BuildContext context) {
return Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: List.generate( //equivalent to your code using for loop and a list
captions.length, //if length of captions is 4, it'll iterate 4 times
(idx) {
return Expanded(
flex: 10,
child: GestureDetector(
onTap: () => doCallback(
idx), //value of idx is the actual index of the button
child: Text(captions[idx],
textAlign: TextAlign.center,
style: const TextStyle(fontSize: 18))));
}));
}
void doCallback(int idx) {
onTapItem(idx);
}
}
The answer from jamesdlin is correct. I just wanted to add that the code could be made a bit more idiomatic by using collection for to define the widget tree declaratively rather than imperatively. (Also, this is a pretty good article explaining why collection for and similar features were added to the language)
#override
Widget build(BuildContext context) {
return Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
for (var idx = 0; idx < captions.length; idx += 1)
Expanded(
flex: 10,
child: GestureDetector(
onTap: () => doCallback(idx),
child: Text(
captions[idx],
textAlign: TextAlign.center,
style: TextStyle(fontSize: 18),
),
),
),
],
);
}

How to create a/ instantiate a constructor from one file to the main dart file in flutter?

I am working on creating a hashMap for my flutter program and would like some input on it. As I created my hashMap in another dart file that is not the main dart file and I have no idea on how to connect it even when I created constrictors for the hashMaps. This is very important as the hashMap will be used on several files within the program hence why it is not in the main dart. Therefore I would like your guys input on how I could connect the two files.
This is part of my code:
main dart file:
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
//Always use Stateless first then use stateful or stateless widgets afterward
#override
Widget build(BuildContext context) {
return MaterialApp(
//only used at the beginning of the program
title: 'The Cafe',
//just a title to the app it does not show for there is nothing telling it to show on the screen
debugShowCheckedModeBanner: false,
//takes out the ribbon at the top right corner of the screen and app
theme: ThemeData(
primarySwatch: Colors.green,
brightness: Brightness.dark,
fontFamily: 'georgia',
textTheme: TextTheme(headline1: TextStyle(fontSize: 100))
//controls the color of the very top part of the application
),
home: StartPage(),
//used to connect the Stateless widget to the Stateful widget below
);
}
}
class StartPage extends StatefulWidget {
#override
_StartPageState createState() => _StartPageState();
}
// do not forget the } prior to this comment if you do it will result in error and the program does not known why either
class _StartPageState extends State<StartPage> {
String value = "";
//stating the string is not seen until you have started to compute the drop-downs
//have the drop down's take you to the item page
//void main(){
//HashMap map = new HashMap<String, double>();
// LinkedHashMap linkedHashMap = new LinkedHashMap<int, String>();
// SplayTreeMap treeMap = new SplayTreeMap<int, String>();
//}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('The Campus Cafe'),
//where the main title is computed to be shown on the screen
centerTitle: true,
//centers the title
),
body: Center(
//This is Header that is after the main Title
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
//Header Container
Expanded(
child: Image.asset('assets/images/campus-cafe-logo-350sidebar.png',)
),
Container(
padding: const EdgeInsets.all(8.0),
alignment: Alignment.center,
child: Text("Our Menu",style: TextStyle(fontSize: 30),
),
),
Expanded(
//Expands is used to create a body if you want a header and body...can also be used for other things but at the moment this is all I know
child: Column(
//there can be different types of Columns
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Flexible(
//Padding is how far away one container or item is away from another as shown below
flex:3,
child: DropdownButton<String>(
//items are basically like an array or list
items: [
DropdownMenuItem<String>(
value: "1",
child: Center(
child: Text('Grilled Cheese'),
),
),
DropdownMenuItem<String>(
value: "2",
child: Center(
child: Text('Grilled Ham & Cheese'),
),
),
DropdownMenuItem<String>(
value: "3",
child: Center(
child: Text('BLT'),
),
),
DropdownMenuItem<String>(
value: "4",
child: Center(
child: Text('Western Chicken Sandwich'),
),
),
DropdownMenuItem<String>(
value: "5",
child: Center(
child: Text('Crispy Chicken Wrap'),
),
),
DropdownMenuItem<String>(
value: "6",
child: Center(
child: Text('Cheese Steak'),
),
),
],
onChanged: (_value) => {
print(_value.toString()),
setState(() {
value = _value;
}),
},
hint: Text('Sandwiches')
//This hint displays on your drop-box before you open it to see the items list
),
),
Flexible(
flex:3,
child: DropdownButton<String>(
items: [
DropdownMenuItem<String>(
value: "1",
child: Center(
child: Text('Quantum Burger'),
),
),
DropdownMenuItem<String>(
value: "2",
child: Center(
child: Text('Cheeseburger'),
),
),
DropdownMenuItem<String>(
value: "3",
child: Center(
child: Text('Double Cheeseburger 1/4'),
),
),
DropdownMenuItem<String>(
value: "4",
child: Center(
child: Text('Hamburger 1/4'),
),
),
DropdownMenuItem<String>(
value: "5",
child: Center(
child: Text('Cheeseburger'),
),
),
DropdownMenuItem<String>(
value: "6",
child: Center(
child: Text('Veggie Burger'),
),
),
],
onChanged: (_value) => {
print(_value.toString()),
setState(() {
value = _value;
}),
},
hint: Text('Burgers')),
),
This is my hashMap file:
List<String> sandwich = ["Veggie Melt", "Crispy Chicken Wrap", "Italian Meatball Sub",
"Chicken Parm Grinder", "Grill Cheese", "Grilled Ham & Cheese", "Bacon Bagel Melt"];
List<double> sandwichPrice = [4.50, 6.95, 6.99, 6.59, 3.59, 4.59, 5.29];
Map<String, double> map1 = Map.fromIterables(sandwich, sandwichPrice);
List<String> burgers = ["Veggie Burger", "The Quantum Burger", "Cafe Melt",
"The Bull Rider", "Double Cheese Burger", "Hamburger"];
List<double> burgerPrice = [4.99, 7.25, 6.59, 5.79, 5.89, 3.99, 3.79];
Map<String, double> map2 = Map.fromIterables(burgers, burgerPrice);
List<String> otherItems = ["Chicken Quesadilla", "Cheese Quesadilla",
"Chicken Strips", "Popcorn Chicken", "Jalapeno Poppers"];
List<double> otherItemsPrice = [6.79, 6.29, 4.99, 4.59, 3.49];
Map<String, double> map3 = Map.fromIterables(otherItems, otherItemsPrice);
List<String> sides = ["French Fries", "Onion Rings", "Jalapeno Cheese Curds",
"Tater Tots", "Pretzel Bites", "Nachos & Cheese"];
List<double> sidesPrice = [3.29, 4.79, 4.99, 3.19, 4.59, 3.50];
Map<String, double> map4 = Map.fromIterables(sides, sidesPrice);
List<String> pizza = ["7-inch Cheese", "7-inc with topping"];
List<double> pizzaPrice = [4.59, 4.99];
Map<String, double> map5 = Map.fromIterables(pizza, pizzaPrice);
class Menu {
String sandwich;
String burger;
String otherItems;
String sides;
String pizza;
double sandwichPrice;
double burgerPrice;
double otherItemsPrice;
double sidesPrice;
double pizzaPrice;
Menu.s(this.sandwich, this.sandwichPrice){}
Menu.b(this.burger, this.burgerPrice){}
Menu.o(this.otherItems, this.otherItemsPrice){}
Menu.q(this.sides, this.sidesPrice){}
Menu.p(this.pizza, this.pizzaPrice){}
}
First of all, you need to import your hashMap file. Then update your MyWidget as follows:
I have displayed here an example of how you can use the Dropdown with map1 (i.e, Sandwiches).
You have to just iterate over the keys of the hashmap 'map1' & create the list of DropdownMenuItem from it & pass this list to the items property.
For each dropdown, you will need to save the selected option, so instead of using String value = '';, I have changed it to String selectedSandwich = 'Sandwiches';. This part is crucial as the Dropdown widget can have its value only as one of the options available. So, if you do not have the Sandwiches option in your dropdown list, there will be an error. Hence, I have added the Sandwiches option in the initState of your MyAppWidget.
You have to do the same for the remaining of the hashmaps. Let me know if you need any more help.
class MyWidget extends StatefulWidget {
#override
_MyWidgetState createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
// Instead of value use selectedSandwich
String selectedSandwich = 'Sandwiches';
// List of sandwiches, you have to do the same for rest of the maps
// like: burgers, otherItems etc.
List<String> sandwiches = map1.keys.toList();
#override
void initState() {
super.initState();
// Adding sandwiches as an option is necessay as the dropdown's value
// must be equal to one of its options.
// I have done this only for sandwiches, but you need to do the same
// for rest.
sandwiches.insert(0, 'Sandwiches');
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
DropdownButton<String>(
items: sandwiches // using map1.keys.toList
.map(
(e) => DropdownMenuItem<String>(
value: e,
child: Center(
child: Text(e),
),
),
)
.toList(),
onChanged: (_value) => {
print(_value.toString()),
setState(() {
selectedSandwich = _value; // Set selected sandwich
}),
},
value: selectedSandwich, // Use value
),
],
),
);
}
}

Why do i get a RangeError, if i add something to my List?

im trying to create a new Hero Widget by klicking on my FloatingActionButton. Therefore i have created a HeroCover widget, which holds the single Hero widgets.
class HeroCover extends StatelessWidget {
final Widget callPage;
final heroTag;
final coverImageName;
final name;
HeroCover({this.callPage, this.heroTag, this.coverImageName, this.name});
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Hero(
tag: heroTag,
child: GestureDetector(
onTap: () => Navigator.push(
context, MaterialPageRoute(builder: (context) => callPage)),
child: Column(children: <Widget>[
Image(
image: new AssetImage(coverImageName),
height: 100,
width: 100,
),
Text(name),
])),
),
);
}
}
On my HeroPage i now Create those HeroCover widgets depending on the following Lists with mapping
static List<int> matrixID = [0, 1, 2];
static var heroTag = ['matrix1', 'matrix2', 'matrix3'];
static var name = ['Matrix Kitchen', 'DAAANCEFLOR', 'Bath'];
static var matrixIMG = [
'imgs/matrix1.png',
'imgs/matrix2.png',
'imgs/matrix3.png'
];
var matrixCall = [
...matrixID.map((id) {
return MatrixPageOne(
name: name[id],
matrixSize: 20,
heroTag: heroTag[id],
heroImage: matrixIMG[id],
);
}).toList(),
];
Here i map the matrixID in the BuildMethod to return HeroCover Widgets depending on matrixID's length:
body: Column(
children: [
Wrap(children: [
...matrixID.map((id) {
return HeroCover(
heroTag: heroTag[id],
callPage: matrixCall[id],
name: name[id],
coverImageName: matrixIMG[id],
);
}).toList()
] // wrap children
),
],
),
Now if i press my FloatingActionButton, i add one Element to each of the lists:
floatingActionButton: FloatingActionButton(
onPressed: () {
//startAddMatrix(context);
setState(() {
matrixID.add(matrixID.length);
name.add('new Matrix');
matrixIMG.add('imgs/matrix1.png');
heroTag.add(DateTime.now().toString());
});
},
child: Icon(Icons.add),
backgroundColor: color_3,
),
So the .map should find one more element in each list and the next HeroCover Widget should be displayed ( if i add it manually to each list there is no problem), but if i press my FloatingActionButton, this happens:
but if i tap on "Home" in my BottomNavigationBar now and back to "Devices" everything is as it should be:
i just dont understand why .add is causing an RangeError. If anyone knows whats wrong here, id be very Thankful for your help!
your matrixCall init with ...matrixID.map((id) { ,
so it have 3 values 0..2
In your floatingActionButton, did not extend matrixCall, matrixCall still only have 3 values 0..2
when use
Wrap(children: [
...matrixID.map((id) {
return HeroCover(
heroTag: heroTag[id],
callPage: matrixCall[id],
name: name[id],
coverImageName: matrixIMG[id],
);
}).toList()
matrixID have 4 values 0..3,
and matrixCall still have 3 values, matrixCall[3] do not have value.

Iterating through a list to render multiple widgets in Flutter?

I have a list of strings defined like this:
var list = ["one", "two", "three", "four"];
I want to render the values on the screen side by side using text widgets. I have attempted to use the following code to attempt this:
for (var name in list) {
return new Text(name);
}
However, when I run this code, the for loop only runs once and there is only one text widget that gets rendered that says one (the first item in the list). Additionally, when I add a log message inside my for loop, it gets triggered once as well. Why isn't my for loop looping based on the length of the list? It seems to run only once and then quit.
Basically when you hit 'return' on a function the function will stop and will not continue your iteration, so what you need to do is put it all on a list and then add it as a children of a widget
you can do something like this:
Widget getTextWidgets(List<String> strings)
{
List<Widget> list = new List<Widget>();
for(var i = 0; i < strings.length; i++){
list.add(new Text(strings[i]));
}
return new Row(children: list);
}
or even better, you can use .map() operator and do something like this:
Widget getTextWidgets(List<String> strings)
{
return new Row(children: strings.map((item) => new Text(item)).toList());
}
It is now possible to achieve that in Flutter 1.5 and Dart 2.3 by using a for element in your collection.
var list = ["one", "two", "three", "four"];
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
for(var item in list ) Text(item)
],
),
This will display four Text widgets containing the items in the list.
NB. No braces around the for loop and no return keyword.
The Dart language has aspects of functional programming, so what you want can be written concisely as:
List<String> list = ['one', 'two', 'three', 'four'];
List<Widget> widgets = list.map((name) => new Text(name)).toList();
Read this as "take each name in list and map it to a Text and form them back into a List".
For googler, I wrote a simple Stateless Widget containing 3 method mentioned in this SO. Hope this make it easier to understand.
import 'package:flutter/material.dart';
class ListAndFP extends StatelessWidget {
final List<String> items = ['apple', 'banana', 'orange', 'lemon'];
// for in (require dart 2.2.2 SDK or later)
Widget method1() {
return Column(
children: <Widget>[
Text('You can put other Widgets here'),
for (var item in items) Text(item),
],
);
}
// map() + toList() + Spread Property
Widget method2() {
return Column(
children: <Widget>[
Text('You can put other Widgets here'),
...items.map((item) => Text(item)).toList(),
],
);
}
// map() + toList()
Widget method3() {
return Column(
// Text('You CANNOT put other Widgets here'),
children: items.map((item) => Text(item)).toList(),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: method1(),
);
}
}
To loop through a for-loop with multiple widgets in children,
children: [
for(int i = 0; i < item.length; i++) ...[
Widget1,
Widget2,
...
],
],
The simplest way is to map your list inside a Row or a Column widget :
var list = ["one", "two", "three", "four"];
Widget build(BuildContext context) {
return Row(children: List.from(list.map((name) => Text(name))));
}
One line
Column( children: list.map((e) => Text(e)).toList() )
You can use ListView to render a list of items. But if you don't want to use ListView, you can create a method which returns a list of Widgets (Texts in your case) like below:
var list = ["one", "two", "three", "four"];
#override
Widget build(BuildContext context) {
return new MaterialApp(
home: new Scaffold(
appBar: new AppBar(
title: new Text('List Test'),
),
body: new Center(
child: new Column( // Or Row or whatever :)
children: createChildrenTexts(),
),
),
));
}
List<Text> createChildrenTexts() {
/// Method 1
// List<Text> childrenTexts = List<Text>();
// for (String name in list) {
// childrenTexts.add(new Text(name, style: new TextStyle(color: Colors.red),));
// }
// return childrenTexts;
/// Method 2
return list.map((text) => Text(text, style: TextStyle(color: Colors.blue),)).toList();
}
You can make use of ListView.Builder() if you are receiving response from a http request that as an array
List items = data;
Container(
child: ListView.builder(
shrinkWrap: true,
itemCount: items.length,
itemBuilder: (BuildContext context, int index){
return Container(
child: Text(
items[index]['property']
),
);
},
),
);
Where
data is content returned from a http request using post or get
item is the array
'property' is one of the property of each item in the array assuming your are receiving back a list of objects
An easier approach may be to use expand:
For example
var paragraphs = ['Para1','Para2','Para3'];
Somewhere in your widget tree you can do this:
...paragraphs.expand((value) => [
SizedBox(
height: 10.0,
),
Text(
value,
// Add some styling if necessary
),
SizedBox(
height: 20.0,
),
]),
Here expand returns an iterable of widgets which is then spread using the Spread Operator(...).
when you return some thing, the code exits out of the loop with what ever you are returning.so, in your code, in the first iteration, name is "one". so, as soon as it reaches return new Text(name), code exits the loop with return new Text("one"). so, try to print it or use asynchronous returns.
Below works for me using the collection package :
https://pub.dev/packages/collection
children: <Widget>[
...languages.mapIndex((idx, item) {
return InkWell(
child: CustomCheckbox(Skill(item, _languageSelections[idx])),
onTap: () {
setState(() {
_languageSelections[idx] = !_languageSelections[idx];
});
});
})
],