Flutter, How to search instantly in sqflite database? - flutter

When I search for any poet it always gives me the first records. it does not show the exact record that I am searching for.
My TasksPage:
TextEditingController _searchInputController = TextEditingController();
var list = [];
var filteredList = [];
bool doItJustOnce = false;
void _filterList(value) {
setState(() {
filteredList = list
.where((text) => text.name.toLowerCase().contains(value.toLowerCase())).toList();
});}
The TextField through which I search the desired record
TextField(
onChanged: (value) {
setState(() {
// _filterList(value);
});
},
),
The FutureBuilder
FutureBuilder<List<Poets>>(
//we call the method, which is in the folder db file database.dart
future: DatabaseHelper.instance.getPoets(),
builder: (BuildContext context, AsyncSnapshot<List<Poets>> snapshot) {
if (snapshot.hasData) {
if (!doItJustOnce) {
//You should define a bool like (bool doItJustOnce = false;) on your state.
list = snapshot.data!;
filteredList = list;
doItJustOnce = !doItJustOnce; //this line helps to do just once.
}
return ListView.builder(
padding: EdgeInsets.symmetric(horizontal: 0, vertical: 7),
physics: BouncingScrollPhysics(),
reverse: false,
//Count all records
itemCount: snapshot.data!.length,
// itemCount: filteredList.length, // snapshot.data!.length, //filterLis.length,
//all the records that are in the Student table are passed to an item Poet item = snapshot.data [index];
itemBuilder: (BuildContext context, int index) {
Poets item = snapshot.data![index];
//delete one register for id
return Dismissible(
key: UniqueKey(),
background: Container(
color: Colors.red,
child: Padding(
padding: const EdgeInsets.fromLTRB(338, 30, 0, 0),
child: Text(
'Delete',
style: TextStyle(
color: Colors.white,
fontSize: 20,
fontWeight: FontWeight.bold),
),
),
),
onDismissed: (direction) {
setState(() {
DatabaseHelper.instance.remove(item.id);
});
},
//Now we paint the list with all the records, which will have a number, name, phone
child: Card(
elevation: 15.0,
color: Colors.white12,
child: Container(
decoration: BoxDecoration(
// color: Color.fromRGBO(64, 75, 96, .9,),
color: Colors.white70,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20.0),
topRight: Radius.circular(20.0),
bottomLeft: Radius.circular(20.0),
bottomRight: Radius.circular(20.0),
),
),
child: ListTile(
leading: CircleAvatar(
child: Text(item.id.toString()),
backgroundColor: Color.fromRGBO(
64,
75,
96,
.9,
),
foregroundColor: Colors.white,
),
title: Text(
item.name,
style: TextStyle(fontWeight: FontWeight.bold),
),
subtitle: Text(item.f_name),
trailing: Text(item.serial_no.toString()),
//If we press one of the cards, it takes us to the page to edit, with the data onTap:
//This method is in the file add_editclient.dart
onTap: () {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => AddEditClient(
true,
//Here is the record that we want to edit
poet: item,
)));
},
// onLongPress: () {
// setState(() {
// DatabaseHelper.instance.remove(item.id);
// });
// },
),
),
),
);
},
);
} else {
return Center(child: CircularProgressIndicator());
}
},
),
My Question is How to search in sqflite database,please help me.

you can use this sqflite package that will make your task very easy on the query side. you can find an example on its repository(GitHub).
or you can try this,
Future getSearch async(){try {
var mapList = await DbHelper.getTaskDetail(
table: 'CustomerDetails', where: 'name= joe');
if (mapList != null && mapList.isNotEmpty) {
yourlist.clear()
yourlist
.addAll(mapList.map((e) => yourmodel.fromJson(e)).toList());
}
}catch(Exception e){
}}
static Future<List<Map<String, dynamic>>?> getTaskDetail(
{required String table,
String? query,
String? orderBy,
String? where,
int? limit}) async {
final db = await instance.taskDatabase;
return db?.query(table, orderBy: orderBy, limit: limit, where: where);}
put your result in setState().

Related

Flutter User Filter

