I want to activate and deactivate favorite icon for every individual item
as what I am getting now is to fill that icon but at the same time,it doesnt get
deactivated.
bool isPressed=false;
new GestureDetector(
onTap: () {
setState(() => isPressed = true);
},
child: Icon(Icons.favorite_sharp,
// color: Colors.redAccent,
color: (isPressed)
? Colors.red
: Colors.black12)),
Now activation and deactivation is working but while selecting an individual favorite icon, it is showing all the favorite icon as selected.
ListView.builder(
itemCount: infoList.length,
itemBuilder: (BuildContext context, int index) {
Info info = new Info(
"${infoList[index].id}",
"${infoList[index].name}",
"${infoList[index].image}",
"${infoList[index].thumb}",
"${infoList[index].catagory}",
"${infoList[index].price}",
"${infoList[index].qty}",
);
return new Card(
margin: EdgeInsets.fromLTRB(5, 0, 5, 5),
elevation: 5,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0)),
child: ClipRRect(
child: ListTile(
leading: Container(
child: Image.network("${infoList[index].image}")),
title: Text(
"${infoList[index].name}",
style: TextStyle(
fontStyle: FontStyle.normal,
fontSize: 14,
color: Colors.black),
),
subtitle: Text(
"\$ ${infoList[index].price}",
style: TextStyle(
fontStyle: FontStyle.normal,
fontSize: 14,
color: Colors.black),
),
trailing: Wrap(
spacing: 12,
children: [
GestureDetector(
onTap: () {
setState(() => isPressed = !isPressed);
},
child: Icon(Icons.favorite_sharp,
// color: Colors.redAccent,
color: (isPressed)
? Colors.red
: Colors.black12)),
// Icon(
// Icons.add_shopping_cart,
// color: Colors.white,
// ),
],
),
You need to change your onTap to actually toggle:
onTap: () {
setState(() => isPressed = !isPressed);
},
I just added an ' _ ' to the isPressed variable as it is a good practice to keep such variables as private.
i.e.
isPressed -> Public
_isPressed -> Private
bool _isPressed = false;
GestureDetector(
onTap: () {
setState(() => _isPressed = !_isPressed);
},
child: Icon(Icons.favorite_sharp,
color: _isPressed ? Colors.red : Colors.black12)),
For each widget to have it's on selection you'll have to make it into a separate Stateful Widget and then pass it into the ListView.
Once you've done that now every widget will have it's own state and they can be separately selected / disselected.
EDIT
Make the Card Widget into another StateFull widget
For eg.
class CardWidget extends StatefulWidget {
final Info info;
CardWidget(this.info);
#override
_CardWidgetState createState() => _CardWidgetState();
}
class _CardWidgetState extends State<CardWidget> {
bool _isPressed = false;
#override
Widget build(BuildContext context) {
return Card(
margin: EdgeInsets.fromLTRB(5, 0, 5, 5),
elevation: 5,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0)),
child: ClipRRect(
child: ListTile(
leading: Container(
child: Image.network("${widget.info.image}")),
title: Text(
"${widget.info.name}",
style: TextStyle(
fontStyle: FontStyle.normal,
fontSize: 14,
color: Colors.black),
),
subtitle: Text(
"\$ ${widget.info.price}",
style: TextStyle(
fontStyle: FontStyle.normal,
fontSize: 14,
color: Colors.black),
),
trailing: Wrap(
spacing: 12,
children: [
GestureDetector(
onTap: () {
setState(() => _isPressed = !_isPressed);
},
child: Icon(Icons.favorite_sharp,
// color: Colors.redAccent,
color: (isPressed)
? Colors.red
: Colors.black12)),
// Icon(
// Icons.add_shopping_cart,
// color: Colors.white,
// ),
],
),
Now use the CardWidget to populate the ListView.
Just remember to pass in all the values to the widget as shown below.
ListView.builder(
itemCount: infoList.length,
itemBuilder: (BuildContext context, int index) {
Info info = new Info(
"${infoList[index].id}",
"${infoList[index].name}",
"${infoList[index].image}",
"${infoList[index].thumb}",
"${infoList[index].catagory}",
"${infoList[index].price}",
"${infoList[index].qty}",
);
return CardWidget(info);
Related
I created a select country page and I is created using ListView inside a sizedBox with a specific height.
The error is i can select any country and when i scroll down i can still the see the blank selected ListTile in blue color.
I searched if there are other options for this, but was unable to find any.
screenshot 1
screenshot 2
Help is appreciated.
class SelectCountryScreen extends StatefulWidget {
const SelectCountryScreen({super.key});
#override
State<SelectCountryScreen> createState() => _SelectCountryScreenState();
}
class _SelectCountryScreenState extends State<SelectCountryScreen> {
// list for filtered countries
List<Country> _filteredCountries = [];
final List<Country> countries = Countries.all();
TextEditingController searchController = TextEditingController();
int _selectedIndex = -1;
#override
void initState() {
super.initState();
_filteredCountries = countries;
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Theme.of(context).backgroundColor,
body: Container(
margin: const EdgeInsets.all(24),
height: MediaQuery.of(context).size.height,
width: double.infinity,
child: Column(
children: [
SizedBox(
height: 500,
child: ListView.builder(
itemCount: _filteredCountries.length,
itemBuilder: ((context, index) {
return Container(
margin:
const EdgeInsets.symmetric(vertical: 2, horizontal: 1),
child: ListTile(
visualDensity: const VisualDensity(vertical: -3),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(4),
),
contentPadding: const EdgeInsets.symmetric(
vertical: 0,
horizontal: 15,
),
title: Text(
_filteredCountries[index].name!,
style: Theme.of(context).textTheme.bodySmall?.copyWith(
color: _selectedIndex == index
? Colors.white
: Theme.of(context)
.textTheme
.bodySmall!
.color,
),
),
leading: Text(
_filteredCountries[index].flagIcon!,
style: const TextStyle(fontSize: 26),
),
selectedTileColor: Theme.of(context).primaryColor,
selected: _selectedIndex == index ? true : false,
selectedColor: Theme.of(context).primaryColor,
onTap: () {
setState(() {
_selectedIndex = index;
});
},
),
);
}),
),
),
PrimaryButton(
label: "Next",
onPressed: () {},
)
],
),
),
);
}
}
Move the selected color from ListTile to parent Container like this:
Container(
decoration: BoxDecoration(
color: _selectedIndex == index ? Theme.of(context).primaryColor : null,
borderRadius: const BorderRadius.all(Radius.circular(5)),
),
margin:
const EdgeInsets.symmetric(vertical: 2, horizontal: 1),
child: ListTile(
visualDensity: const VisualDensity(vertical: -3),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(4),
),
contentPadding: const EdgeInsets.symmetric(
vertical: 0,
horizontal: 15,
),
title: Text(
_filteredCountries[index].name!,
style:Theme.of(context).textTheme.bodySmall?.copyWith(
color: _selectedIndex == index
? Colors.white
: Theme.of(context).textTheme
.bodySmall!
.color,
),
),
leading: Text(
_filteredCountries[index].flagIcon!,
style: const TextStyle(fontSize: 26),
),
// selectedTileColor: Theme.of(context).primaryColor,
// selected: _selectedIndex == index ? true : false,
selectedColor: Theme.of(context).primaryColor,
onTap: () {
setState(() {
_selectedIndex = index;
});
},
),
);
With my current code, my list is put into separate cards. I need it to be in one. I'm using two ListView.builders and a loop. I believe that's what's causing the problem. Please tell me if I'm wrong.
Every time the user taps submit on my second TextField a new TextField appears, functionality I would like to keep one way or another.
I'm just staring out so any help if appreciated.
My end goal is to have a bullet point list but the bullet points aren't important right now.
Here's my code:
class PostNote extends StatefulWidget {
User user;
PostNote({
required this.user,
});
#override
State<PostNote> createState() => _PostNoteState();
}
class _PostNoteState extends State<PostNote> {
FirebaseFirestore firestore = FirebaseFirestore.instance;
TextEditingController titleController = TextEditingController();
final List<TextField> _textFields = [];
final List<TextEditingController> _controllers = [];
bool loading = false;
#override
void initState() {
super.initState();
_addTextField();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Color(0xFF162242),
elevation: 0,
),
body: GestureDetector(
onTap: () {
FocusScope.of(context).unfocus();
},
child: SingleChildScrollView(
child: Padding(
padding: EdgeInsets.all(20),
child: Column(
children: [
Text(
"Title",
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
SizedBox(
height: 15,
),
Container(
height: 60,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(
Radius.circular(10),
),
color: Colors.white,
),
padding: EdgeInsets.only(left: 10, right: 10),
child: TextField(
decoration: InputDecoration(
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Colors.transparent),
),
),
textInputAction: TextInputAction.next,
style: TextStyle(
color: Color(0xFF192A4F),
fontSize: 18,
),
controller: titleController,
autofocus: true,
),
),
SizedBox(
height: 30,
),
Text(
"Notes",
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
SizedBox(
height: 15,
),
Container(
padding: EdgeInsets.only(left: 10, right: 10),
decoration: BoxDecoration(
borderRadius: BorderRadius.all(
Radius.circular(10),
),
color: Colors.white,
),
child: ListView.builder( // HERE
shrinkWrap: true,
itemCount: _textFields.length,
itemBuilder: (_, index) {
return _textFields[index];
},
),
),
SizedBox(
height: 50,
),
loading
? Center(
child: CircularProgressIndicator(),
)
: Container(
height: 50,
width: MediaQuery.of(context).size.width,
child: ElevatedButton(
child: Text(
"Add Note",
style: TextStyle(
fontSize: 25,
fontWeight: FontWeight.bold,
),
),
style: ButtonStyle(
backgroundColor:
MaterialStateProperty.all(Color(0xFF162242)),
shape: MaterialStateProperty.all<
RoundedRectangleBorder>(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
),
),
onPressed: () async {
for (var notesController in _controllers) // HERE {
if (titleController.text == "" ||
notesController.text.isEmpty) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content:
Text("All fields are required")));
} else {
setState(() {
loading = true;
});
await FirestoreServiceEdit().insertNote(
titleController.text,
notesController.text,
widget.user.uid);
CollectionReference notes =
firestore.collection('notes');
QuerySnapshot allResults = await notes.get();
allResults.docs.forEach((DocumentSnapshot result) {
print(result.data());
});
if (!mounted) return;
setState(() {
loading = false;
});
Navigator.pop(context);
}
}
}),
),
]),
),
),
),
);
}
void _addTextField() {
final notesController = TextEditingController();
_textFields.add(
TextField(
decoration: InputDecoration(
prefix: Icon(
Icons.circle,
size: 8,
color: Colors.black,
),
),
autofocus: true,
controller: notesController,
onSubmitted: (_) => setState(() => _addTextField()),
),
);
_controllers.add(notesController);
}
}
class FirestoreServiceEdit{
FirebaseFirestore firestore = FirebaseFirestore.instance;
Future insertNote(String title, String notes, String? userId,)async{
try{
await firestore.collection('notes').add({
"title":title,
"notes":notes,
"userId":userId
});
} catch (e) {}
}
}
class NoteModelEdit {
String id;
String title;
String notes;
String userId;
NoteModelEdit({
required this.id,
required this.title,
required this.notes,
required this.userId
});
factory NoteModelEdit.fromJson(DocumentSnapshot snapshot){
return NoteModelEdit(
id: snapshot.id,
title: snapshot['title'],
notes: snapshot['notes'],
userId: snapshot['userId']
);
}
}
Home screen:
body: StreamBuilder(
stream: FirebaseFirestore.instance
.collection("notes")
.where('userId', isEqualTo: user.uid)
.snapshots(),
builder: (context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
if (snapshot.data.docs.length > 0) {
return ListView.builder( // HERE
itemCount: snapshot.data.docs.length,
itemBuilder: (context, index) {
NoteModelEdit note =
NoteModelEdit.fromJson(snapshot.data.docs[index]);
return Card(
margin: EdgeInsets.only(top: 18, left: 15, right: 15),
child: Column(children: [
ListTile(
title: Center(
child: Container(
padding: EdgeInsets.only(bottom: 10),
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(width: 0.5),
),
),
child: Text(
note.title,
textWidthBasis: TextWidthBasis.longestLine,
style: TextStyle(
fontSize: 40,
fontWeight: FontWeight.w600),
textAlign: TextAlign.center,
),
),
),
onTap: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => EditNoteScreen(),
));
},
),
SizedBox(
height: 15,
),
Align(
alignment: Alignment.centerLeft,
child: Text(
note.notes,
textAlign: TextAlign.left,
style: TextStyle(
fontSize: 18, fontWeight: FontWeight.w700),
),
),
SizedBox(
height: 15,
),
]),
);
});
Thank you for your time!
You will need to augment your logic to look at all the TextFields at the same time rather than one at a time and inserting a note for each.
if (titleController.text.isEmpty ||
_controllers.any((element) => element.text.isEmpty)) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content:
Text("All fields are required")));
} else {
setState(() {
loading = true;
});
}
await FirestoreServiceEdit().insertNote(
titleController.text,
_controllers.map((element) => element.text).join("\n"),
widget.user.uid);
you can do like this :
Widget listInCard() {
List testList = ["note1", "note2", "note3"];
return Card(
color: Colors.blue.shade200,
elevation: 5,
child: ListView.builder(
itemCount: testList.length,
itemBuilder: (context, index) {
return Text(testList[index]);
}),
);
}
The blue color is the Card and inside it, it is a list of notes.
You can also use Container instead of Card.
This Error Showing When i Click On Notification Navigation Item from Profile Page To Notification
Exception has occurred. FlutterError (setState() called after
dispose(): _MyProfileState#c3ad1(lifecycle state: defunct, not
mounted) This error happens if you call setState() on a State object
for a widget that no longer appears in the widget tree (e.g., whose
parent widget no longer includes the widget in its build). This error
can occur when code calls setState() from a timer or an animation
callback. The preferred solution is to cancel the timer or stop
listening to the animation in the dispose() callback. Another solution
is to check the "mounted" property of this object before calling
setState() to ensure the object is still in the tree. This error might
indicate a memory leak if setState() is being called because another
object is retaining a reference to this State object after it has been
removed from the tree. To avoid memory leaks, consider breaking the
reference to this object during dispose().)
Profile Page :
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:play_big_win/constants.dart';
import 'package:play_big_win/services/firebase-auth-helper.dart';
class MyProfile extends StatefulWidget {
#override
_MyProfileState createState() => _MyProfileState();
}
class _MyProfileState extends State<MyProfile> {
final firebaseUser = FirebaseAuth.instance.currentUser;
final db = FirebaseFirestore.instance;
String fullname = '';
String email = '';
#override
void dispose() {
SystemChrome.setEnabledSystemUIOverlays(SystemUiOverlay.values);
super.dispose();
}
#override
initState() {
SystemChrome.setEnabledSystemUIOverlays([]);
super.initState();
}
getData() async {
while (mounted) {
dynamic names = await FirebaseAuthHelper().getCurrentUserData();
if (names != null) {
fullname = names[0];
email = names[1];
setState(() {});
} else {
print("Nulllll");
}
}
}
#override
Widget build(BuildContext context) {
getData();
return Scaffold(
backgroundColor: kPrimaryColor,
body: SafeArea(
child: ListView(
shrinkWrap: true,
children: [
SizedBox(
height: 20,
),
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Container(
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.all(
Radius.circular(15),
),
),
width: MediaQuery.of(context).size.width - 25,
height: 150,
child: Row(
children: [
CircleAvatar(
radius: 60.0,
backgroundImage: NetworkImage(
'https://res.cloudinary.com/dqunmzmqo/image/upload/v1606248032/male-clipart-avatar_ewaerc.png',
),
),
Padding(
padding: const EdgeInsets.only(top: 45.0),
child: Column(
children: [
Text(
"Name: $fullname",
style: TextStyle(
fontSize: 14,
),
),
SizedBox(
height: 10,
),
Text(
"Email: $email",
style: TextStyle(
fontSize: 14,
),
),
SizedBox(
height: 10,
),
Text(
"Refer Code: Xasdsas",
style: TextStyle(
fontSize: 14,
),
)
],
),
),
],
),
),
Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Text(
'Play Big Win Big',
style: TextStyle(
fontFamily: 'Pacifico',
fontSize: 20.0,
color: Colors.white,
),
),
),
SizedBox(
height: 5,
),
Text(
'V1.0',
style: TextStyle(
fontSize: 10.0,
letterSpacing: 2.5,
color: Colors.teal.shade100,
fontWeight: FontWeight.bold,
),
),
SizedBox(
height: 20.0,
width: 150.0,
child: Divider(
color: Colors.teal.shade100,
),
),
GestureDetector(
onTap: () {
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => MyprivacyPolicy(),
// ));
},
child: Card(
color: Colors.white,
margin:
EdgeInsets.symmetric(vertical: 10.0, horizontal: 25.0),
child: ListTile(
leading: Icon(
Icons.group_add,
color: Colors.teal,
),
title: Text(
'Invite Friends',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 17.0,
color: Colors.teal.shade900,
),
),
),
),
),
GestureDetector(
onTap: () {
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => MyprivacyPolicy(),
// ));
},
child: Card(
color: Colors.white,
margin:
EdgeInsets.symmetric(vertical: 10.0, horizontal: 25.0),
child: ListTile(
leading: Icon(
Icons.question_answer,
color: Colors.teal,
),
title: Text(
"FAQ's",
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 17.0,
color: Colors.teal.shade900,
),
),
),
),
),
GestureDetector(
onTap: () {
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => MyprivacyPolicy(),
// ));
},
child: Card(
color: Colors.white,
margin:
EdgeInsets.symmetric(vertical: 10.0, horizontal: 25.0),
child: ListTile(
leading: Icon(
Icons.privacy_tip,
color: Colors.teal,
),
title: Text(
'Privacy Policy',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 17.0,
color: Colors.teal.shade900,
),
),
),
),
),
GestureDetector(
onTap: () {
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => TermsandCondtions(),
// ));
},
child: Card(
color: Colors.white,
margin:
EdgeInsets.symmetric(vertical: 10.0, horizontal: 25.0),
child: ListTile(
leading: Icon(
Icons.auto_fix_normal,
color: Colors.teal,
),
title: Text(
'Terms & Conditions',
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 17.0,
color: Colors.teal.shade900,
),
),
),
),
),
],
),
],
),
),
);
}
}
Notification Page:
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import '../../constants.dart';
class MyNotification extends StatefulWidget {
#override
_MyNotificationState createState() => _MyNotificationState();
}
class _MyNotificationState extends State<MyNotification> {
#override
void dispose() {
SystemChrome.setEnabledSystemUIOverlays(SystemUiOverlay.values);
super.dispose();
}
#override
initState() {
SystemChrome.setEnabledSystemUIOverlays([]);
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
backgroundColor: kPrimaryColor,
title: Text(
"Notifications",
),
),
body: Center(
child: Padding(
padding: const EdgeInsets.all(15.0),
child: Container(
decoration: BoxDecoration(
color: Colors.deepPurple,
borderRadius: BorderRadius.all(
Radius.circular(
20,
),
),
),
height: 300,
width: MediaQuery.of(context).size.width,
child: Center(
child: Padding(
padding: const EdgeInsets.all(12.0),
child: Text(
"Today Is Your sadsadasdas das das dsa sa dsa dsad asd as das asd sad asd asds das sa dsa",
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w600,
),
),
),
),
),
),
),
);
}
}
My Authenticate Code:
Future getCurrentUserData() async {
try {
DocumentSnapshot ds = await users.doc(firebaseUser.uid).get();
String fullname = ds.get('full_name');
String email = ds.get('email');
return [fullname, email];
} catch (e) {
print(e.toString());
return null;
}
}
This Code Which I Call in Profile Page:
getData() async {
while (mounted) {
dynamic names = await FirebaseAuthHelper().getCurrentUserData();
if (names != null) {
fullname = names[0];
email = names[1];
setState(() {});
} else {
print("Null");
}
}
}
You are using setState in async function, After an await, your widget may not be mounted anymore. Doing setState gives you an exception at that time. use the below code or place it at any other place
if (this.mounted) {
setState(() {
});
}
or more clear approach override setState
#override
void setState(fn) {
if(mounted) {
super.setState(fn);
}
}
I'm developing a flight ticket booking app with flutter and I'm trying to add a search query from Firestore for the start and destination. basically the idea is for the user to choose his starting and destination location by searching and when he select his starting station it will be stored in selected item and this particular item will not be found in the destination items no longer.
can you show me how to accomplish this task?
You can implement search text by using this code:
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:trackingsystem/Director/Director_View_Job_Details.dart';
class DirectorViewJob extends StatefulWidget {
#override
_DirectorViewJobState createState() => new _DirectorViewJobState();
}
class _DirectorViewJobState extends State<DirectorViewJob> {
var jobTitle = [];
var jobDescription = [];
var jobSalary = [];
var jobExperience = [];
var jobDeadlineDate = [];
var companyName = [];
bool dataCheck = false;
bool isLoading = false;
var jobDetails;
var id;
var documnet = [];
List products = [];
var productId = [];
var deleteTitle;
void getJobs() async {
setState(() {
isLoading = true;
});
Firestore.instance
.collection("CreateJob")
.getDocuments()
.then((querySnapshot) {
querySnapshot.documents.forEach((result) {
id = result.documentID;
products.add(result.data['Job Details']);
documnet.add(id);
jobDetails = (result.data["Job Details"]);
jobTitle.add(jobDetails['title']);
jobDescription.add(jobDetails['description']);
jobSalary.add(jobDetails['salary']);
jobDeadlineDate.add(jobDetails['date']);
print("date $jobDeadlineDate");
jobExperience.add(jobDetails['Experience_Level']);
companyName.add(jobDetails['companyName']);
if (jobDetails.isNotEmpty) {
setState(() {
dataCheck = true;
});
} else {
isLoading = true;
}
});
setState(() {
isLoading = false;
});
});
}
searchJob(q) {
print(q);
print('products $products');
for (int i = 0; i < products.length; i++) {
if (products[i]['title'] == "$q") {
setState(() {
jobTitle.clear();
jobSalary.clear();
jobDescription.clear();
jobDeadlineDate.clear();
jobTitle.add(products[i]['title']);
jobDescription.add(products[i]["description"]);
jobSalary.add(products[i]['salary']);
jobDeadlineDate.add(products[i]['date']);
});
}
}
}
#override
void initState() {
getJobs();
super.initState();
}
#override
void dispose() {
// TODO: implement dispose
super.dispose();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
backgroundColor: Colors.blueGrey[600],
title: Text(
"Jobs",
style: TextStyle(fontFamily: 'Righteous'),
),
),
backgroundColor: Colors.white,
body: isLoading
? SpinKitDoubleBounce(
color: Colors.blueGrey,
)
: Center(
child: ListView(
children: dataCheck
? <Widget>[
SizedBox(
height: 20,
),
SizedBox(
height: 10,
),
Container(
child: TextField(
// controller: _searchQueryController,
autofocus: true,
decoration: InputDecoration(
labelText: "Search Job",
hintText: "Search",
prefixIcon: Icon(
Icons.search,
color: Colors.blueGrey[400],
),
fillColor: Colors.white,
border: new OutlineInputBorder(
borderRadius:
new BorderRadius.circular(25.0),
borderSide: new BorderSide(),
),
//fillColor: Colors.green
),
style: TextStyle(
color: Colors.blueGrey[300],
fontSize: 16.0),
onChanged: (query) => {searchJob(query)},
),
),
SizedBox(
height: 10,
),
Container(
decoration: BoxDecoration(
// color: Colors.lightGreen[100],
),
child: new ListView.builder(
shrinkWrap: true,
physics: BouncingScrollPhysics(),
itemCount: jobTitle?.length ?? 0,
itemBuilder: (BuildContext context, index) {
return InkWell(
splashColor: Colors.white,
onTap: () async {
Navigator.push(
context,
new MaterialPageRoute(
builder: (context) =>
DirectorJobDetails(
jobDetailName:
jobTitle[index],
jobDetailDescription:
jobDescription[
index],
jobDetailExperience:
jobExperience[
index],
jobDetailDate:
jobDeadlineDate[
index],
jobDetailSalary:
jobSalary[index],
jobDetailCompany:
companyName[index],
documentId:
documnet[index],
)),
);
},
child: new Card(
color: Colors.blueGrey[200],
elevation: 5,
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(30.0),
),
child: Container(
decoration: BoxDecoration(),
child: ListTile(
leading: Icon(Icons.work,
size: 40),
title: Text(jobTitle[index],
style: TextStyle(
color: Colors.black,
fontSize: 23.0,
// fontWeight: FontWeight.bold,
fontFamily:
'Righteous',
//decoration: TextDecoration.none
)),
subtitle: Row(children: [
SizedBox(
height: 10,
),
Expanded(
child: Text(
"Salary : ${jobSalary[index]}",
style: TextStyle(
color:
Colors.black,
fontSize: 18.0,
// fontWeight: FontWeight.bold,
fontFamily:
'Righteous',
//decoration: TextDecoration.none
)),
),
Expanded(
child: Text(
"DeadLine Date : ${jobDeadlineDate[index]}",
style: TextStyle(
color:
Colors.black,
fontSize: 18.0,
// fontWeight: FontWeight.bold,
fontFamily:
'Righteous',
//decoration: TextDecoration.none
)),
)
]),
//
))));
}),
),
SizedBox(
height: 20,
)
]
: <Widget>[
Container(
padding: EdgeInsets.fromLTRB(
50.0, 100.0, 50.0, 50.0),
child: Center(
child: Text(
"No Jobs are available",
style: TextStyle(
color: Colors.black,
fontSize: 25.0,
fontWeight: FontWeight.bold,
fontFamily: 'Righteous',
//decoration: TextDecoration.none
),
),
))
]),
)),
// This trailing comma makes auto-formatting nicer for build methods.
);
}
}
You can use limit in your code Like this:
FirebaseFirestore.instance.collection('test').limit(2).get()
and you'll get only two elements
I am new to Flutter here i'm trying to select all the square boxes, given below is the code for single selection of ListTile when one tile is selected it changes it's background color to redAccent, but i need code for multiple selection where i can select all three ListTile or either two ListTile and not only one
class MultiSelect extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: GradientAppBar(
title: Text('MultiSelect'),
),
body: MultipleSelectItems(),
);
}
}
class MultipleSelectItems extends StatefulWidget {
#override
_MultipleSelectItemsState createState() => _MultipleSelectItemsState();
}
class _MultipleSelectItemsState extends State<MultipleSelectItems> {
String selected = "First";
#override
Widget build(BuildContext context) {
return Container(
child: GestureDetector(
child: Column(
children: <Widget>[
SizedBox(
height: 40,
),
GestureDetector(
onTap: () {
setState(() {
selected = "First";
});
},
child: Container(
margin: EdgeInsets.only(left: 15, right: 15),
height:100,
width: double.maxFinite,
decoration: BoxDecoration(
color: selected == 'First' ? Colors.redAccent : Colors.lightBlueAccent,
),
child: ListTile(
title: Text(
'First',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 20,
fontFamily: 'WorksSansSemiBold',
fontWeight: FontWeight.bold,
),
),
),
),
),
Padding(padding: EdgeInsets.only(top: 20)),
GestureDetector(
onTap: () {
setState(() {
selected = "Second";
});
},
child: Container(
margin: EdgeInsets.only(left: 15, right: 15),
height:100,
width: double.maxFinite,
decoration: BoxDecoration(
color: selected == 'Second' ? Colors.redAccent : Colors.lightBlueAccent,
),
child: ListTile(
title: Text(
'Second',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 20,
fontFamily: 'WorksSansSemiBold',
fontWeight: FontWeight.bold,
),
),
),
),
),
Padding(padding: EdgeInsets.only(top: 20)),
GestureDetector(
onTap: () {
setState(() {
selected = "Third";
});
},
child: Container(
margin: EdgeInsets.only(left: 15, right: 15),
height:100,
width: double.maxFinite,
decoration: BoxDecoration(
color: selected == 'Third' ? Colors.redAccent : Colors.lightBlueAccent,
),
child: ListTile(
title: Text(
'Third',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 20,
fontFamily: 'WorksSansSemiBold',
fontWeight: FontWeight.bold,
),
),
),
),
),
SizedBox(
height: 40,
),
MaterialButton(
child: Text("Submit"),
color: Colors.blueGrey,
textColor: Colors.white,
onPressed: () {},
),
],
),
),
);
}
}
I am taking the requirement as you don't want to toggle, but to select multiple items. This is the solution.
In Flutter, creating a different StatefulWidget for the buttons, will be unique for every button, and when you select the buttons. And hitting each button will have unique informations only. I know it is little confusing but follow this, and you will understand.
class MultipleSelectItems extends StatefulWidget {
#override
_MultipleSelectItemsState createState() => _MultipleSelectItemsState();
}
class _MultipleSelectItemsState extends State<MultipleSelectItems> {
// This is responsible to crate your buttons
// Every button is created will be having it's unique instance only
// Means, if you hit one button, it won't effect another, and you can select
// multiple
// And you don't have to declare your buttons multiple times in the code
// Which is indeed bad way of coding :)
List<Widget> get listTileWidgets{
List<Widget> _widget = [SizedBox(height: 40.0)];
List<String> _buttonName = ['First', 'Second', 'Third', 'Fourth'];
// ListTileWidget is defined below in another StatefulWidget
_buttonName.forEach((name){
_widget.add(ListTileWidget(name: name));
_widget.add(SizedBox(height: 20.0));
});
return _widget;
}
#override
Widget build(BuildContext context) {
return Material(
child: Container(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: this.listTileWidgets
)
)
);
}
}
// This will accept name of the button which will be used to be given
// plus maintaining the uniqueness
class ListTileWidget extends StatefulWidget{
final String name;
ListTileWidget({Key key, this.name}):super(key:key);
#override
ListTileWidgetState createState() => ListTileWidgetState();
}
class ListTileWidgetState extends State<ListTileWidget>{
bool isTapped = false;
#override
Widget build(BuildContext context){
return GestureDetector(
onTap: () {
setState(() => isTapped = true);
},
child: Container(
margin: EdgeInsets.only(left: 15, right: 15),
height:100,
color: isTapped ? Colors.redAccent : Colors.lightBlueAccent,
width: double.maxFinite,
child: ListTile(
title: Text(
widget.name,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 20,
fontFamily: 'WorksSansSemiBold',
fontWeight: FontWeight.bold,
)
)
)
)
);
}
}
Result you will get is below:
I am sorry that, I have not added your "Submit" button. So in order to make that thing visible in your code, simply add this in your Column only, and you will be good to go:
Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
this.listTileWidgets,
SizedBox(height: 40),
MaterialButton(
child: Text("Submit"),
color: Colors.blueGrey,
textColor: Colors.white,
onPressed: () {},
)
]
)
That's pretty much it now.
I've got your answer. Changing the string variable to be an array can complete what you are looking to do. Then by checking if "First" or "Second" or "Third" is in the array we can determine what color the ListTile should be. Also when the ListTile is tapped we need to check if the array contains that string to determine if we are going to remove the string from the array (aka turning the color to blue) or if we need to add the string to the array (aka turning the color to red). Below I have included all of those changes to your class. Hope this answer helps! Comment if you have any questions
class MultipleSelectItems extends StatefulWidget {
#override
_MultipleSelectItemsState createState() => _MultipleSelectItemsState();
}
class _MultipleSelectItemsState extends State<MultipleSelectItems> {
var theSelected = ["First"];
#override
Widget build(BuildContext context) {
return Material(
child: Container(
child: GestureDetector(
child: Column(
children: <Widget>[
SizedBox(
height: 40,
),
GestureDetector(
onTap: () {
setState(() {
if(theSelected.contains("First")) {
theSelected.remove("First");
}
else {
theSelected.add("First");
}
});
},
child: Container(
margin: EdgeInsets.only(left: 15, right: 15),
height: 100,
width: double.maxFinite,
decoration: BoxDecoration(
color: theSelected.contains('First') ? Colors.redAccent : Colors.lightBlueAccent,
),
child: ListTile(
title: Text(
'First',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 20,
fontFamily: 'WorksSansSemiBold',
fontWeight: FontWeight.bold,
),
),
),
),
),
Padding(padding: EdgeInsets.only(top: 20)),
GestureDetector(
onTap: () {
setState(() {
if(theSelected.contains("Second")) {
theSelected.remove("Second");
}
else {
theSelected.add("Second");
}
});
},
child: Container(
margin: EdgeInsets.only(left: 15, right: 15),
height:100,
width: double.maxFinite,
decoration: BoxDecoration(
color: theSelected.contains('Second') ? Colors.redAccent : Colors.lightBlueAccent,
),
child: ListTile(
title: Text(
'Second',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 20,
fontFamily: 'WorksSansSemiBold',
fontWeight: FontWeight.bold,
),
),
),
),
),
Padding(padding: EdgeInsets.only(top: 20)),
GestureDetector(
onTap: () {
setState(() {
if(theSelected.contains("Third")) {
theSelected.remove("Third");
}
else {
theSelected.add("Third");
}
});
},
child: Container(
margin: EdgeInsets.only(left: 15, right: 15),
height:100,
width: double.maxFinite,
decoration: BoxDecoration(
color: theSelected.contains("Third") ? Colors.redAccent : Colors.lightBlueAccent,
),
child: ListTile(
title: Text(
'Third',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 20,
fontFamily: 'WorksSansSemiBold',
fontWeight: FontWeight.bold,
),
),
),
),
),
SizedBox(
height: 40,
),
MaterialButton(
child: Text("Submit"),
color: Colors.blueGrey,
textColor: Colors.white,
onPressed: () {},
),
],
),
),
),
);
}
}