how do I get out of this itemBuilder and forEach problem? - mobile

child:new ListView.builder(
itemCount: 4,
scrollDirection: Axis.vertical,
itemBuilder: (BuildContext context, int index) {
NewsData.news.forEach((n)=> _getPostWidgets(n));
}),
I just have a empty page and that's the only error
"This function has a return type of 'Widget', but doesn't end with a return statement."
If I only do
child:new ListView.builder(
itemCount: 4,
scrollDirection: Axis.vertical,
itemBuilder: (BuildContext context, int index) {
return _getPostWidgets(n1));
}),
n1 working 4 times its cool but it won't let me put a return in the first code.I tried throwing itembuilder by creating a different function but it didn't work or i did wrong
can someone help?

The itemBuilder will be called for each line of your listView. Just it appears on screen...
You should call _getPostWidgets(NewsData.news[index]);
For best code, you should use the size of your list as the size of listView:
child:new ListView.builder(
itemCount: NewsData.news.length,
scrollDirection: Axis.vertical,
itemBuilder: (BuildContext context, int index) {
return _getPostWidgets(NewsData.news[index]));
}),

Related

Sorting and removing duplicates of multi dimensional array flutter

Hello I am working on a project here I have a multidimensional array with name and votes this is the array
[[[Avoos, 0]], [[Abhiram MS, 1]], [[Amritha tg, 0]], [[usha, 2]]]
I get this from the server,the problem is every time I refresh the page it stores these values again in the array(repeating the same values) so its getting something like this
[[[Avoos, 0]], [[Abhiram MS, 1]], [[Amritha tg, 0]], [[usha, 2]], [[Amritha tg, 0]], [[Abhiram MS, 1]], [[Avoos, 0]], [[usha, 2]], [[Amritha tg, 0]], [[Abhiram MS, 1]], [[Avoos, 0]], [[usha, 2]]]
I want to remove these repeated values and sort this array according to the votes
here is my complete code used on the page
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:web3dart/web3dart.dart';
import '../../services/Auth.dart';
import '../../services/IntoLogin.dart';
import '../../services/functions.dart';
class CloseElec extends StatefulWidget {
final Web3Client ethClient;
final String electionName;
final String electionAdress;
const CloseElec({Key? key, required this.ethClient, required this.electionName, required this.electionAdress}) : super(key: key);
#override
State<CloseElec> createState() => _CloseElecState();
}
class _CloseElecState extends State<CloseElec> {
void refresh() {
setState(() {
//candidatearray.clear();
candidatearray =candidatearrayreal.toSet().toList();
});
}
Future<void> signOut() async {
if (!mounted) return;
await Auth().signOut();
if (!mounted) return;
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(builder: (context) => IntroLogin()),
(route) => false);
}
late String winner = 'No candidate';
late int winnervotes = 0;
late int row = 5;
late int col = 5;
var candidatearray = [] ;
var candidatearrayreal = [] ;
#override
void initState() {
candidatearray.clear();
super.initState();
}
#override
Widget build(BuildContext context) {
return Container(
decoration: const BoxDecoration(gradient:
LinearGradient(colors: [
Color(0xFF516395),
Color(0xFF614385 ),
])),
child: Scaffold(
appBar:AppBar(
backgroundColor: Colors.transparent,
leading: IconButton(onPressed: () {
signOut();
}, icon: const Icon(Icons.logout_sharp),),
title: const Text('Election progress'),
actions: [
IconButton(onPressed: () {
refresh();
}, icon: const Icon(Icons.refresh))
],
),
body: SingleChildScrollView( //Here we are getting the whole candidate details
child: Column(
children: [
Container(margin: const EdgeInsets.only(bottom: 56),
child: SingleChildScrollView( // this stream builder will give the number of items/candidates
child: StreamBuilder<List>(stream: getCandidatesNum(widget.ethClient, widget.electionAdress).asStream(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(child: CircularProgressIndicator(),);//circular bar for waiting
} else {
return Column(
children: [ // here we will get all candidates using a loop
for (int i = 0; i < snapshot.data![0].toInt(); i++)
FutureBuilder<List>( // call to get candidate info
future: candidateInfo(i, widget.ethClient, widget.electionAdress),
builder: (context, candidatesnapshot) {
if (candidatesnapshot.connectionState == ConnectionState.waiting) {
return const Center(child: CircularProgressIndicator(),);
} else {
// logic to decide the winner
if(candidatesnapshot.data![0][1].toInt() > winnervotes){
winnervotes = candidatesnapshot.data![0][1].toInt();
winner = candidatesnapshot.data![0][0];
}else if(candidatesnapshot.data![0][1].toInt() == winnervotes){
winner = candidatesnapshot.data![0][0];
}
candidatearrayreal.add(candidatesnapshot.data);
// print(candidatesnapshot.data);
return Container(
padding: const EdgeInsets.all(12),
margin: const EdgeInsets.all(12),
decoration: const BoxDecoration(
boxShadow: [
BoxShadow(color: Color(0xFF7F5A83),
offset: Offset(-11.9, -11.9),
blurRadius: 39,
spreadRadius: 0.0,
),
BoxShadow(color: Color(0xFF7F5A83),
offset: Offset(11.9, 11.9),
blurRadius: 39,
spreadRadius: 0.0,
),
],
borderRadius: BorderRadius.all(Radius.circular(10)),
gradient: LinearGradient(colors: [
Color(0xFF74F2CE),
Color(0xFF7CFFCB),
])),
child: ListTile(
title: Text('Name: ${candidatesnapshot.data![0][0]}',
style: const TextStyle(color: Colors.purple)),
subtitle: Text('Votes: ${candidatesnapshot.data![0][1]}',
style: const TextStyle(color: Colors.purple)),
),
);
}
})
],
);
}
},
),
),
),
const SizedBox(height: 12,),
Text('The winner of the election is : $winner with votes $winnervotes',style: const TextStyle(color: Colors.white)),
const SizedBox(height: 16,),
SizedBox(
height: MediaQuery.of(context).size.height,
width: double.infinity,
child: ListView.builder(
itemCount:candidatearray.length,
itemBuilder: (context,index){
for (var i = 0; i < candidatearray.length; i++) {
candidatearray.sort((a, b) {
print(candidatearrayreal);
//print(b[0][1]);
return int.parse(a[0][1].toString()).compareTo(int.parse(b[0][1].toString()));
});
}
return ListTile(
title: Text('${candidatearray[index][0][0]}'),
subtitle:Text('votes : ${candidatearray[index][0][1]}'),
);
}),
),
],
),
),
),
);
}
}
This seems a lot like a task a model class would make 100 times easier. Instead of using a multi-dimensional array where you might make various different mistakes, you can combine the data into a single object and get IDE support too.
In your case, that class could look like this:
class MyObject {
final String name;
final int votes;
MyObject({required this.name, required this.votes});
}
When you receive the data in your FutureBuilder you will need to transform the list of lists into a list of these objects. This is already much better, but there's more!
You can implement the == and hashCode overrides which allows you to compare two of the same objects and determine whether they are equal or not. Write this in your model class too:
#override
bool operator ==(covariant MyObject other) {
if (identical(this, other)) return true;
return
other.name == name &&
other.votes == votes &;
}
#override
int get hashCode {
return name.hashCode ^
votes.hashCode;
}
Now you can compare them anywhere by simply writing ==:
MyObject a = MyObject(name: "test", votes: 10);
MyObject b = MyObject(name: "test", votes: 10);
MyObject c = MyObject(name: "xyz", votes: 0);
print(a == b); // true
print(a == c); // false
What this also allows you to do is instead of storing the returned list candidatesnapshot.data, you can create a Set, which only allows any given value to be stored inside it a single time! This automatically eliminates you from adding duplicates, if that isn't what you want.
To do this, you're going to have to fix up the code after your FutureBuilder. I'm not going to lie, I don't really understand what's going on there since you seem to be creating a new FutureBuilder for every object returned by the Stream. Either way, I think it would be best to simply loop over the values from the stream and add the data to the Set.
Now, you can also easily sort this set of your MyObjects. Simply get the values as a list and then use the lists .sort method.
Set<MyObjects> m = {...}; // your data goes here
final sortedList = m.toList()..sort((a, b) => a.votes.compareTo(b.votes));
Since the types are only int and string, you can use their compareTo methods and automatically sort them. To reverse the order, simply reverse a and b on the sort function!
If you for some reason can't use a model class - and I really don't see why you couldn't - it is still possible to filter out duplicates by either:
overwriting the list every time you get new data (using x = .. instead of x.add()
checking for duplicates by looping over the list for every new value / using the .contains() method on the list
As for sorting, you can use the .sort() method, you'll just have to use a [index] syntax instead of object fields on the right side, which really isn't great either.
To remove the repeated values and sort the array according to the votes, you can use the toSet() function and then convert it back to a list using toList(). This will remove any duplicate values. Then you can use the sort() function to sort the array according to the votes.
candidatearray = candidatearrayreal.toSet().toList();
candidatearray.sort((a, b) => a[1].compareTo(b[1]));
This will first convert the candidatearrayreal to a set, which will remove any duplicate values, and then convert it back to a list. Next, it will sort the list according to the second element of each sublist (which is the number of votes) using the sort() function and a comparator function that compares the votes of the two candidates.
You can put this piece of code in the refresh() function, so it will be executed every time the user refreshes the page.
Also, you can move the candidatearray.clear(); code to the initState() function, this will clear the array every time the user enters the CloseElec page.

How to compare 2 arrays of different lengths and look for matching values - Flutter

I'm not sure if my strategy or logic is correct to achieve this, but I have 2 lists coming from 2 different jsondata mysql queries, let's say they look like this:
List newsAgency = [{id: 1, name: 9news, image: x}
{id: 2, name: abcnews, image: y}
{id: 3, name: bbcnews, image:z}];
List following = [{userid: 41, username: x, newsid: 2}
{userid: 41, username: x newsid: 3}];
I want to see if the id in newsAgency matches the newsid in the following list, and to return true or false correspondingly.
The idea is to say that I am following 2 news agencies out of 3, so my goal is to display the button to follow or unfollow based on the results.
I tried everything suggested from this post how can I find a list contains in any element another list in flutter? but couldn't get it.
This is my code example:
Listview.builder(
itemCount: newsAgency.length,
itemBuilder: (BuildContext context, int index) {
bool following = false;
return Card(
elevation: 10.0,
child: Row(
children: [
Text(newsAgency[index]['name'],
following
? TextButton(onPressed: () {//unfollow function},
child: const Text('unfollow')),
: TextButton(onPressed: () {//follow function},
child: const Text('follow')),
]));});
Any help is highly appreciated
add this method in your class, it will be responsible for searching which items are following and which are not, and return a bool based on it:
bool checkIsFollowing(Map<String, dynamic> current) {
for(int index = 0; index < following.length; index+=1) {
if(current["id"] == following[index]["newsid"]) {
return true;
}
}
return false;
}
now inside of your ListView's itemBuilder, replace this:
bool following = false;
with this:
final currentNewsAgency = newsAgency[index];
bool following = checkIsFollowing(currentNewsAgency);
following will be true or false based on if the current Agency's id exists in some item in the following list.
use contains() method to check if the list contains the value you want to match or not, for example:-
following.contains(newsAgency[index]['name'].toString())// true if value matches.

The argument type 'Map<String, Object>' can't be assigned to the parameter type 'String'

import 'package:learnflutter/questionMain.dart';
import 'questionButton.dart';
class mainQuestions extends StatelessWidget {
List aQuestions;
int questionIndex;
Function answerQuestion;
mainQuestions(
{required this.aQuestions,
required this.answerQuestion,
required this.questionIndex});
#override
Widget build(BuildContext context) {
return Column(
children: [
Question(
aQuestions[questionIndex]['aQuestion'],
),
...(aQuestions[questionIndex]['answers'] as List<Map<dynamic, dynamic>>)
.map((answer) {
return Answer(answerQuestion, answer);
})
],
);
}
}
My problem is that it keeps saying:
The argument type 'Map<String, Object>' can't be assigned to the parameter type 'String'
I am new to flutter is anyone able to help me? Thanks!
(Didn't mean to use HTML just not sure how to add code)
...(aQuestions[questionIndex]['answers'] as List<Map<dynamic, dynamic>>)
.map((answer) {
return Answer(answerQuestion, answer);
I think what will fix is is extracting the answers into a separate variable, together with calling toList at the end. This didn't raise any compilation errors for me:
List<Widget> _answers() {
List<Map<dynamic, dynamic>> answers = aQuestions[questionIndex]['answers'] as List<Map<dynamic, dynamic>>;
return answers.map(answer => Answer(answerQuestion, answer)).toList();
}
return Column(
children: [
Question(aQuestions[questionIndex]['aQuestion']),
..._answers(),
]
The map function returns an iterable, not a list. That is why after mapping, you have to convert it to a list by calling the toList() function on it.
Here's how:
import 'package:learnflutter/questionMain.dart';
import 'questionButton.dart';
class mainQuestions extends StatelessWidget {
List aQuestions;
int questionIndex;
Function answerQuestion;
mainQuestions(
{required this.aQuestions,
required this.answerQuestion,
required this.questionIndex});
#override
Widget build(BuildContext context) {
return Column(
children: [
Question(
aQuestions[questionIndex]['aQuestion'],
),
...(aQuestions[questionIndex]['answers'] as List<Map<dynamic, dynamic>>)
.map((answer) {
return Answer(answerQuestion, answer);
}).toList()
],
);
}
}

how to set the array list in a listview builder in flutter?

I have array fetched from firestore database successfully, for which I am trying to build a list for array using ListView.builder but not able to do so.
here is the array list I have
[{step: ffg}, {step: fgsgg}, {step: fgfda}]
code for list view builder
Expanded(
child: ListView.builder(
itemCount: widget.steps.length,
itemBuilder: (context, index) => Container(
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Text(
//"STEPS ${index + 1}",
"${widget.steps}",
],
),
),
),
),
Here is the screenshot of the result I am getting
I want the list of array fetched in a serialized manner index wise. How am I suppose to achive it?
This is how I want the list to be displayed
ffg
fgsgg
fgfda
You need to reference an index within the array in the builder. widget.steps is using the default toString method of List to put convert it to a String.
And if you want to not use the default toString of Map(which is what is contained at each List reference), reference the Map item you want to show as well.
Both reference operators for these object are []
Expanded(
child: ListView.builder(
itemCount: widget.steps.length,
itemBuilder: (context, index) => Container(
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Text(
"${widget.steps[index]['step']}",//Reference an index & key here. This is why index is provided as a parameter in this callback
],
),
),
),
),
You can do it like this using a Column..
Column(
children: widget.steps.map((item){
return Text('${item['step']}');
}).toList(),
)
..or using a ListView.builder like this..
ListView.builder(
itemCount: widget.steps.length,
itemBuilder: (BuildContext context, int index){
return Text('${widget.steps[index]['step']}');
},
)
From your response widget.steps is a List of type Map so to get what's inside the list:
you have to define the index number
select the key to get its value
Try this: Text("${widget.steps[index][step]}")
Just use
Text( "${widget.steps[index]['step']}",)

error: The element type 'Iterable<DataRow>' can't be assigned to the list type 'DataRow' [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
In the below code, I tried putting objects in another local list but it still didn't work:
class Amortization extends StatefulWidget {
final String value;
final List<Installment> installments;
Amortization({Key key, this.value, this.installments}) : super(key: key);
#override
_AmortizationState createState() => _AmortizationState();
}
class _AmortizationState extends State<Amortization> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Color.fromRGBO(27, 202, 155, 2),
title: Expanded(
child: Text(
"Amortization Schedule",
style: TextStyle(
color: Color.fromRGBO(25, 0, 64, 2),
fontSize: 25,
fontWeight: FontWeight.bold,
fontStyle: FontStyle.italic),
),
),
),
body: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: DataTable(
columns: <DataColumn>[
DataColumn(label: Text("Month"),),
DataColumn(label: Text("Payment")),
DataColumn(label: Text("Principal")),
DataColumn(label: Text("Interest")),
DataColumn(label: Text("Total I")),
DataColumn(label: Text("Balance")),
],
rows: <DataRow>[
widget.installments.map((Installment) => DataRow())
]
)
)
);
}
}
I'm seeing an error of
error: The element type 'Iterable<DataRow>' can't be assigned to the list type 'DataRow'
What could be causing this?
Try the Spread Operator as shown below.
rows: <DataRow>[
...widget.installments.map((Installment) => DataRow())
]
or use the toList() method:
rows: widget.installments.map((Installment) => DataRow()).toList<DataRow>()

Resources