List<User> allusers = [];
List<User> selectedUsers = [];
List<User> selectableUsers = allusers - selectedUsers
Is anyone able to help me how to get selectableUsers list here? I am trying to subtract the selected users from all users so that the search function eliminates selectedUsers?
I want to filter users based on the selection.
View for getting and searching users. Issue is that selected user gets into the search once again. Expected behavior is that "selected" users shouldn't come up in the "selectable" user list.
class SearchGroup extends StatefulWidget {
const SearchGroup({Key? key}) : super(key: key);
#override
State<SearchGroup> createState() => _SearchGroupState();
}
class _SearchGroupState extends State<SearchGroup> {
final TextEditingController _searchController = TextEditingController();
List<User> _users = [];
List<User> _selectedUsers = [];
List<User> _selectableUsers = [];
#override
void initState() {
super.initState();
var setAllUsers = Set.from(_users);
var setSelectedUsers = Set.from(_selectedUsers);
_selectableUsers
.addAll(List.from(setAllUsers.difference(setSelectedUsers)));
}
_clearSearch() {
WidgetsBinding.instance
.addPostFrameCallback((_) => _searchController.clear());
setState(() => _selectableUsers = []);
}
#override
void dispose() {
super.dispose();
_searchController.dispose();
}
#override
Widget build(BuildContext context) {
final currentUserUid =
Provider.of<UserProvider>(context).getUser?.uid ?? '';
return Scaffold(
appBar: AppBar(
title: TextField(
controller: _searchController,
hintText: 'Search & select users by fullname',
suffixIcon: _selectableUsers.isEmpty
? Icon(Icons.search,
size: 20.0, color: Color.fromARGB(255, 235, 228, 228))
: IconButton(
iconSize: 15,
icon: Icon(CupertinoIcons.clear_circled_solid),
onPressed: _clearSearch,
color: Color.fromARGB(255, 235, 228, 228)),
),
onSubmitted: (input) async {
if (input.trim().isNotEmpty) {
List<User> users =
await Provider.of<DatabaseService>(context, listen: false)
.searchUsers(currentUserUid, input);
_selectedUsers.forEach((user) => users.remove(user));
_selectableUsers.forEach((user) => users.remove(user));
setState(() {
_selectableUsers = users;
});
}
}),
body: Column(
children: [
Padding(
padding: const EdgeInsets.only(left: 5.0),
child: Container(
width: double.infinity,
height: 100,
child: ListView.builder(
itemCount: _selectedUsers.length,
scrollDirection: Axis.horizontal,
itemBuilder: (BuildContext context, int index) {
User selectedUser = _selectedUsers[index];
return Container(
margin: EdgeInsets.all(10),
width: 60,
height: 60,
decoration: BoxDecoration(shape: BoxShape.circle),
child: GestureDetector(
onTap: () {
_selectedUsers.remove(selectedUser);
_selectableUsers.insert(0, selectedUser);
setState(() {});
},
child: Stack(
alignment: AlignmentDirectional.bottomEnd,
children: [
CircleAvatar(
radius: 60,
child: CachedNetworkImage(
imageUrl: selectedUser.profileImageUrl,
imageBuilder: (context, imageProvider) =>
Container(
height: 60,
width: 60,
decoration: BoxDecoration(
borderRadius:
BorderRadius.all(Radius.circular(100)),
image: DecorationImage(
image: imageProvider,
fit: BoxFit.cover,
),
),
),
),
),
Positioned(
top: 3,
child: Icon(
Icons.remove_circle,
size: 20,
color: Colors.red,
),
),
],
),
),
);
}),
),
),
Expanded(
child: ListView.separated(
separatorBuilder: (BuildContext context, int index) {
return const Divider(thickness: 1.0);
},
itemCount: _selectedUsers.length + _selectableUsers.length,
itemBuilder: (BuildContext context, int index) {
if (index < _selectedUsers.length) {
User selectedUser = _selectedUsers[index];
return ListTile(
leading: CircleAvatar(
radius: 28,
child: CachedNetworkImage(
imageUrl: selectedUser.profileImageUrl,
imageBuilder: (context, imageProvider) => Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(30)),
image: DecorationImage(
image: imageProvider, fit: BoxFit.cover),
),
),
),
),
title: Text(
selectedUser.fullname,
style: TextStyle(fontSize: 14),
),
trailing: Icon(Icons.check_circle, color: blueColor),
onTap: () {
_selectedUsers.remove(selectedUser);
_selectableUsers.insert(0, selectedUser);
setState(() {});
},
);
} else {
int userIndex = index - _selectedUsers.length;
User user = _selectableUsers[userIndex];
return ListTile(
leading: CircleAvatar(
radius: 28,
child: CachedNetworkImage(
imageUrl: user.profileImageUrl,
imageBuilder: (context, imageProvider) => Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(50)),
image: DecorationImage(
image: imageProvider, fit: BoxFit.cover),
),
),
),
),
title: Text(
user.fullname,
style: TextStyle(fontSize: 14),
),
trailing: Icon(
CupertinoIcons.circle,
color: Colors.grey,
),
onTap: () {
_selectedUsers.add(user);
_selectableUsers.remove(user);
setState(() {});
},
);
}
},
),
),
],
),
);
}
}
Try this:
onSubmitted: (input) async {
if (input.trim().isNotEmpty) {
List<User> users = await Provider.of<DatabaseService>(context, listen: false).searchUsers(currentUserUid, input);
var setAllUsers = Set.from(users);
var setSelectedUsers = Set.from(selectedUsers);
setState(() {
selectableUsers.addAll(List.from(setAllUsers.difference(setSelectedUsers)));
});
}
}),
You also need add Equatable package to your user model class, lets assume this is your model
class:
class User extends Equatable {// <-- add this
final String fullName;
final String avatar;
final int phone;
const User({
required this.fullName,
required this.avatar,
required this.phone,
});
#override
List<Object?> get props => [fullName, avatar, phone];// <-- add this
}
A basic way of doing will be checking each item like
List<User> allusers = [];
List<User> selectedUsers = [];
List<User> selectableUsers = [];
for (final user in allusers) {
if (!selectableUsers.contains(user)) selectableUsers.add(user);
}

