change containerColor from a list - list

I have previously asked a question regarding lists in Flutter. I got good help but new problems arose within the same list. Since this new probelm is of other character then the initial question I made this new question.
I have a list (the code below is simplified from my working-code to make my problem clearer) of blue colored containers.
When the user types in 5 and press the 'submit'-button the color of the first container should change to green (if not 5 the button should turn red).
The second time the user press the 'submit'-button the second container should change color. And so on...
The problem I'm facing is that I can't get my increment to the list to work.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'listing 4',
theme: ThemeData(primarySwatch: Colors.blue),
home: FirstScreen(),
);
}
}
class FirstScreen extends StatefulWidget {
#override
_FirstScreenState createState() => _FirstScreenState();
}
class _FirstScreenState extends State<FirstScreen> {
int sum = 5;
String userAnswer;
String correction = "";
var _controller = new TextEditingController();
int _counter = 1;
List<Color> colors = [Colors.blue, Colors.blue, Colors.blue];
submitPressed(int index) {
if (userAnswer == sum.toString()) {
setState(() {
correction = sum.toString();
colors[index] = Colors.green;
});
} else {
setState(() {
correction = sum.toString();
colors[index] = Colors.red;
});
}
}
Widget myTextField() {
return Container(
width: 50.0,
child: TextField(
controller: _controller,
textAlign: TextAlign.center,
autofocus: true,
keyboardType: TextInputType.number,
onChanged: (val) {
userAnswer = val;
},
),
);
}
Widget myListBuilder() {
return Container(
height: 50.0,
width: 300.0,
child: Padding(
padding: const EdgeInsets.all(10.0),
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: 3,
itemBuilder: buildContainer,
),
),
);
}
Widget buildContainer(BuildContext context, int index) {
return Container(
child: Padding(
padding: const EdgeInsets.only(top: 10.0),
child: Container(
height: 20.0,
width: 15.0,
decoration: BoxDecoration(
color: colors[index], //this is the important line
borderRadius: BorderRadius.all(Radius.circular(8.0))),
),
));
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text('Listing 4'),
),
body: Container(
child: Center(
child: Column(
children: <Widget>[
Padding(
padding: EdgeInsets.only(top: 10.0),
child: Text('Correct answer is 5',
style: TextStyle(fontSize: 20.0)),
),
myTextField(),
RaisedButton(
child: Text('Submit'),
onPressed: () {
setState(() {
submitPressed(0); //This will naturally only give index 0
});
},
),
myListBuilder(),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
buildContainer(context, 0),
buildContainer(context, 1),
buildContainer(context, 2)
],
),
RaisedButton(
child: Text('Next'),
onPressed: () {
_counter++;
_controller.clear();
myTextField();
},
),
Text('This should be container no: $_counter'),
],
),
),
),
);
}
}

I can't figure out why you have this
submitPressed(0);
This code works:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'listing 4',
theme: ThemeData(primarySwatch: Colors.blue),
home: FirstScreen(),
);
}
}
class FirstScreen extends StatefulWidget {
#override
_FirstScreenState createState() => _FirstScreenState();
}
class _FirstScreenState extends State<FirstScreen> {
int sum = 5;
String userAnswer;
String correction = "";
var _controller = new TextEditingController();
int _counter = 0;
List<Color> colors = [Colors.blue, Colors.blue, Colors.blue];
submitPressed(int index) {
if (userAnswer == sum.toString()) {
setState(() {
correction = sum.toString();
colors[index] = Colors.green;
});
} else {
setState(() {
correction = sum.toString();
colors[index] = Colors.red;
});
}
}
Widget myTextField() {
return Container(
width: 50.0,
child: TextField(
controller: _controller,
textAlign: TextAlign.center,
autofocus: true,
keyboardType: TextInputType.number,
onChanged: (val) {
userAnswer = val;
},
),
);
}
Widget myListBuilder() {
return Container(
height: 50.0,
width: 300.0,
child: Padding(
padding: const EdgeInsets.all(10.0),
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: 3,
itemBuilder: buildContainer,
),
),
);
}
Widget buildContainer(BuildContext context, int index) {
return Container(
child: Padding(
padding: const EdgeInsets.only(top: 10.0),
child: Container(
height: 20.0,
width: 15.0,
decoration: BoxDecoration(
color: colors[index], //this is the important line
borderRadius: BorderRadius.all(Radius.circular(8.0))),
),
));
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: Text('Listing 4'),
),
body: Container(
child: Center(
child: Column(
children: <Widget>[
Padding(
padding: EdgeInsets.only(top: 10.0),
child: Text('Correct answer is 5',
style: TextStyle(fontSize: 20.0)),
),
myTextField(),
RaisedButton(
child: Text('Submit'),
onPressed: () {
setState(() {
submitPressed(_counter);
});
},
),
myListBuilder(),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
buildContainer(context, 0),
buildContainer(context, 1),
buildContainer(context, 2)
],
),
RaisedButton(
child: Text('Next'),
onPressed: () {
setState(() {
_counter++;
});
_controller.clear();
myTextField();
},
),
Text('This should be container no: ${_counter +1}'),
],
),
),
),
);
}
}
I changed the _counter to act like an index and use it as the parameter of the method submitPressed.
I also put the increment in a setState, or you saw the new number only after hitting the Submit button.

