Table Calendar won't change focusedDay - flutter

I'm using table_calendar package to display a calendar on a page.
I want the user to be able to chose a date from the calendar, but when tapping on a date, the focusedDay won't change, so it always stays on the default focusedDay.
I tried to search the docs, and I can't figure out what is wrong, from the docs it seems like it should work fine.
This is what I have for the CalendarWidget:
TableCalendar(
focusedDay: _focusedDay,
firstDay: DateTime.now(),
lastDay: DateTime.utc(2030, 1, 1),
calendarFormat: CalendarFormat.month,
headerStyle: HeaderStyle(
formatButtonVisible: false,
titleCentered: true,
rightChevronIcon: Icon(
Icons.chevron_right,
size: 16,
color: Colors.grey,
),
leftChevronIcon: Icon(
Icons.chevron_left,
size: 16,
color: Colors.grey,
),
),
onDaySelected: (selectedDay, focusedDay) {
setState(() {
_selectedDay = selectedDay;
_focusedDay = focusedDay;
});
},
),
This is inside a stateful widget, and I have _focusdDay as a variable in that class, which I update.
The TableCalendar is of course inside the build function of that class.

Don't forget to define the selectedDayPredicate in your TableCalendar:
TableCalendar(
...
selectedDayPredicate: (day) =>isSameDay(day, selectedDay),
...
)
The widget will use this to find out which day is the selected day

Instead of Using this , You can Use DatePicker and Redesign it by Yourself
here is the Example :
onTap: () async {
DateTime newSelectedDate =
await showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime.now(),
lastDate: DateTime(2100),
builder: (BuildContext context,
Widget child) {
return Theme(
data: ThemeData.dark().copyWith(
colorScheme: ColorScheme.dark(
primary: Colors.pink,
onPrimary: Colors.white,
surface: Colors.white,
onSurface: Colors.black,
),
dialogBackgroundColor:
Colors.grey[200],
),
child: child,
);
});
if (newSelectedDate != null) {
setState(() {
_selectedDate = newSelectedDate;
final DateFormat formatter =
DateFormat('yyyy-MM-dd');
formattedSelectedDate =
formatter.format(_selectedDate);
});
}
},

Related

Flutter Stream listen does not work properly