How to pass user input into StreamBuilder and use that snapshot inside GestureDetector?

I wanted to do an update function where user can input a tracking number and update a parcel data. The doc(trackingnumber) will be taken from user inputted trackingnumber before getting the snapshot from StreamBuilder. After the button is clicked(gesturedetector), the function will compare the snapshot data with user input before the update is executed. I'm still new to flutter. Here's my effort so far.
GestureDetector(
onTap: () {
StreamBuilder<ParcelModel>(
stream:
ParcelService(trackingNumber: trackingNumberController.text)
.singleparcel,
builder: (context, snapshot) {
ParcelModel? singleparcel = snapshot.data;
return GestureDetector(
onTap: () async {
if (singleparcel?.parcelNumber ==
int.parse(parcelNumberController.text) &&
singleparcel?.trackingNumber ==
trackingNumberController.text) {
await ParcelService(
trackingNumber: trackingNumberController.text)
.executeRetrieveParcel(
trackingNumberController.text,
retrieverNameController.text,
studentIDController.text,
retrieverPhoneController.text,
int.parse(parcelNumberController.text),
singleparcel?.studentName,
singleparcel?.dateArrived);
Fluttertoast.showToast(
msg: "Parcel retrieved successfully :)");
setState(() => loading = false);
} else if (singleparcel?.parcelNumber !=
int.parse(parcelNumberController.text)) {
Fluttertoast.showToast(msg: "Incorrect Parcel Number!");
setState(() => loading = false);
} else {
setState(() => loading = false);
}
});
});
},
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 25.0),
child: Container(
padding: EdgeInsets.all(20),
decoration: BoxDecoration(
color: Color(0xffA97575),
borderRadius: BorderRadius.circular(12),
),
child: Center(
child: Text(
'Update & Notify Student',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
fontSize: 18,
),
),
),
),
),
),

Flutter - lost connection error when updating an array