Related

Flutter - list inside a list builder

I don't have much experience with flutter.
I would like to use the language_tool library for Dart and Flutter.
I created the script below:
void main() => runApp(mainApp());
class mainApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Chat(),
);
}
}
class Chat extends StatefulWidget {
const Chat({Key? key}) : super(key: key);
#override
_ChatState createState() => _ChatState();
}
class _ChatState extends State<Chat> {
String text = 'Henlo i am Gabriele';
Future<List<WritingMistake>> tool(String text) async {
var tool = LanguageTool();
var result = tool.check(text);
var correction = await result;
print(correction);
List<WritingMistake> mistakes = [];
for (var m in correction) {
//var mistake = m.issueDescription;
WritingMistake mistake = WritingMistake(
message: m.message,
offset: m.offset,
length: m.length,
issueType: m.issueType,
issueDescription: m.issueDescription,
replacements: m.replacements,
);
mistakes.add(mistake);
}
print(mistakes.length);
print(mistakes);
return mistakes;
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
color: Colors.red,
height: 150.0,
width: double.infinity,
child:
Center(child: Text(text, style: TextStyle(fontSize: 20.0))),
),
Text(
'\n Tap on the blue button to replace it in the message.\n',
),
FutureBuilder(
future: tool(text),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.data == null) {
return Container(
child: Center(
child: Text('Loading...'),
),
);
} else {
return SizedBox(
height: 200.0,
child: ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
return Container(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
Row(
children: [
Row(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(' ' +
(index + 1).toString() +
' '),
Container(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(text.substring(
snapshot.data[index].offset,
snapshot.data[index].offset +
snapshot
.data[index].length)),
),
color: Colors.blue,
),
],
),
Icon(
Icons.arrow_forward,
),
Text(snapshot.data[index].issueDescription)
],
),
// Todo: Row with List of .replacements
],
),
),
// snapshot.data[index].issueDescription),
);
},
),
);
}
},
),
Expanded(child: Container(color: Colors.grey))
],
),
),
);
}
}
And it currently looks like this:
And I would like it to become like in this screen, but I would like the green containers derive from the WritingMistake.replacements list (with each element of the list as text):
Do you know how I can do it?
Spent several hours doing exactly what you wanted. My Code:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:language_tool/language_tool.dart';
void main() => runApp(mainApp());
class mainApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return const MaterialApp(
home: Chat(),
);
}
}
class Chat extends StatefulWidget {
const Chat({Key? key}) : super(key: key);
#override
_ChatState createState() => _ChatState();
}
class _ChatState extends State<Chat> {
String text = 'Henlo i am Gabriele';
static List<WritingMistake> mistakes = []; // Moved Here And Init Like Static
Future<List<WritingMistake>> tool(String text) async {
var tool = LanguageTool();
var result = tool.check(text);
var correction = await result;
print(correction);
for (var m in correction) {
//var mistake = m.issueDescription;
WritingMistake mistake = WritingMistake(
message: m.message,
offset: m.offset,
length: m.length,
issueType: m.issueType,
issueDescription: m.issueDescription,
replacements: m.replacements,
);
mistakes.add(mistake);
}
print(mistakes.length);
print(mistakes);
return mistakes;
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
color: Colors.red,
height: 150.0,
width: double.infinity,
child: Center(
child: Text(text, style: const TextStyle(fontSize: 20.0))),
),
const Text(
'\n Tap on the blue button to replace it in the message.\n',
),
FutureBuilder(
future: tool(text),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.data == null) {
return const Center(
child: Text('Loading...'),
);
} else {
return SizedBox(
height: 200.0,
child: ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int mistakeIdIndex) {
return Container(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
Row(
children: [
Row(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(' ' +
(mistakeIdIndex + 1).toString() +
' '),
Container(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(text.substring(
snapshot.data[mistakeIdIndex]
.offset,
snapshot.data[mistakeIdIndex]
.offset +
snapshot
.data[mistakeIdIndex]
.length)),
),
color: Colors.blue,
),
],
),
const Icon(
Icons.arrow_forward,
),
Text(snapshot
.data[mistakeIdIndex].issueDescription)
],
),
// Todo: Row with List of .replacements
SizedBox(
width: MediaQuery.of(context)
.size
.width, // Width = Screen Width
height: 44,
child: ListView.builder(
itemCount: mistakes.length,
scrollDirection: Axis.horizontal,
shrinkWrap: true,
itemBuilder: (BuildContext context,
int replacementsListIndex) {
return buildReplacements(mistakeIdIndex,
replacementsListIndex);
}),
)
],
),
),
// snapshot.data[index].issueDescription),
);
},
),
);
}
},
),
Expanded(child: Container(color: Colors.grey))
],
),
),
);
}
Widget buildReplacements(int mistakeIdIndex, int replacementsListIndex) {
if (mistakes[replacementsListIndex].replacements!.length == null) {
return const SizedBox(); // Return Empty If No Replacements Found, Just To Be Safe
}
// Check For Mistake ID - Remove This Will Cause A Problem with Displaying All Replacements Under All Words
if (mistakeIdIndex == replacementsListIndex) {
// If Only 1 Replacement, No Need To Create ListView.builder
if (mistakes[replacementsListIndex].replacements!.length == 1) {
return Container(
margin: const EdgeInsets.all(4),
padding: const EdgeInsets.all(8),
decoration: const BoxDecoration(
color: Color.fromARGB(255, 174, 213, 130)), // Green Color
child: Text(
mistakes[replacementsListIndex].replacements!.toString(),
style: const TextStyle(),
textAlign: TextAlign.center,
),
);
}
// Create ListView.builder to Create A Split Between Replacements To One Wrong-Word (Every Replacement Has It's Own Container With Green Background)
else {
return ListView.builder(
itemCount: mistakes[replacementsListIndex].replacements!.length,
scrollDirection: Axis.horizontal,
shrinkWrap: true,
itemBuilder: (context, index) {
return Container(
margin: const EdgeInsets.all(4),
padding: const EdgeInsets.all(8),
decoration: const BoxDecoration(
color: Color.fromARGB(255, 174, 213, 130)), // Green Color
child: Text(
mistakes[replacementsListIndex]
.replacements![index]!
.toString(),
style: const TextStyle(),
textAlign: TextAlign.center,
),
);
});
}
}
// If Replacement Not For This Wrong-Word, Then Skip
else {
return const SizedBox();
}
}
}
And Screenshot:

Adding words to the list in the correct order

I'm trying to adjust the words to form the sentence in the correct order. Like this. Or like Duolingo sentence examples. (without drag and drop, just lists and/or maps)
Sentence:
static String mySentence = "My cat is black";
static List<String> correctWords = mySentence.split(" ");
static List<String> shuffleWords = [...correctWords]..shuffle();
Green part: shuffleWidgetList. A widget has been added to each word in the shuffleWords.
List<Widget> shuffleWidgetList = [];
generateShuffleWidgets() {
for (int i = 0; i < shuffleWords.length; i++) {
shuffleWidgetList.add(shuffleWordWidget(shuffleWords[i]));
}
}
Blue part: answerWidgetList.
List<Widget> answerWidgetList = [];
White part: The answer is checked with the button.
I am comparing the list of words (List<String>) correctWords with answerWords.
onTap: () {
if (IterableEquality().equals(correctWords, answerWords)) {
print("correct");
} else {
print("wrong");
}
},
Steps:
1. In the green part, I choose a word from the list. The item I clicked on is added to the answerWidgetList (blue part). And removed from shuffleWidgetList (green part).
onTap: () {
setState(() {
shuffleWidgetList.remove(shuffleWordWidget(word));
//not necessary remove. Look at Problem 1.a
answerWidgetList.add(answerWordWidget(word));
answerWords.add(word);
});
},
2. Clicking on a word in the blue part adds it to its old place in the shuffleWidgetList(green part). And it is removed from answerWidgetList (blue part).
onTap: () {
setState(() {
shuffleWidgetList.add(shuffleWordWidget(word)); //Problem 1.b
answerWidgetList.remove(answerWordWidget(word)); //Problem 2
answerWords.remove(word);
});
},
Problems:
1.a. How can I change shuffleWordWidget's text color when I click an item in shuffleWidgetList?
I tried: In the shuffleWidgetList(green part) it is unnecessary to remove the item when clicking. Text should be transparent (to keep the widget size) and not be clicked again. For this I added bool clicked=false; to shuffleWordWidget. When clicked, onTap() updates to true, but color doesn't update. Like this:
shuffleWordWidget(String word) {
bool clicked = false;
return InkWell(
child: Container(
color: clicked == false ? Colors.white54 : Colors.grey,
child: Text(
word,
style: TextStyle(fontSize: 12,color:clicked == false ? Colors.black : Colors.transparent ),
),
),
onTap: () {
if (clicked == false) {
setState(() {
...
clicked = true;
});
}
},
);
}
1.b. How can I add shuffleWidgetList to its old place when an item is clicked in answerWidgetList?
For old place; that if the user clicks on a word from the answerWidgetList(blue part), it should be the same word clicked=false; again in the shuffleWidgetList(green part).
2. How can I remove item from answerWidgetList when I click an item in answerWidgetList?
answerWidgetList.remove(answerWordWidget(word)); doesn't work.
My approach may be completely wrong. You can also suggest different solutions.
Full code:
import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return const MaterialApp(
title: 'Sentence Creation',
debugShowCheckedModeBanner: false,
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
const HomePage({Key? key}) : super(key: key);
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
static String mySentence = "My cat is black";
static List<String> correctWords = mySentence.split(" ");
static List<String> shuffleWords = [...correctWords]..shuffle();
List<String> answerWords = [];
List<Widget> shuffleWidgetList = [];
List<Widget> answerWidgetList = [];
generateShuffleWidgets() {
for (int i = 0; i < shuffleWords.length; i++) {
shuffleWidgetList.add(shuffleWordWidget(shuffleWords[i]));
}
}
#override
void initState() {
super.initState();
generateShuffleWidgets();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
Expanded(
flex: 2,
child: Container(
color: Colors.blue,
child: Center(
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: answerWidgetList,
),
),
)),
Expanded(
child: Container(
color: Colors.green,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: shuffleWidgetList,
),
),
),
SizedBox(
height: 50,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: InkWell(
child: Center(child: Text("Check")),
onTap: () {
if (IterableEquality().equals(correctWords, answerWords)) {
print("correct");
} else {
print("wrong");
}
print("correct list: $correctWords");
print("answer list: $answerWords");
},
),
),
)
],
),
);
}
shuffleWordWidget(String word) {
return Padding(
padding: const EdgeInsets.all(4.0),
child: InkWell(
child: Container(
color: Colors.white54,
child: Padding(
padding: const EdgeInsets.all(4.0),
child: Text(
word,
style: TextStyle(fontSize: 12),
),
),
),
onTap: () {
setState(() {
shuffleWidgetList.remove(shuffleWordWidget(word));
//not necessary remove. Look at Problem 1.a
answerWidgetList.add(answerWordWidget(word));
answerWords.add(word);
});
},
),
);
}
answerWordWidget(String word) {
return Padding(
padding: const EdgeInsets.all(4.0),
child: InkWell(
child: Container(
color: Colors.white,
child: Padding(
padding: const EdgeInsets.all(4.0),
child: Text(
word,
style: TextStyle(fontSize: 12),
),
),
),
onTap: () {
setState(() {
shuffleWidgetList.add(shuffleWordWidget(word)); //Problem 1.b
answerWidgetList.remove(answerWordWidget(word)); //Problem 2
answerWords.remove(word);
});
},
),
);
}
}
Put this code in _HomePageState.
static String mySentence = "My cat is black";
static List<String> correctWords = mySentence.split(" ");
static List<String> shuffleWords = [...correctWords]..shuffle();
List<String> answerWords = [];
List<Widget> shuffleWidgetList = [];
List<Widget> answerWidgetList = [];
generateShuffleWidgets() {
for (int i = 0; i < shuffleWords.length; i++) {
shuffleWidgetList.add(shuffleWordWidget(shuffleWords[i],true));
}
}
#override
void initState() {
super.initState();
generateShuffleWidgets();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: [
Expanded(
flex: 2,
child: Container(
color: Colors.blue,
child: Center(
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: answerWidgetList,
),
),
)),
Expanded(
child: Container(
color: Colors.green,
child: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: shuffleWidgetList,
),
),
),
SizedBox(
height: 50,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: InkWell(
child: Center(child: Text("Check")),
onTap: () {
if (IterableEquality().equals(correctWords, answerWords)) {
print("correct");
} else {
print("wrong");
}
print("correct list: $correctWords");
print("answer list: $answerWords");
},
),
),
)
],
),
);
}
shuffleWordWidget(String word,bool visible) {
return Visibility(
visible: visible,
child: Padding(
padding: const EdgeInsets.all(4.0),
child: InkWell(
child: Container(
color: Colors.white54,
child: Padding(
padding: const EdgeInsets.all(4.0),
child: Text(
word,
style: TextStyle(fontSize: 12),
),
),
),
onTap: () {
setState(() {
//shuffleWidgetList.remove(shuffleWordWidget(word));
int i = shuffleWords.indexOf(word);
shuffleWidgetList[i]=shuffleWordWidget(word,false);
//not necessary remove. Look at Problem 1.a
answerWidgetList.add(answerWordWidget(word));
answerWords.add(word);
});
},
),
),
);
}
answerWordWidget(String word) {
return Padding(
padding: const EdgeInsets.all(4.0),
child: InkWell(
child: Container(
color: Colors.white,
child: Padding(
padding: const EdgeInsets.all(4.0),
child: Text(
word,
style: TextStyle(fontSize: 12),
),
),
),
onTap: () {
setState(() {
int i = shuffleWords.indexOf(word);
// shuffleWidgetList.insert(i,shuffleWordWidget(word)); //Problem 1.b
shuffleWidgetList[i]=shuffleWordWidget(word,true);
int y = answerWords.indexOf(word);
answerWidgetList.removeAt(y); //Problem 2
answerWords.remove(word);
});
},
),
);
}
I added a visibility detector which is triggered with a bool value. I used the shuffleWords list to get the index of the widget and hid it by changing the bool to false. Similarly answerWords can be used for removing widgets from answerWidgetList. As the widget from answerWidgetList is removed therefore we don't need visibility widget there.
Or if shuffleWordWidget is replaced with this then Visibility() is not needed and the image in the question is obtained.
shuffleWordWidget(String word, bool visible) {
return Padding(
padding: const EdgeInsets.all(4.0),
child: InkWell(
child: Container(
color: visible == true ? Colors.white54 : Colors.grey,
child: Padding(
padding: const EdgeInsets.all(4.0),
child: Text(
word,
style: TextStyle(
fontSize: 12,
color: visible == true ? Colors.black : Colors.transparent),
),
),
),
onTap: () {
if (visible == true) {
setState(() {
//shuffleWidgetList.remove(shuffleWordWidget(word));
int i = shuffleWords.indexOf(word);
shuffleWidgetList[i] = shuffleWordWidget(word, false);
//not necessary remove. Look at Problem 1.a
answerWidgetList.add(answerWordWidget(word));
answerWords.add(word);
});
}
},
),
);
}