What I want to do is listening to a stream which contains Lists of Events for each day of month.
I need this for my TableCalendar Widget
I want to count each Event of each list of the stream and display it in the calendar.
For this I wrote this function:
countEvents(DateTime datetime) {
eventBloc.getEventsOfDay(datetime).listen((event) {
counter = event.length;
});
}
This is where I execute the function (in markerBuilder):
StreamBuilder<List<Event>>(
stream: selectedEvents,
builder: (context, snapshot) {
if (snapshot.hasData) {
final events = snapshot.data;
groupEvents(allEventsList);
return Column(children: [
Card(
clipBehavior: Clip.antiAlias,
margin: const EdgeInsets.all(10),
elevation: 5,
child: TableCalendar(
firstDay: DateTime.utc(1970, 01, 01),
lastDay: DateTime.utc(2999, 12, 31),
focusedDay: _selectedDay,
locale: 'en_US',
onPageChanged: (focusedDay) {
_focusedDay = focusedDay;
},
selectedDayPredicate: (day) {
return isSameDay(_selectedDay, day);
},
headerStyle: HeaderStyle(
decoration: BoxDecoration(
color: AppColors.red,
),
headerMargin: const EdgeInsets.only(bottom: 10),
),
calendarStyle: CalendarStyle(),
calendarBuilders: CalendarBuilders(
markerBuilder: ((context, day, events) {
countEvents(day);
return Container(
width: 20,
height: 15,
decoration: BoxDecoration(
color: AppColors.red,
borderRadius: BorderRadius.circular(4.0)),
child: Text(counter.toString()),
);
})),
//Day Changed
onDaySelected: (DateTime selectDay, DateTime focusDay) {
setState(() {
_selectedDay = selectDay;
_focusedDay = focusDay;
selectedEvents =
eventBloc.getEventsOfDay(_selectedDay);
});
//print(_focusedDay);
},
startingDayOfWeek: StartingDayOfWeek.monday,
eventLoader: getEventsForDay,
),
counter is a global variable for the class
I used the debugger and it seems like the listen function is skipped all the time..
Thank you for your help!

Validating Date Time Picker in flutter. (From Date selection date to To Date selection)

I want to validating from date selection date to To date selction
date. I selected 17th July 2022 in FromDate and ToDate selection time
only show 4 days(17,18,19,20) how i show only 7 past dates in ToDate
Picker in flutter.
DateTime fromDate = DateTime.now();
TimeOfDay fromTime = TimeOfDay.now();
String selectedFromDateTime;
String selectedToDateTime;
DateTime toDate = DateTime.now();
TimeOfDay toTime = TimeOfDay.now();
Future<void> _showFromDateTimePicker() async {
final DateTime datePicked = await showDatePicker(
context: context,
initialDate: fromDate,
firstDate: DateTime(1900),
lastDate: DateTime.now(),builder: (context, child) {
return Theme(
data: ThemeData(
splashColor: AppTheme.card_bg,
colorScheme: ColorScheme.light(
primary: AppTheme.card_bg,
onSecondary: Colors.black,
onPrimary: Colors.white,
surface: Colors.black,
onSurface: Colors.black,
secondary: Colors.black),
dialogBackgroundColor: Colors.white,
),
child: child ?? Text(""),
);
},);
if (datePicked != null) {
final hour = fromTime.hour.toString().padLeft(2, "0");
final minute = fromTime.minute.toString().padLeft(2, "0");
final TimeOfDay timePicked =
await showTimePicker(context: context, initialTime: fromTime,builder: (context, child) {
return Theme(
data: ThemeData(
splashColor: AppTheme.card_bg,
colorScheme: ColorScheme.light(
primary: AppTheme.card_bg,
onSecondary: Colors.black,
onPrimary: Colors.white,
surface: Colors.white,
onSurface: Colors.black,
secondary: Colors.black),
dialogBackgroundColor: Colors.white,
),
child: child ?? Text(""),
);
},);
if (timePicked != null) {
setState(() {
selectedFromDateTime =
"${DateFormat("yyyy-MM-dd").format(datePicked)} $hour:$minute" +
":00";
});
}
}
}
Future<void> _showToDateTimePicker() async {
final DateTime datePicked = await showDatePicker(
context: context,
initialDate: toDate,
firstDate: DateTime.now(),
lastDate: DateTime.now(),
builder: (context, child) {
return Theme(
data: ThemeData(
splashColor: AppTheme.card_bg,
colorScheme: ColorScheme.light(
primary: AppTheme.card_bg,
onSecondary: Colors.black,
onPrimary: Colors.white,
surface: Colors.black,
onSurface: Colors.black,
secondary: Colors.black),
dialogBackgroundColor: Colors.white,
),
child: child ?? Text(""),
);
},
);
if (datePicked != null) {
final hour = toTime.hour.toString().padLeft(2, "0");
final minute = toTime.minute.toString().padLeft(2, "0");
final TimeOfDay timePicked = await showTimePicker(
context: context,
initialTime: toTime,
builder: (context, child) {
return Theme(
data: ThemeData(
splashColor: AppTheme.card_bg,
colorScheme: ColorScheme.light(
primary: AppTheme.card_bg,
onSecondary: Colors.black,
onPrimary: Colors.white,
surface: Colors.white,
onSurface: Colors.black,
secondary: Colors.black),
dialogBackgroundColor: Colors.white,
),
child: child ?? Text(""),
);
},
);
if (timePicked != null) {
setState(() {
selectedToDateTime =
"${DateFormat("yyyy-MM-dd").format(datePicked)} $hour:$minute" +
":00";
});
}
}
}
It's quite easy to do, you just need to subtract 7 days from today.
final sevenDaysBeforeToday =DateTime.now().subtract(Duration(days: 7));
and change firstDate to sevenDaysBeforeToday of showDatePicker
firstDate: sevenDaysBeforeToday,

How to change header formatting in Flutter table_calendar package

I have the following calendar and code. How can I have the month be only 3 letters eg Nov 2021 instead of November 2021.
Container(
height: MediaQuery.of(context).size.height*0.3,
// width: MediaQuery.of(context).size.width*0.3,
color: Colors.white,
child: TableCalendar(
headerStyle: HeaderStyle(
titleTextStyle: TextStyle(fontSize: 12)
),
shouldFillViewport: true,
rowHeight:MediaQuery.of(context).size.height*0.02,
firstDay: DateTime.utc(2010, 10, 16),
lastDay: DateTime.utc(2030, 3, 14),
focusedDay: DateTime.now(),
onDaySelected: (selectedDay, focusedDay) {
if (!isSameDay(_selectedDay, selectedDay)) {
// Call `setState()` when updating the selected day
setState(() {
_selectedDay = selectedDay;
_focusedDay = focusedDay;
});
}
}
),
),
I achieved a responsive table with the customisation I wanted using this code:
Container(
height: MediaQuery.of(context).size.height*0.3,
color: Colors.white,
child: TableCalendar(
calendarStyle: CalendarStyle(
todayTextStyle: TextStyle(fontSize: MediaQuery.of(context).size.width*0.008,color: Colors.white),
weekendTextStyle: TextStyle(fontSize: MediaQuery.of(context).size.width*0.008),
outsideTextStyle: TextStyle(fontSize: MediaQuery.of(context).size.width*0.008),
defaultTextStyle: TextStyle(
fontSize: MediaQuery.of(context).size.width*0.008
)
) ,
headerStyle: HeaderStyle(
titleCentered: true,
titleTextFormatter: (date, locale) => DateFormat.yMMM(locale).format(date),
formatButtonVisible: false,
titleTextStyle: TextStyle(fontSize: MediaQuery.of(context).size.width*0.007)
),
shouldFillViewport: true,
rowHeight:MediaQuery.of(context).size.height*0.02,
firstDay: DateTime.utc(2010, 10, 16),
lastDay: DateTime.utc(2030, 3, 14),
focusedDay: DateTime.now(),
onDaySelected: (selectedDay, focusedDay) {
if (!isSameDay(_selectedDay, selectedDay)) {
// Call `setState()` when updating the selected day
setState(() {
_selectedDay = selectedDay;
_focusedDay = focusedDay;
});
}
}
),
),
as new table_calender 3.0.8 to disable two weeks/format button you can set
availableCalendarFormats: const {
CalendarFormat.month : 'Month'
}
and to center the title you also need to set up
headerStyle: HeaderStyle(
titleCentered: true
)
To remove 2 weeks use different calendarFormat
To change Header titile use titleTextFormatter
And finally play with PositionedOffset to control positions.
** Everything that is possible to change is documented here: https://pub.dev/documentation/table_calendar/latest/table_calendar/table_calendar-library.html

Get the value of selected time and day using a DatePicker

I am trying to get the value of the selected time and date when the Datepicker is shown.
I achieved the UI and shown the date and time picker when onTap.
The problem is that I can get the value after selected. The idea would be to render it somewhere in the screen as follows:
time selected: .....
date selected: .....
This is my code regarding the popUp of the DayPicker and the function that gets the value:
function and variables:
DateTime? _dateTime;
TimeOfDay _time = TimeOfDay(hour: 7, minute: 15);
void _selectTime() async {
final newTime = await showTimePicker(
context: context,
initialTime: _time,
initialEntryMode: TimePickerEntryMode.input,
);
if (newTime != null) {
setState(() {
_time = newTime;
});
}
}
Gesture Detector to show the PickerDate:
GestureDetector(
onTap: () {
showDatePicker(
context: context,
initialDate: _dateTime ?? DateTime.now(),
firstDate: DateTime(2021),
lastDate: DateTime(2023),
builder: (BuildContext context, Widget? child) {
return Theme(
data: ThemeData.light().copyWith(
primaryColor: context.themeSettings.lightRed,
accentColor: context.themeSettings.lightRed,
colorScheme: ColorScheme.light(primary: context.themeSettings.lightRed),
buttonTheme: ButtonThemeData(textTheme: ButtonTextTheme.primary),
),
child: child!,
);
},
).then(
(date) {
setState(
() {
_dateTime = date;
},
);
print('date');
},
);
},
Gesture detector to show the DatePicker:
GestureDetector(
onTap: _selectTime,
child: Container(
decoration: BoxDecoration(
border: Border.all(color: context.themeSettings.mediumGray),
borderRadius: BorderRadius.all(Radius.circular(
5.0,
) //
),
),
width: width * 0.40,
height: height * 0.05,
child: Center(
child: Text(
'Pick a time',
style: TextStyle(fontSize: 18, color: context.themeSettings.darkText, fontWeight: FontWeight.bold),
),
),
),
),
The only thing missing is to show the actual value selected for both information.
what am I missing?
It remains only to display the time for the user. With Text().
Your time value in the _time variable
and dates in _dateTime
Text("time selected: $_time date selected: _dateTime",),
put this somewhere in your interface
for example in a child in GestureDetector
upd (24.08.2021):
I can not understand what your problem may be, according to the code fragments that you showed
Try to use code close to this
Source of code
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(primarySwatch: Colors.blue, brightness: Brightness.dark),
home: DatePickerDemo(),
);
}
}
class DatePickerDemo extends StatefulWidget {
#override
_DatePickerDemoState createState() => _DatePickerDemoState();
}
class _DatePickerDemoState extends State<DatePickerDemo> {
/// Which holds the selected date
/// Defaults to today's date.
DateTime selectedDate = DateTime.now();
_selectDate(BuildContext context) async {
final DateTime picked = await showDatePicker(
context: context,
initialDate: selectedDate,
firstDate: DateTime(2000),
lastDate: DateTime(2025),
);
if (picked != null && picked != selectedDate)
setState(() {
selectedDate = picked;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text(
"${selectedDate.toLocal()}".split(' ')[0],
style: TextStyle(fontSize: 55, fontWeight: FontWeight.bold),
),
SizedBox(
height: 20.0,
),
ElevatedButton(
onPressed: () => _selectDate(context),
child: Text(
'Select date',
style:
TextStyle(color: Colors.black, fontWeight: FontWeight.bold),
),
),
],
),
),
);
}
}

how can i change the TextStyle of showDateRangePicker() or showDateRangePicker() in flutter

Want to change the TextStyle of helpText in showDateRangePicker() in Flutter.
Can anybody Help.
buildMaterialDatePicker({BuildContext context, SearchVM model})
async {
final DateTimeRange picked = await showDateRangePicker(
context: context,
firstDate: initialDate,
helpText: 'Select a Date or Date-Range',
fieldStartHintText: 'Start Booking date',
fieldEndHintText: 'End Booking date',
currentDate: initialDate,
lastDate: DateTime(2020, initialDate.month + 1,
initialDate.day),
builder: (BuildContext context, Widget child) {
return Theme(
data: ThemeData.dark().copyWith(
colorScheme: ColorScheme.dark(
primary: Colors.greenAccent,
onPrimary: oppColor,
surface: Colors.greenAccent,
onSurface: oppColor,
),
dialogBackgroundColor: mainColor,
),
child: child,
);
},
);
}
So, according to the answer of abbas jafary answer.
I deep Dived into the Documentation of the showDateRangePicker() (you can do so using Ctrl+ Right-Clicking) and found what texstTheme it is using for that Text.
Text(
helpText,
style: textTheme.overline.apply(
color: headerForeground,),
),
So, Then I wrapped my Widget with Theme and updated the textTheme field.
buildMaterialDatePicker({BuildContext context, SearchVM model}) async {
final DateTimeRange picked = await showDateRangePicker(
context: context,
firstDate: initialDate,
helpText: 'Select a Date or Date-Range',
fieldStartHintText: 'Start Booking date',
fieldEndHintText: 'End Booking date',
currentDate: initialDate,
lastDate: DateTime(2020, initialDate.month + 1, initialDate.day),
builder: (BuildContext context, Widget child) {
return Theme(
data: ThemeData.dark().copyWith(
colorScheme: ColorScheme.dark(
primary: Colors.greenAccent,
onPrimary: oppColor,
surface: Colors.greenAccent,
onSurface: oppColor,
),
// Here I Chaged the overline to my Custom TextStyle.
textTheme: TextTheme(overline: TextStyle(fontSize: 16)),
dialogBackgroundColor: mainColor,
),
child: child,
);
},
);
}
For change colors, font and etc. You must wrap element into Theme:
Widget returnRangePicker(BuildContext context) {
return Theme(
data: Theme.of(context).copyWith(
accentColor: Colors.green,
primaryColor: Colors.blue,
buttonTheme: ButtonThemeData(
highlightColor: Colors.green,
buttonColor: Colors.green,
colorScheme: Theme.of(context).colorScheme.copyWith(
secondary: epapGreen,
background: Colors.white,
primary: Colors.green,
primaryVariant: Colors.green,
brightness: Brightness.dark,
onBackground: Colors.green),
textTheme: ButtonTextTheme.accent)),
child: Builder(
builder: (context) => FlatButton(
onPressed: () async {
final List<DateTime> picked = await DateRangePicker.showDatePicker(
context: context,
initialFirstDate: DateTime.now(),
initialLastDate:
DateTime.now()).add(Duration(days: 7),
firstDate: DateTime(2015),
lastDate: DateTime(2020));
if (picked != null && picked.length == 2) {
print(picked);
}
},
child: Text(
"Choose range",
style: TextStyle(color: Colors.green),
),
),
),
);
}
For more info you can check out the docs. or check this link