I am trying to update an array in flutter. I found out that it is not possible directly.
I have understood that I must first create a list[], transfer my document fields value into the created list, then I must update the information in my list and only then can I can update my Firebase Firestore array with my updated list.
My code is below. Problem is, when I use my function the simulator crashes and I am getting the error lost connection.
I am looking for any advice. Many thanks.
List listTest =[];
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
class DetailScreen_CheckList_V3 extends StatefulWidget {
//final Map listName;
final docID;
const DetailScreen_CheckList_V3( this.docID,{
Key key}) : super(key: key);
#override
_DetailScreen_CheckList_V3State createState() => _DetailScreen_CheckList_V3State(docID);
}
class _DetailScreen_CheckList_V3State extends State<DetailScreen_CheckList_V3> {
// Map listName;
var docID;
_DetailScreen_CheckList_V3State( //this.listName,
this.docID);
#override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
appBar: AppBar(
title: Text('Your list items'),
leading:
InkWell(
child:
Icon(Icons.fast_rewind_outlined),
onTap: () {
Navigator.pop(context);
},),
),
body: MyBody(context, docID),
floatingActionButton: FloatingActionButton(
onPressed: () {
showAddNewItemToAList();
setState(() {});
},
child: const Icon(Icons.add),
backgroundColor: Colors.blue,
),
floatingActionButtonLocation: FloatingActionButtonLocation.endFloat,
);
}
Widget MyBody(BuildContext context, var docID) {
return SingleChildScrollView(
child: Column(
children: [
Container(
height: MediaQuery
.of(context)
.size
.height / 1.4,
width: MediaQuery
.of(context)
.size
.width,
child: StreamBuilder<DocumentSnapshot>(
stream: FirebaseFirestore.instance
.collection('Users')
.doc(FirebaseAuth.instance.currentUser.uid)
.collection('lists')
.doc(docID)
.snapshots(),
builder: (BuildContext context,
AsyncSnapshot<DocumentSnapshot> snapshot) {
if (!snapshot.hasData) {
return Center(
child: CircularProgressIndicator(),
);
} else {
DocumentSnapshot data = snapshot.requireData;
return ListView.builder(
itemCount: data['allItems'].length,
itemBuilder: (context, index) {
return Card(
child:
InkWell(
child: ListTile(
leading: data['allItems'][index]['itemChecked'] ==
'Yes' ? Icon(
Icons.check_box,
color: Colors.blue,) : Icon(
Icons.check_box_outline_blank),
title:
Text(
(data['allItems'][index]['itemName'])),
onTap: () {
String checked = data['allItems'][index]['itemChecked'];
String myItemName = data['allItems'][index]['itemName'];
String myListName = data['listName'];
listTest.addAll(data['allItems']);
print('before');
print (listTest);
setState(() {
if (checked == 'Yes') {
checked = 'No';
listTest[index]['itemChecked'] = checked;
print('after');
print(listTest);
myTest(myListName,index);
}
else {
checked = 'Yes';
listTest[index]['itemChecked'] = checked;
print('after');
print(listTest);
myTest(myListName,index);
}
});
}
),
onTap: () {
},)
);
});
}
}))
]),
);
}
void showAddNewItemToAList() {
TextEditingController _noteField = new TextEditingController();
showDialog(
context: context,
builder: (BuildContext context) {
return CustomAlertDialog(
content: Container(
width: MediaQuery
.of(context)
.size
.width / 1.3,
height: MediaQuery
.of(context)
.size
.height / 4,
child: Column(
children: [
TextField(
controller: _noteField,
maxLines: 4,
decoration: InputDecoration(
border: const OutlineInputBorder(
borderSide:
const BorderSide(color: Colors.black, width: 1.0),
),
),
),
SizedBox(height: 10),
Material(
elevation: 5.0,
borderRadius: BorderRadius.circular(25.0),
color: Colors.white,
child: MaterialButton(
minWidth: MediaQuery
.of(context)
.size
.width / 1.5,
onPressed: () {
if (_noteField.text != '') {
setState(() {
AddObjectItemToArray(_noteField.text);
});
Navigator.of(context).pop();
}
else {
return;
}
},
padding: EdgeInsets.fromLTRB(10.0, 15.0, 10.0, 15.0),
child: Text(
'Add Item',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 20.0,
color: Colors.black,
fontWeight: FontWeight.bold,
),
),
),
)
],
),
),
);
});
}
Future AddObjectItemToArray(newItemName,) async {
AllItems _allItems = AllItems(newItemName, 'No');
FirebaseFirestore.instance
.collection('Users')
.doc(FirebaseAuth.instance.currentUser.uid)
.collection('lists')
.doc(docID).update({
"allItems": FieldValue.arrayUnion([_allItems.toMap()])
},);
}
Future ModifyCheckedStatus(newItemName, newCheckedStatus,
currentListName) async {
AllItems _allItems = AllItems(newItemName, newCheckedStatus);
FirebaseFirestore.instance
.collection('Users')
.doc(FirebaseAuth.instance.currentUser.uid)
.collection('lists')
.doc(docID).update(
{'listName': currentListName,
"allItems": ([_allItems.toMap()]),
}, //SetOptions(merge: true),
);
}
Future myTest(currentListName,index) async {
FirebaseFirestore.instance
.collection('Users')
.doc(FirebaseAuth.instance.currentUser.uid)
.collection('lists')
.doc(docID).set(
{'listName': currentListName,
"allItems": [listTest],
},//SetOptions(merge: true)
);
}
}
So I guess your AddObjectToArray method is working well, you are correctly using arrayUnion. But then the ModifyCheckStatus is not working as expected because you are still using arrayUnion.
ArrayUnion adds an object to the array. What you have to do in ModifyCheckStatus is to extract all items, toggle the checked status of a particular item, then update the entire items list in Firebase (instead of using arrayUnion). This should only be in ModifyCheckStatus.
Something like the following
Future ModifyCheckedStatus(newItemName, newCheckedStatus,
currentListName) async {
// TODO: obtain all items
// changed the checked status of a particular item
allItems.where((i) => i.name == item.name).forEach((i) {
i.checked = !i.checked;
});
// update as you did
FirebaseFirestore.instance
.collection('Users')
.doc(FirebaseAuth.instance.currentUser.uid)
.collection('lists')
.doc(docID)
.update({"allItems": allItems});
}