Flutter Firebase where query arrayContains in List [duplicate]

This question already has answers here:
Firestore search array contains for multiple values
(6 answers)
Closed 1 year ago.
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class SearchPage extends StatefulWidget {
#override
_SearchPageState createState() => _SearchPageState();
}
class _SearchPageState extends State<SearchPage> with TickerProviderStateMixin {
final searchController = TextEditingController();
final _firestore = FirebaseFirestore.instance;
static const defaultSearch = "";
String search = defaultSearch ;
void dispose() {
searchController.dispose();
super.dispose();
}
#override
void initState() {
super.initState();
searchController.addListener(searchChanged);
}
searchChanged() {
setState(() {
search = searchController.text;
});
}
#override
Widget build(BuildContext context) {
var tarifRef = _firestore
.collection("vehicles")
.where("models", arrayContains: search);
return Scaffold(
body: Container(
child: ListView(
children: <Widget>[
Expanded(
child: Container(
height: MediaQuery.of(context).size.height * 0.08,
margin: EdgeInsets.only(top: 25),
child: Text(
"Vehicles",
style: TextStyle(
fontSize: 20, fontFamily: "Quando", color: Colors.indigo),
),
),
),
Expanded(
child: Container(
margin: EdgeInsets.only(
top: 10.0, bottom: 10.0, right: 30, left: 30),
child: TextField(
keyboardType: TextInputType.text,
decoration: InputDecoration(
prefixIcon: Icon(Icons.search),
),
controller: searchController,
),
),
),
Expanded(
child: Container(
height: MediaQuery.of(context).size.height * 0.50,
child: StreamBuilder<QuerySnapshot>(
stream: tarifRef.snapshots(),
builder: (BuildContext context, AsyncSnapshot asyncsnapshot) {
if (asyncsnapshot.hasError) {
return Center(
child: Text("Error"),
);
} else {
if (asyncsnapshot.hasData) {
List<DocumentSnapshot> listOfDocumentSnapshot =
asyncsnapshot.data.docs;
return Flexible(
child: ListView.builder(
itemCount: listOfDocumentSnapshot.length,
itemBuilder: (context, index) {
return Card(
color: Colors.indigo,
child: ListTile(
title: Text(
"${listOfDocumentSnapshot[index]["name"]}",
style: TextStyle(
fontSize: 20,
color: Colors.white,
),
),
subtitle: Text(
"${listOfDocumentSnapshot[index]["models"]}",
style: TextStyle(
fontSize: 15,
color: Colors.white,
),
),
trailing: IconButton(
icon: Icon(
Icons.delete,
color: Colors.white,
),
onPressed: () async {
await listOfDocumentSnapshot[index]
.reference
.delete();
},
),
),
);
},
),
);
} else {
return Center(
child: CircularProgressIndicator(),
);
}
}
},
),
),
),
],
),
),
);
}
}
This my all code and also I have database in Firebase like this;
vehicles: [
{
"name": "Vehicle1",
"models": ["bus", "plane", "motorcycle"]
},
{
"name": "Vehicle2",
"models": ["motorcycle", "sporcar", "plane"]
},
{
"name": "Vehicle3",
"models": ["motorcycle", "plane", "bus"]
}
]
In this example I can take one input from user, I can query and display which list includes this data but I want to query more than one data is in lists or not.
For example in this code if user input bus, program display Vehicle1 list but I want user can input more than one data such as plane and motorcycle. And so when the user input the plane and motorcycle, I want it to be displayed the list of Vehicle 2 and Vehicle 3.
I try a lot of different ways but I can't found proparly solution to this problem.
I think you're looking for arrayContainsAny here:
var tarifRef = _firestore
.collection("vehicles")
.where("models", arrayContainsAny: ["bus", "plane"]);
This query will return documents whose models array contains either "bus", "plane" or both.
Also see the FlutterFire documentation for Query.where.

