I am currently having a few difficulties with ReorderableListView.
I have a list of ToDoPrefabs, which I want to output, because my list does not consist of strings but something else, I get errors in the index, for the key and the text.
this is the error:
"type 'To Prefab' is not a subtype of type 'int'"
I suspect that this is the key. It is also logical since todoprefab is not an int. Does anyone have an idea how I can get another index of the type int in my ReorderableListView
This is my ReorderableListView
return ReorderableListView(
onReorder: _onReorder,
scrollDirection: Axis.vertical,
padding: const EdgeInsets.symmetric(vertical: 8.0),
children: [
for(final item in toDoManagerClass.todoBank)
todocardprefab(item)
]
);
the todocardprefab (not the list)
todocardprefab(var key){
return Dismissible(
key: ValueKey(key),
background: Container(color: Colors.red, alignment: Alignment.centerLeft, child: Icon(Icons.delete),),
secondaryBackground: Container(color: Colors.green, alignment: Alignment.centerRight, child: Icon(Icons.archive),),
child: Card(
child: ListTile(
//leading: Icon(Icons.check_box_outline_blank),
title: Text(toDoManagerClass.todoBank[key].toDoText),
onTap: (){},
),
),
);
}
and this is the simple list.
class ToDoManagerClass{
List<ToDoPrefab> todoBank = [
ToDoPrefab(text: 'Homework', f: false),
ToDoPrefab(text: 'Homework1', f: false),
ToDoPrefab(text: 'Homework12', f: false),
ToDoPrefab(text: 'Homework123', f: false),
ToDoPrefab(text: 'Homework1234', f: false),
ToDoPrefab(text: 'Homework12345', f: false),
];
}
This method should work:
Your reordable listview
return ReorderableListView(
onReorder: _onReorder,
scrollDirection: Axis.vertical,
padding: const EdgeInsets.symmetric(vertical: 8.0),
children: [
for(final item in toDoManagerClass.todoBank)
todocardprefab(item, index())
]
);
and here the function. It returns a number higher with each call.
int index(){
if(i < toDoManagerClass.todoBank.length){
print(i);
i++;
}
return i-1;
}
now you only have to use the index instead of the item in your todocard
Related
I'm trying to create a List of containers containing a Headline and multiple cards. It should look like this in the end:
The Scaffold should contain a List of containers containing Rows of Cards and Text.
I'm not sure if that's smart so if you have a recommendation how this could be done better...
This is my code so far (without text "Text 1" segments):
body: ListView(
children: getItems(snapshot),
),//getItems(snapshot),
);
}
getItems(AsyncSnapshot<List<html.Document>> snapshot) {
List<Container> containers = [];
for(int x = 0; x<snapshot.data!.length; x++) {
containers.add(toRow(snapshot.data![x]));
}
return containers;
}
/*
Build list of containers first in a Row -> cards....
*/
toRow(html.Document document){
return Row(
children: listofcards(document),
);
}
listofcards(html.Document document) {
List<Card> cards = [];
return FutureBuilder<List<tage>>(
future: SiteParser().getData(document),
builder: (BuildContext context, AsyncSnapshot<List<tage>> document) {
for(int q = 0; q<document.data!.length; q++) {
containers.add(_buildCard(document.data![q]));
}
return cards;
},
);
}
_buildCard(tage snap) {
return Card(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
color: MyThemes().choosecardcolor(snap),
elevation: 5,
//color: _chooseColor(snap.art.toString()),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Text(snap.stunde),
Text(snap.klasse),
Text(snap.raum)
],
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Text(snap.art),
Text(snap.lehrer),
Text(snap.mitteilung)
],
)
],
),
);
}
At the moment I can't do that, because "The return type 'List' isn't a 'Widget', as required by the closure's context. ".
It was easier thanks to #ravindra-s-patil's recommendation to use group list view.
Here is my code I've wrote.
Widget buildrevresh(AsyncSnapshot<List<html.Document>> snapshot) {
return RefreshIndicator(
onRefresh: _refresh,
child: buildData(snapshot),
);
}
Widget buildData(AsyncSnapshot<List<html.Document>> snapshot) {
List<List<tage>> days = [];
for(int x = 0; x<snapshot.data!.length; x++) {
days.add(SiteParser().getData(snapshot.data![x]));
}
return GroupListView(
itemBuilder: (context, index) {
return _buildCard(days[index.section][index.index]);
},
sectionsCount: days.length ,
groupHeaderBuilder: (BuildContext context, int section) {
return Text(
days[section].first.datum,
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.w600));
},
countOfItemInSection: (int section) {
return days[section].length;
},
);
}
i am trying to make a banner using this list which can be accessed with function "getBannerList" instead of having to manually write a list in this carousel
if i set items by manually putting a list at items: ['base64string','base64string','base64string'].map it will work fine but when i replace it with the function it causes this error
Error
The following NoSuchMethodError was thrown building MyApp(dirty, dependencies: [MediaQuery], state: _MyAppState#5a46f):
'map'
Dynamic call of null.
Receiver: Instance of '_Future<dynamic>'
Arguments: [Instance of '(dynamic) => Builder']
Code for carousel
Dependencies: carousel_slider: ^4.0.0
CarouselSlider(
options: CarouselOptions(
height: MediaQuery.of(context).size.height * 0.15,
autoPlay: true,
autoPlayInterval: Duration(seconds: 5),
initialPage: 0,
),
items: getBannerList().map((e) { // <---- if i replaced this with ['asdf','asdf,'asdf].map((e) it works fine
return Builder(
builder: (BuildContext context) {
return Container(
width: MediaQuery.of(context).size.width,
margin: EdgeInsets.symmetric(horizontal: 5.0),
decoration: BoxDecoration(
image: DecorationImage(image: MemoryImage(base64Decode(e.toString()))),
color: Colors.white,
),
);
},
);
}).toList(),
),
GetList Function
getBannerList() async{
dynamic data = await getDashBoardBannerData();
print(data);
return data;
}
returns (example of return cause base64 string is too long):
['base64imgstring','base64imgstring','base64imgstring']
getBannerList method returns Future<dynamic> not List :
1- change method signature to Future<List<String>> getBannerList() async{}
2- define a variable in your StatefullWidget called
late final Future<List> bannerList;
3- initialize you variable in init state
#override
void initState(){
bannerList = getBannerList();
}
4- now we should use FutureBuilder with our basserList
FutureBuilder<List<String>>(
future: bannerList, // your future data
builder: (BuildContext context, AsyncSnapshot<List<String>> snapshot) {
if (snapshot.hasData) {
return CarouselSlider(
options: CarouselOptions(
height: MediaQuery.of(context).size.height * 0.15,
autoPlay: true,
autoPlayInterval: Duration(seconds: 5),
initialPage: 0,
),
items: snapshot.data.map((e) {
return Builder(
builder: (BuildContext context) {
return Container(
width: MediaQuery.of(context).size.width,
margin: EdgeInsets.symmetric(horizontal: 5.0),
decoration: BoxDecoration(
image: DecorationImage(image: MemoryImage(base64Decode(e.toString()))),
color: Colors.white,
),
);
},
);
}).toList(),
);
} else if (snapshot.hasError) {
return Text('Loading Error'); // error state
} else {
return CircularProgressIndicator(); // loading state
},
you should use explicit types for fewer bugs.
I am trying to create a list of switch tiles in flutter which have separators between the tiles.
I've tried doing this by using ListTile.divideTiles:
ListView(
children: ListTile.divideTiles(
context: context,
tiles: [
SwitchListTile(
secondary: Icon(Icons.signal_cellular_4_bar),
title: Text(
"First Tile",
),
value: var1,
onChanged: (bool value) {
setState(
() {
var1= value;
},
);
},
),
SwitchListTile(
secondary: Icon(Icons.swap_vert),
title: Text(
"Second Tile",
),
value: var2,
onChanged: (bool value) {
setState(
() {
var2= value;
},
);
},
),
],
),
),
But when I tried running the code I got the following error:
"type '_SyncIterable<Widget>' is not a subtype of type 'List<Widget>'"
Who do I create a list of switch tiles with separator?
Please try this.
Add .toList() to the end of your ListTile.divideTiles
ListTile.divideTiles(
// all your code
// all your code
// all your code
).toList()
Why don't you try ListView.separated ?
int _selectedIndex = 0;
return ListView.separated(
//Here's your separator
separatorBuilder: (BuildContext context, int index) {
return SizedBox(
height: 10, //Whatever spacing you want.
);
},
physics: BouncingScrollPhysics(),
scrollDirection: Axis.vertical,
shrinkWrap: true,
itemCount: 2, //How many tiles you want
padding: EdgeInsets.all(10),
itemBuilder: (BuildContext context, int index) {
return ClipRRect( //round up the edges for nicer look
borderRadius: BorderRadius.all(Radius.circular(5)),
//And here's your tile
child: SwitchListTile(
tileColor: Colors.grey[900],
selectedTileColor: Colors.black,
selected: index == _selectedIndex,
value: ... ,
onChanged: (v) {
...
},
title: Text('Tile #' + index.toString()),
subtitle: Text('-'),
),
);
},
);
The idea behind my code is to populate a Column widget with dynamic data I get from a list of objects
I use a List>> that's essentially just a list of objects.
My List :
List<List<Map<String, String>>> listCardsAll = [
[
{
"cardCate": "AMEX",
"cardDesc": "American Platinum 6",
"cardImg":
"images/AMEX/American-Express®-Green-Card-Earn-Rewards-Points.png"
}
],
[
{
"cardCate": "AMEX",
"cardDesc": "American Platinum 5",
"cardImg":
"images/AMEX/American-Express®-Green-Card-Earn-Rewards-Points.png"
}
],
];
Then I call a function within a column that returns a Widget(I want to return a List but it gives an error)
Widget:
Column(
children: <Widget>[
Row(
children: <Widget>[generateCardsALL()],
)
],
)
I Use a for-loop then in the function a make a widget with that dynamic data but it only returns one widget rather than the Collection that i was hoping for.
my Function :
Widget generateCardsALL() {
var count = 0;
for (var item in listCardsAll) {
count++;
if (count <= 2) {
return ReusableCards(
cardName: item[0]["cardDesc"],
cardLink: item[0]["cardImg"],
cardRowNum: count,
);
} else {
count = 0;
return ReusableCards(
cardName: item[0]["cardDesc"],
cardLink: item[0]["cardImg"],
cardRowNum: 3,
);
}
}
}
(The cardRowNum is only to see when its 3 cards next to each other that it can generate a new row)
This is the ReusableCards
ReusableCards:
class ReusableCards extends StatelessWidget {
final String cardLink;
final int cardRowNum;
final String cardName;
ReusableCards(
{#required this.cardLink,
#required this.cardRowNum,
#required this.cardName});
#override
Widget build(BuildContext context) {
// addToListcards(cardLink);
print("Inserted");
return (cardRowNum == 1 || cardRowNum == 2
? GestureDetector(
onDoubleTap: () {},
child: Padding(
padding: EdgeInsets.fromLTRB(0, 15, 15, 20),
child: Container(
width: MediaQuery.of(context).size.width * 0.24,
child: SizedBox(
child: Column(
children: <Widget>[
Image.asset(cardLink, fit: BoxFit.fill),
Text(cardName)
],
),
),
),
),
)
: cardRowNum == 3
? Padding(
padding: EdgeInsets.fromLTRB(0, 15, 0, 20),
child: Container(
width: MediaQuery.of(context).size.width * 0.24,
child: SizedBox(
child: Column(
children: <Widget>[
Image.asset(cardLink, fit: BoxFit.fill),
Text("" + cardRowNum.toString())
],
),
),
),
)
: SizedBox());
}
}
if I want to make it a List rather then just a widget it breaks. Can someone please help me with this dilemma
Try using map for iterating through the list and getting a list of widgets,
Example:
Column(
children: listCardsAll.map((oneCard){
return Container(
child: Text(oneCard.cardDesc)
);
}).toList(),
)
I think the problem is that inside of the function generateCardsALL. You don't return an array of Widgets, you should change to this.
List<Widget> generateCardsALL() {
var count = 0;
List<Widget> widgets;
for (var item in listCardsAll) {
count++;
if (count <= 2) {
widgets.add(ReusableCards(
cardName: item[0]["cardDesc"],
cardLink: item[0]["cardImg"],
cardRowNum: count,
));
} else {
count = 0;
widgets.add(ReusableCards(
cardName: item[0]["cardDesc"],
cardLink: item[0]["cardImg"],
cardRowNum: 3,
));
}
}
return widgets;
}
My function types() should return a unique list of ExpansionTiles.
In dart combining .toSet().toList() is really efficient in removing duplicates in List and I am trying to do the same here but I'm still rendering duplicates.
In the picture I don't want NISSAN to appear twice, just once as one category.
types() {
return snapshot.data.documents.map((doc) {
if(doc['car']['registryNumber'] != null && doc['car']['category'] ==
'car') {
return ExpansionTile(
title: new Row(
children: <Widget>[
new Text(
doc['car']['type'].split(' ')[0],
style: new TextStyle(
fontSize: 15.0
),
)
],
),
children: <Widget>[
],
);
} else {
return new Text('');
}
}).toSet().toList();
}
Don't forget to add a unique key: to ExpansionTile to avoid any duplicate issues!