Flutter FutureBuilder calling function continuously

I have simple function which is calling data from firestore and filtering data. But issue is my futurebuilder keeps on loader situation (Data is called successfully i can see in console but now showing in future) I think its because my fucntion is calling in loop or something i have try to print something in my function which indicates me that my function is not stopping and thats why i think my futureBuilder keeps on loading.
My code
Future<List> getCustomerList() async {
print('calling');
String uUid1 = await storage.read(key: "uUid");
String uName1 = await storage.read(key: "uName");
String uNumber1 = await storage.read(key: "uNumber");
setState(() {
uUid = uUid1;
uName = uName1;
uNumber = uNumber1;
});
CollectionReference _collectionRef =
FirebaseFirestore.instance.collection('Customers');
QuerySnapshot querySnapshot = await _collectionRef.get();
// Get data from docs and convert map to List
List allData = querySnapshot.docs
.where((element) => element['sellerUID'] == uUid)
.map((doc) => doc.data())
.toList();
double gGive = 0;
double gTake = 0;
double gCal = 0;
for (int i = 0; i < allData.length; i++) {
// print(allData[i]);
// print('give ${double.parse(allData[i]['give'].toString()) }');
// print('take ${double.parse(allData[i]['take'].toString()) }');
double.parse(allData[i]['give'].toString()) -
double.parse(allData[i]['take'].toString()) >
0
? gGive += double.parse(allData[i]['give'].toString()) -
double.parse(allData[i]['take'].toString())
: gTake += double.parse(allData[i]['give'].toString()) -
double.parse(allData[i]['take'].toString());
}
// print(gGive);
// print(gTake);
setState(() {
Gtake = gGive.toString().replaceAll("-", "");
Ggive = gTake.toString().replaceAll("-", "");
});
if (greenBox) {
var check = allData.where((i) => i['take'] > i['give']).toList();
return check;
} else if (redBox) {
var check = allData.where((i) => i['give'] > 1).toList();
return check;
} else {
return allData;
}
}
And my futureBuilder look like this
Expanded(
child: Container(
height: Height * 0.5,
child: FutureBuilder(
future: getCustomerList(),
builder: (context, snapshot) {
if (snapshot.hasData) {
list = snapshot.data;
return SingleChildScrollView(
child: Column(
children: [
Container(
height: Height * 0.5,
child: ListView.builder(
shrinkWrap: true,
itemCount: list.length,
itemBuilder:
(BuildContext context,
int index) {
var showThis = list[index]
['give'] -
list[index]['take'];
return list[index]
['customerName']
.toString()
.contains(searchString)
? GestureDetector(
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
CustomerData(
data: list[
index])),
);
},
child: Padding(
padding:
const EdgeInsets
.only(
left: 13,
right: 13),
child: Container(
decoration:
BoxDecoration(
border: Border(
top: BorderSide(
color: Colors
.grey,
width:
.5)),
),
child: Padding(
padding:
const EdgeInsets
.all(
13.0),
child: Row(
mainAxisAlignment:
MainAxisAlignment
.spaceBetween,
children: [
Row(
children: [
CircleAvatar(
child:
Text(
list[index]['customerName'][0]
.toString(),
style:
TextStyle(fontFamily: 'PoppinsBold'),
),
backgroundColor:
Color(0xffF7F9F9),
),
SizedBox(
width:
20,
),
Text(
list[index]['customerName']
.toString(),
style: TextStyle(
fontFamily:
'PoppinsMedium'),
),
],
),
Text(
'RS ${showThis.toString().replaceAll("-", "")}',
style: TextStyle(
fontFamily:
'PoppinsMedium',
color: list[index]['give'] - list[index]['take'] <
0
? Colors.green
: Colors.red),
),
],
),
),
),
),
)
: Container();
},
),
)
],
),
);
} else
return Center(
heightFactor: 1,
widthFactor: 1,
child: SizedBox(
height: 70,
width: 70,
child: CircularProgressIndicator(
strokeWidth: 2.5,
),
),
);
}),
),
),
I am damn sure its because futurebuilder keeps calling function which is returning data but because of keeps calling functions my Futurebuilder keeps showing loading.
You should not call setState inside the future that you are giving to the FutureBuilder.
The state actualization will cause the FutureBuilder to re-build. Meaning triggering the future again, and ... infinite loop !