onEnd in CountdownTimer with bool

I tried to set a bool to true when my CountdownTimer() from the package flutter_countdown_timer: 1.5.0 is finished. But it changes all my CountdownTimer from my ListView. I think I must to use a List but I don't know how to use that. I am a beginner, be indulgent please. This is my code :
main.dart
import 'package:flutter/material.dart';
import 'package:flutter_countdown_timer/flutter_countdown_timer.dart';
import './data.dart';
import './favorite_screen.dart';
import './home_list.dart';
class Home extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
class Item {
final String title;
final String description;
final String imageURL;
final int countdown;
final int id;
final bool boole;
Item({
this.title,
this.description,
this.imageURL,
this.countdown,
this.id,
this.boole,
});
}
class _HomeState extends State<Home> {
List<Item> savedItems = new List<Item>();
//List<bool> addFavorite = List<bool>();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Home'),
actions: [
IconButton(
icon: Icon(Icons.favorite_border),
onPressed: () => pushToFavorite(context))
],
),
body: ListView.builder(
itemCount: itemData.length,
itemBuilder: (context, index) {
bool isSaved = savedItems.contains(itemData[index]);
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
TextObject(
itemData[index].title, itemData[index].description),
TimerWidget(itemData[index].countdown),
Spacer(),
Container(
padding: const EdgeInsets.only(left: 8.0, top: 8.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(7.0),
child: GestureDetector(
child: Icon(
isSaved
? Icons.favorite
: Icons.favorite_border,
color: isSaved ? Colors.red : null,
size: 32,
),
onTap: () {
setState(() {
if (isSaved) {
savedItems.remove(itemData[index]);
isSaved = false;
} else {
savedItems.add(itemData[index]);
isSaved = true;
}
});
},
),
),
])),
],
),
)
],
);
}));
}
Future pushToFavorite(BuildContext context) {
return Navigator.of(context).push(MaterialPageRoute(
builder: (context) => Favorite(favoriteItem: savedItems)));
}
}
timerWidget.dart
import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:flutter_countdown_timer/flutter_countdown_timer.dart';
class TextObject extends StatelessWidget {
final String title;
final String description;
const TextObject(this.title, this.description);
#override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Spacer(),
//Titre
Container(
padding: const EdgeInsets.only(top: 15.0),
child: FittedBox(
child: Text(
title,
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
),
),
),
//Decription
Container(
padding: const EdgeInsets.only(left: 10.0, top: 15.0),
child: Text(
description,
style: TextStyle(fontSize: 18, fontWeight: FontWeight.normal),
),
),
Spacer(),
],
);
}
}
class TimerWidget extends StatefulWidget {
final int date;
const TimerWidget(
this.date,
);
#override
_TimerWidgetState createState() => _TimerWidgetState();
}
class _TimerWidgetState extends State<TimerWidget> {
bool finished = false;
#override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.only(top: 10.0),
child: finished == false ? CountdownTimer(
daysSymbol: new Text("j "),
hoursSymbol: new Text(" : "),
minSymbol: new Text(" : "),
secSymbol: new Text(""),
endTime: widget.date,
textStyle: TextStyle(
fontSize: 14,
fontWeight: FontWeight.bold,
color: Colors.black,
),
onEnd: () {
setState(() {
finished = true;
});
},
) : Text('It is finished'));
}
}
Thanks !

Flutter Merging List of Images

I was working on merging few images and display it as one.
I have two dart files one is for adding images and other is for displaying the merged result.
first file code is,
class SingleImageUpload extends StatefulWidget {
#override
_SingleImageUploadState createState() {
return _SingleImageUploadState();
}
}
class _SingleImageUploadState extends State<SingleImageUpload> {
List<Object> images = List<Object>();
File _selectedFile;
bool _inProcess = false;
Map data = {};
Readerservice _readerservice;
#override
void initState() {
// TODO: implement initState
super.initState();
setState(() {
images.add("Add Image");
images.add("Add Image");
images.add("Add Image");
images.add("Add Image");
});
}
#override
Widget build(BuildContext context) {
return new MaterialApp(
debugShowCheckedModeBanner: false,
home: new Scaffold(
appBar: AppBar(
backgroundColor: Colors.white,
leading: Padding(
padding: EdgeInsets.only(left: 12),
child: IconButton(
icon: Icon(Icons.arrow_back_ios,
color: Colors.black,
size: 30,),
onPressed: () {
Navigator.pushNamed(context, '/');
},
),
),
title: Row(
mainAxisAlignment: MainAxisAlignment.center,
children:<Widget>[
Text('Basic AppBar'),
]
),
actions: <Widget>[
IconButton(
icon: Icon(Icons.more_vert,
color: Colors.black,
size: 30,),
onPressed: () {
print('Click start');
},
),
],
),
body:
Column(
children: <Widget>[
SizedBox(height: 10),
Row(children: <Widget>[
Text('Image',
style: TextStyle(
color: Colors.black,
fontSize: 33,
fontWeight: FontWeight.bold,
)),
Text('Merger',
style: TextStyle(
color: Colors.orange,
fontSize: 33,
fontWeight: FontWeight.bold,
)),
]),
SizedBox(height: 40),
Text(' merge it here'),
SizedBox(height: 10),
Expanded(
child: buildGridView(),
),
RaisedButton(
textColor: Colors.white,
color: Colors.orange,
child: Text("Finish",
style: TextStyle(fontSize: 15),),
onPressed: () {
pasimage();
},
shape: new RoundedRectangleBorder(
borderRadius: new BorderRadius.circular(8.0),
),
),
],
),
),
);
}
Widget buildGridView() {
return GridView.count(
shrinkWrap: true,
crossAxisCount: 3,
childAspectRatio: 1,
children: List.generate(images.length, (index) {
if (images[index] is ImageUploadModel) {
ImageUploadModel uploadModel = images[index];
return Card(
clipBehavior: Clip.antiAlias,
child: Stack(
children: <Widget>[
Image.file(
uploadModel.imageFile,
width: 300,
height: 300,
),
Positioned(
right: 5,
top: 5,
child: InkWell(
child: Icon(
Icons.remove_circle,
size: 20,
color: Colors.red,
),
onTap: () {
setState(() {
images.replaceRange(index, index + 1, ['Add Image']);
});
},
),
),
],
),
);
} else {
return Card(
child: IconButton(
icon: Icon(Icons.add),
onPressed: () {
//popup
showDialog(
context: context,
builder: (context) {
return Dialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10)),
elevation: 16,
child: Container(
height: 180.0,
width: 330.0,
child: ListView(
children: <Widget>[
SizedBox(height: 20),
//Center(
Padding(
padding: const EdgeInsets.only(left: 15.0),
child: Text(
"Add a Receipt",
textAlign: TextAlign.left,
style: TextStyle(
fontSize: 24,
color: Colors.black,
fontWeight: FontWeight.bold),
),
),
// ),
SizedBox(height: 20),
FlatButton(
child: Text(
'Take a photo..',
textAlign: TextAlign.left,
style: TextStyle(fontSize: 20),
),
onPressed: () {
_onAddImageClick(index,ImageSource.camera);
Navigator.of(context).pop();
// picker.getImage(ImageSource.camera);
},
textColor: Colors.black,
),
FlatButton(
child: Text(
'Choose from Library..',
style: TextStyle(fontSize: 20),
textAlign: TextAlign.left,
),
onPressed: () {
_onAddImageClick(index,ImageSource.gallery);
Navigator.of(context).pop();
},
textColor: Colors.black,
),
],
),
),
);
},
);
//pop ends
},
),
);
}
}),
);
}
Future _onAddImageClick(int index, ImageSource source ) async {
setState(() {
_inProcess = true;
});
File image = await ImagePicker.pickImage(source: source);
if(image != null){
File cropped = await ImageCropper.cropImage(
sourcePath: image.path,
maxWidth: 1080,
maxHeight: 1080,
compressFormat: ImageCompressFormat.jpg,
androidUiSettings: AndroidUiSettings(
toolbarColor: Colors.black,
toolbarWidgetColor: Colors.white,
//toolbarTitle: "RPS Cropper",
statusBarColor: Colors.deepOrange.shade900,
backgroundColor: Colors.black,
initAspectRatio: CropAspectRatioPreset.original,
lockAspectRatio: false
),
iosUiSettings: IOSUiSettings(
minimumAspectRatio: 1.0,
)
);
this.setState((){
_selectedFile = cropped ;
_inProcess = false;
});
} else {
this.setState((){
_inProcess = false;
});
}
getFileImage(index);
}
void getFileImage(int index) async {
// var dir = await path_provider.getTemporaryDirectory();
setState(() {
ImageUploadModel imageUpload = new ImageUploadModel();
imageUpload.isUploaded = false;
imageUpload.uploading = false;
imageUpload.imageFile = _selectedFile;
imageUpload.imageUrl = '';
images.replaceRange(index, index + 1, [imageUpload]);
});
}
void pasimage(){
Navigator.pushReplacementNamed(context, '/crop',arguments: {
'imageList':ImagesMerge(
images,///required,images list
direction: Axis.vertical,///direction
backgroundColor: Colors.black26,///background color
fit: false,///scale image to fit others
),
});
}
}
class ImageUploadModel {
bool isUploaded;
bool uploading;
File imageFile;
String imageUrl;
ImageUploadModel({
this.isUploaded,
this.uploading,
this.imageFile,
this.imageUrl,
});
}
when I tap the finish button after adding the images it shows an error
The following _TypeError was thrown while handling a gesture:
type 'List' is not a subtype of type 'List'
The page just on captures the data sent from the code above and display the image.
please if anyone know why is the error and help me .
Change the images to List<Object> images = [].