Flutter Calendar - Showing custom data on days not works well

I´m using flutter with a calendar carousel (https://pub.dev/packages/flutter_calendar_carousel)
For each day for which there is an entry in the database, I want to display an icon in the calendar. What is the best way to do this?
That´s my current code:
Please check the part with the customDayBuilder
class _CalendarScreenState extends State<CalendarScreen> {
DateTime _currentDate;
openNewEntryDialog(BuildContext context, date) {
setState(() {
_currentDate = date;
});
showBarModalBottomSheet(
context: context,
builder: (BuildContext context, scrollController) {
return AddCalendarEntry(
scrollController: scrollController,
currentDate: _currentDate,
);
});
}
#override
Widget build(BuildContext context) {
final calendarEntriesData = Provider.of<CalendarEntries>(context);
void initState() {
_currentDate = widget._currentDate;
super.initState();
}
dayPressed(date, events) {
this.setState(() => _currentDate = date);
}
return Material(
child: CupertinoPageScaffold(
backgroundColor: Colors.white,
navigationBar: CupertinoNavigationBar(
trailing: IconButton(
icon: Icon(Icons.add),
color: Colors.white,
onPressed: () => openNewEntryDialog(context, DateTime.now())),
middle: Text("Juni 2020",
style: Theme.of(context).appBarTheme.textTheme.headline1),
backgroundColor: Theme.of(context).primaryColor,
),
child: Padding(
padding: const EdgeInsets.only(left: 15.0, right: 15.0),
child: Column(
children: <Widget>[
Expanded(
child: CalendarCarousel(
markedDateIconBorderColor: Theme.of(context).primaryColor,
weekdayTextStyle:
TextStyle(color: Theme.of(context).primaryColor),
daysTextStyle:
TextStyle(color: Theme.of(context).primaryColor),
todayButtonColor: Theme.of(context).primaryColor,
weekendTextStyle: TextStyle(color: Colors.black),
locale: "de",
selectedDayButtonColor: Colors.grey.shade100,
selectedDateTime: _currentDate,
headerTextStyle: TextStyle(
color: Theme.of(context).primaryColor, fontSize: 25),
onDayPressed: (DateTime date, List<Event> events) =>
dayPressed(date, events),
onDayLongPressed: (DateTime date) =>
openNewEntryDialog(context, date),
customDayBuilder: (bool isSelectable,
int index,
bool isSelectedDay,
bool isToday,
bool isPrevMonthDay,
TextStyle textStyle,
bool isNextMonthDay,
bool isThisMonthDay,
DateTime day) {
return FutureBuilder(
future: calendarEntriesData.getAll(),
builder: (BuildContext context,
AsyncSnapshot<List<CalendarEntry>> snapshot) {
if (!snapshot.hasData ||
snapshot.connectionState ==
ConnectionState.waiting) {
return Center(
child: CircularProgressIndicator(),
);
} else {
for (final entry in snapshot.data) {
var temp =
DateTime.parse(entry.dateTime).toUtc();
var d1 = DateTime.utc(
temp.year, temp.month, temp.day);
var d2 = DateTime.utc(
day.year, day.month, day.day);
if (d2.compareTo(d1) == 0) {
return Center(
child: Icon(Icons.local_airport));
}
}
}
});
},
),
),
Expanded(
flex: 1,
child: Container(
margin: EdgeInsets.only(top: 35),
child: FutureBuilder<List<CalendarEntry>>(
future: calendarEntriesData
.getCurrentMonthEntries(_currentDate != null
? _currentDate
: DateTime.now()),
builder: (BuildContext context,
AsyncSnapshot<List<CalendarEntry>> snapshot) {
if (!snapshot.hasData ||
snapshot.connectionState ==
ConnectionState.waiting) {
return Center(
child: CircularProgressIndicator(),
);
} else {
return Container(
height: 100,
child: ListView.builder(
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context,
int index) {
return ListTile(
title: Text(snapshot
.data[index].servicePartner
.toString()),
subtitle: snapshot.data[index]
.dateTime ==
null
? Text("Unbekannt")
: Text(DateFormat(
"dd.MM.yyyy")
.format(DateTime.parse(
snapshot.data[index]
.dateTime))),
trailing: Text((snapshot
.data[index]
.minutes /
60)
.toString() +
" Stunden"),
);
}));
}
})))
],
),
)));
}
}
How you can see, I´m using a FutureBuilder to check all database entries. And if a day matches, I show an Icon on this day. This works in general, but
I have some errors on the screen
The performance is very bad, because there is some flickering..for each click on another day the widget renders completely. I don´t want this.
How could I improve my code? How could I do this better?
Thanks so much for your help!
Please use the button and button style for this to generate a clickable.
Also resolved your issue.
Widget renderDay(
bool isSelectable,
int index,
bool isSelectedDay,
//bool isToday,
bool isPrevMonthDay,
TextStyle? textStyle,
TextStyle defaultTextStyle,
bool isNextMonthDay,
bool isThisMonthDay,
DateTime now,
) {
final EventList<T>? markedDatesMap = widget.markedDatesMap;
List<Event> markedEvents =
widget.markedDatesMap!.getEvents(now) as List<Event>? ?? [];
return Container(
child: ElevatedButtonTheme(
data: ElevatedButtonThemeData(
style: ButtonStyle(
side: MaterialStateProperty.resolveWith<BorderSide>((states) =>
BorderSide(
color: ColorConstants.WHITE)),
backgroundColor: MaterialStateProperty.resolveWith<Color>(
(states) => markedEvents.length > 0 &&
!isPrevMonthDay &&
!isNextMonthDay
? _getStatusColor(
markedEvents[0].dayStatus!.toLowerCase())
: isSelectedDay && widget.selectedDayButtonColor != null
? widget.selectedDayButtonColor
: widget.dayButtonColor,
),
shape: MaterialStateProperty.resolveWith<OutlinedBorder>((_) {
return RoundedRectangleBorder(
borderRadius: BorderRadius.circular(80));
}),
textStyle: MaterialStateProperty.resolveWith<TextStyle>(
(states) =>
TextStyle(color: ColorConstants.BUTTON_BG_COLOR)),
padding: MaterialStateProperty.all(
EdgeInsets.all(widget.dayPadding),
),
),
),
child: ElevatedButton(
onPressed:
widget.disableDayPressed ? null : () => _onDayPressed(now),
child: Stack(
children: <Widget>[
getDayContainer(
isSelectable,
index,
isSelectedDay,
// isToday,
isPrevMonthDay,
textStyle,
defaultTextStyle,
isNextMonthDay,
isThisMonthDay,
now),
],
),
),
),
);
}