In this below code to display a date picker in Flutter as I press a button but nothing happens. I tried looking into the docs found noting there are no errors on how I can debug this or get to work.
import "package:flutter/material.dart" ;
import "dart:async";
void main() {
runApp(new MaterialApp(
home: new Baseapp(),
));
}
class Baseapp extends StatefulWidget{
#override
_State createState() => new _State();
}
class _State extends State<Baseapp> {
String _value = '';
Future _selectDate() async {
DateTime? picked = await showDatePicker(
context: context,
initialDate: new DateTime.now(),
firstDate: new DateTime(2016),
lastDate: new DateTime(2019)
);
if(picked != null) setState(() => _value = picked.toString());
}
#override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title : new Text("NAME HERE", style :TextStyle(color:Colors.black)),
backgroundColor: Colors.yellow ,
),
body: new Container(
padding : new EdgeInsets.all(20),
child: new Center(
child: new Column(
children:<Widget>[
new Text(_value),
new ElevatedButton(onPressed:_selectDate, child: new Text("Date")),
],
),
),
),
);
}
}
In your showDatePicker function, try implementing a builder, like so:
final DateTime picked = await showDatePicker(
context: context,
initialDate: selectedDate,
firstDate: DateTime(1900),
lastDate: lastDate,
//Implement builder here
builder: (context, child) => child,
That should solve the issue.
Future _selectDate() async {
DateTime? picked = await showDatePicker(
context: context,
initialDate: new DateTime.now(),
firstDate: new DateTime(2016),
lastDate: new DateTime(2019) //<= you used here past year but you set initial date is today so use here future year such as "lastDate: new DateTime(2019)" other wise intial date set to less than last year
lastDate: new DateTime(2024)
);
you used here last date in past year but you set initial date is today so use here future year such as "lastDate: new DateTime(2019)" other wise intial date set to less than last year
if(picked != null){
setState(() {
int year = picked.year;
int mth = picked.month;
int day = picked.day;
_value = '${day} / ${mth} / ${year}';
});
hey I figured it out XD
this particular code was missing.
thanks
Related
i have this funtion which handles my Date and Time picker widget ...Code bellow...
Future selectDayAndTimeL(BuildContext context) async {
DateTime? selectedDay = await showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(2021),
lastDate: DateTime(2030),
builder: (BuildContext context, Widget? child) => child!);
TimeOfDay? selectedTime = await showTimePicker(
context: context,
initialTime: TimeOfDay.now(),
);
if (selectedDay != null && selectedTime != null) {
//a little check
}
setState(() {
selectedDateAndTime = DateTime(
selectedDay!.year,
selectedDay!.month,
selectedDay!.day,
selectedTime!.hour,
selectedTime!.minute,
);
// _selectedDate = _selectedDay;
});
// print('...');
}
initially it was inside my add new task class/dart file "Stateful Widget", and everything was working fine but now i want to also use that function on the Home screen when a button is pressed.
Then i checked a StackOverflow question on how to call a function from another dart file which the solution required that i keep the Function on a different dart file then call it from there like this Example
void launchWebView () {
print("1234");
}
when i did i was getting an error which i lookedup and it was because of the "setState" in my function so i needed to put it inside a Stateful widget,
import 'package:flutter/material.dart';
class SelectDateAndTime extends StatefulWidget {
#override
_SelectDateAndTimeState createState() => _SelectDateAndTimeState();
}
class _SelectDateAndTimeState extends State<SelectDateAndTime> {
DateTime? _selectedDate;
// DateTime _selectedDate;
DateTime? selectedDateAndTime;
Future selectDayAndTimeL(BuildContext context) async {
DateTime? selectedDay = await showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(2021),
lastDate: DateTime(2030),
builder: (BuildContext context, Widget? child) => child!);
TimeOfDay? selectedTime = await showTimePicker(
context: context,
initialTime: TimeOfDay.now(),
);
if (selectedDay != null && selectedTime != null) {
//a little check
}
setState(() {
selectedDateAndTime = DateTime(
selectedDay!.year,
selectedDay!.month,
selectedDay!.day,
selectedTime!.hour,
selectedTime!.minute,
);
// _selectedDate = _selectedDay;
});
// print('...');
}
#override
Widget build(BuildContext context) {
// TODO: implement build
throw UnimplementedError();
}
}
And that was the only difference from my code with the example i followed and i was still getting an error when i tried calling the funtion, and i have checked all the quetions related to clling functions from another dart file / class and none of them had SetState so their solution didn't work for me
This is the error i got when i called just the Function Name
Bellow s the error i got when i tried to call
onPressed: () => selectedDateAndTime!.selectDayAndTimeL(),
what should i do from here?
I'm guessing that you originally had a Statefull widget, that probably looked something like this:
class OriginalWidget extends StatefulWidget {
#override
_OriginalWidgetState createState() => _OriginalWidgetState();
}
class _OriginalWidgetState extends State<OriginalWidget> {
DateTime? _selectedDate;
DateTime? selectedDateAndTime;
Future selectDayAndTimeL(BuildContext context) async {
DateTime? selectedDay = await showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(2021),
lastDate: DateTime(2030),
builder: (BuildContext context, Widget? child) => child!);
TimeOfDay? selectedTime = await showTimePicker(
context: context,
initialTime: TimeOfDay.now(),
);
if (selectedDay != null && selectedTime != null) {
//a little check
}
setState(() {
selectedDateAndTime = DateTime(
selectedDay!.year,
selectedDay!.month,
selectedDay!.day,
selectedTime!.hour,
selectedTime!.minute,
);
// _selectedDate = _selectedDay;
});
// print('...');
}
#override
Widget build(BuildContext context) {
return FlatButton(
onPressed: () => selectDayAndTimeL(context));
}
}
Now, what you want to do is to reuse the logic of your selectDayAndTimeL function.
The problem is that both the selectedDateAndTime variable and the setState method are specific to the Statefull widget _OriginalWidgetState.
What you need to do is to modify your selectDayAndTimeL function so that it can take those widget-specific stuff as parameters.
So, in essence what you would do is:
1st create the function as a standalone function, for instance in a new dart file. Make sure to remove the widget-specific stuff from the body and leave them as parameters:
Future selectDayAndTimeL(BuildContext context, void Function(DateTime) onDateAndTimeSelected) async {
DateTime? selectedDay = await showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(2021),
lastDate: DateTime(2030),
builder: (BuildContext context, Widget? child) => child!);
TimeOfDay? selectedTime = await showTimePicker(
context: context,
initialTime: TimeOfDay.now(),
);
if (selectedDay != null && selectedTime != null) {
//a little check
}
onDateAndTimeSelected(DateTime(
selectedDay!.year,
selectedDay!.month,
selectedDay!.day,
selectedTime!.hour,
selectedTime!.minute,
));
// print('...');
}
2nd, on your new Statefull widgets, you may now call this function, make sure that you send the new onDateAndTimeSelected parameter:
class SecondWidget extends StatefulWidget {
#override
_SecondWidgetState createState() => _SecondWidgetState();
}
class _SecondWidgetState extends State<SecondWidget> {
DateTime? selectedDateAndTime;
#override
Widget build(BuildContext context) {
return FlatButton(
onPressed: () => selectDayAndTimeL(context,
setState((DateTime selectedValue) {
selectedDateAndTime = selectedValue;
} )
));
}
}
And then you could just follow the same logic for any other Statefull widget that needs to call your function.
setState tells a stateful widget to re-render based on the changed data. In your case you are changing selectedDateAndTime and re-building the Widget with updated data.
If you want to update/rebuild a widget from a "remote" function you need to use a callback.
Future selectDayAndTimeL(BuildContext context,Function(DateTime time) onDateTimeSelected) async {
DateTime? selectedDay = await showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(2021),
lastDate: DateTime(2030),
builder: (BuildContext context, Widget? child) => child!);
TimeOfDay? selectedTime = await showTimePicker(
context: context,
initialTime: TimeOfDay.now(),
);
if (selectedDay != null && selectedTime != null) {
//a little check
}
// call the callback here with your calculated data
onDateTimeSelected(
DateTime(
selectedDay!.year,
selectedDay!.month,
selectedDay!.day,
selectedTime!.hour,
selectedTime!.minute,
),
);
}
Then in the StatefulWidget where you call this function:
selectDayAndTimeL(BuildContext context,(time) {
setState(() {
selectedDateAndTime = time;
});
});
I am trying to make a date range picker like this ,date picker start with on value (today value) then user select the range he need ,in flutter finally I found this package.
But I can't open it when I click on the button as date picker.
I trayed to use another package date range picker but it doesn't help me!
Flutter has now an inbuilt date range picker below is an example of using it
IconButton(
onPressed: () async {
final picked = await showDateRangePicker(
context: context,
lastDate: endDate,
firstDate: new DateTime(2019),
);
if (picked != null && picked != null) {
print(picked);
setState(() {
startDate = picked.start;
endDate = picked.end;
//below have methods that runs once a date range is picked
allWaterBillsFuture = _getAllWaterBillsFuture(
picked.start.toIso8601String(),
picked.end
.add(new Duration(hours: 24))
.toIso8601String());
});
}
},
icon: Icon(
Icons.calendar_today,
color: Colors.white,
),
),
There's a package specifically built for that purpose, date_range_picker
To install it, you should add the following line under dependecies in the pubspec.yaml file:
date_range_picker: ^1.0.5
You should then import the package at the top of the file of the Widget you would like to use the function:
import 'package:date_range_picker/date_range_picker.dart' as DateRangePicker;
Then, you could use the package as follows:
new MaterialButton(
color: Colors.deepOrangeAccent,
onPressed: () async {
final List<DateTime> picked = await DateRagePicker.showDatePicker(
context: context,
initialFirstDate: new DateTime.now(),
initialLastDate: (new DateTime.now()).add(new Duration(days: 7)),
firstDate: new DateTime(2015),
lastDate: new DateTime(2020)
);
if (picked != null && picked.length == 2) {
print(picked);
}
},
child: new Text("Pick date range")
)
This is a full example on how you could use it:
import 'package:flutter/material.dart';
import 'package:date_range_picker/date_range_picker.dart' as DateRagePicker;
void main() {
runApp(MaterialApp(home: HomeScreen(), title: 'Flutter Date Range Example'));
}
class HomeScreen extends StatefulWidget {
HomeScreen({Key key}) : super(key: key);
#override
_HomeScreenState createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Center(
child: MaterialButton(
color: Colors.deepOrangeAccent,
onPressed: () async {
final List<DateTime> picked = await DateRagePicker.showDatePicker(
context: context,
initialFirstDate: new DateTime.now(),
initialLastDate:
(new DateTime.now()).add(new Duration(days: 7)),
firstDate: new DateTime(2015),
lastDate: new DateTime(2020));
if (picked != null && picked.length == 2) {
print(picked);
}
},
child: new Text("Pick date range")),
),
);
}
}
Here, I'm using Flutter inbuilt date range picker, where you should initially give the start and end date, to display the selected range used two elevated buttons where the date range will be shown.in setState, if you click cancel in daterange picker popup, the initial date range will be assigned.
import 'package:flutter/material.dart';
class DateRangeWidget extends StatefulWidget {
DateRangeWidget({Key? key}) : super(key: key);
#override
State<DateRangeWidget> createState() => _DateRangeWidgetState();
}
class _DateRangeWidgetState extends State<DateRangeWidget> {
DateTimeRange dateRange = DateTimeRange(
start: DateTime(2021, 11, 5),
end: DateTime(2022, 12, 10),
);
#override
Widget build(BuildContext context) {
final start = dateRange.start;
final end = dateRange.end;
return Column(children: [
const Text(
'Date Range',
style: TextStyle(fontSize: 16),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
child: ElevatedButton(
child: Text(
'${start.year}/${start.month}/${start.day}',
),
onPressed: pickDateRange,
),
),
Container(
margin: EdgeInsets.only(left: 20),
child: ElevatedButton(
child: Text(
'${end.year}/${end.month}/${end.day}',
),
onPressed: pickDateRange,
),
),
],
)
]);
}
Future pickDateRange() async {
DateTimeRange? newDateRange = await showDateRangePicker(
context: context,
initialDateRange: dateRange,
firstDate: DateTime(2019),
lastDate: DateTime(2023),
);
setState(() {
dateRange = newDateRange ?? dateRange;
// if (newDateRange == null) return;
// setState(() => dateRange = newDateRange);
});
}
}
[1]: https://i.stack.imgur.com/h1HIN.png
I have an array with certain dates.
I want to disable these dates in the date picker and also change the color. How to do this?
You can use selectableDayPredicate property. For colors, you can change it by themes.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
DateTime selectedDate = DateTime(2020, 1, 14);
// DatePicker will call this function on every day and expect
// a bool output. If it's true, it will draw that day as "enabled"
// and that day will be selectable and vice versa.
bool _predicate(DateTime day) {
if ((day.isAfter(DateTime(2020, 1, 5)) &&
day.isBefore(DateTime(2020, 1, 9)))) {
return true;
}
if ((day.isAfter(DateTime(2020, 1, 10)) &&
day.isBefore(DateTime(2020, 1, 15)))) {
return true;
}
if ((day.isAfter(DateTime(2020, 2, 5)) &&
day.isBefore(DateTime(2020, 2, 17)))) {
return true;
}
return false;
}
Future<void> _selectDate(BuildContext context) async {
final DateTime picked = await showDatePicker(
context: context,
initialDate: selectedDate,
selectableDayPredicate: _predicate,
firstDate: DateTime(2019),
lastDate: DateTime(2021),
builder: (context, child) {
return Theme(
data: ThemeData(
primaryColor: Colors.orangeAccent,
disabledColor: Colors.brown,
textTheme:
TextTheme(body1: TextStyle(color: Colors.blueAccent)),
accentColor: Colors.yellow),
child: child,
);
});
if (picked != null && picked != selectedDate)
setState(() {
selectedDate = picked;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text("${selectedDate.toLocal()}".split(' ')[0]),
SizedBox(
height: 20.0,
),
RaisedButton(
onPressed: () => _selectDate(context),
child: Text('Select date'),
),
],
),
),
);
}
}
I encountered the same problem. After going back and forth, I did the following:
Created a list of specific dates:
static var unavailableDates = ["2020-08-14", "2020-08-20", "2020-08-13","2020-08-21","2020-08-23"];
Created an initial date variable:
static DateTime initialDate = DateTime.now();
formatted the initial date to get rid of the timestamp:
static DateFormat dateFormat = new DateFormat("yyyy-MM-dd");
String formattedDate = dateFormat.format(initialDate);
Put my unavailable dates in order:
unavailableDates.sort(((a, b) => a.compareTo(b)));
Added a way to verify the initial date does not fall on the disabled date. This jumps to the next available date. If you do not have something in place to verify unavailable date and initial date is not the same, you will get an exception:
for(var unavdate in unavailableDates){
if (unavdate.compareTo(formattedDate) == 0) {
formattedDate = unavdate;
fromStringDate = DateTime.parse(formattedDate);
initialDate = fromStringDate.add(new Duration(days: 1));
formattedDate = dateFormat.format(initialDate);
}
}
Created a day predicate function:
bool setDayPredicate(DateTime val) {
//this allows certain dates to be greyed out based on availability
String Dates = dateFormat.format(val); //formatting passed in value
return !unavailableDates.contains(Dates);
}
Put it all together:
date = await showDatePicker(
context: context,
initialDate: initialDate,
firstDate: new DateTime.now(),
lastDate: new DateTime.now().add(new Duration(days: 30)),
selectableDayPredicate: setDayPredicate, });
I have DateTimeField and there is strange issue while editing the date manually.
Here is the display with default value:
I selected month by double tapping and try to type 08 manually.
When I bring pointer at the end of month 12, and pressed backspace to remove 2 from 12. The month was changed to 01.
When I press backspace in the end of year, to remove 8 from 2018. It was changed to 0201.
Here is the code of that field:
DateTimeField(
format: DateFormat("yyyy-MM-dd hh:mm:ss"),
onSaved: (val) => setState(() => _fromDate = val),
keyboardType: TextInputType.datetime,
onChanged: (DateTime newValue) {
setState(() {
_fromDate = newValue;
});
},
onShowPicker: (context, currentValue) {
return showDatePicker(
context: context,
firstDate: DateTime.now(),
initialDate: currentValue ?? DateTime.now(),
lastDate: DateTime.now().add(new Duration(days: 30))
);
},
);
I have no clue, what's going on with this. Please tell me, what could be wrong?
NOTE:
Using picker for date selection works fine
I've date field in another page, it's in yyyy-MM-dd format, and it works as expected there.
So I've tried the available sample that you've provided. I got a different behavior, I'm not able to edit the value manually. The date picker always open whenever I've tried to edit the form.
Here is the complete minimal code that I've tested base from your code:
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:datetime_picker_formfield/datetime_picker_formfield.dart';
void main() => runApp(BasicDateTimeField());
class BasicDateTimeField extends StatefulWidget {
#override
_BasicDateTimeFieldState createState() => _BasicDateTimeFieldState();
}
class _BasicDateTimeFieldState extends State<BasicDateTimeField> {
#override
Widget build(BuildContext context) {
DateTime _fromDate;
return MaterialApp(
home: Scaffold(
body: Center(
child: DateTimeField(
format: DateFormat("yyyy-MM-dd hh:mm:ss"),
onSaved: (val) => setState(() => _fromDate = val),
keyboardType: TextInputType.datetime,
onChanged: (DateTime newValue) {
setState(() {
_fromDate = newValue;
});
},
onShowPicker: (context, currentValue) {
return showDatePicker(
context: context,
firstDate: DateTime.now(),
initialDate: currentValue ?? DateTime.now(),
lastDate: DateTime.now().add(new Duration(days: 30)));
},
),
),
),
);
}
}
Output:
In the sample, I've used the current version of datetime_picker_formfield: ^2.0.0 plugin.
Perhaps you can use the built-in DateTime picker instead.
Here is a sample demo that I've created for your reference:
import 'package:flutter/material.dart';
void main() {
runApp(
MaterialApp(
theme: ThemeData(primaryColor: Colors.blue),
home: MyWidget(),
),
);
}
class MyWidget extends StatefulWidget {
createState() => MyWidgetState();
}
class MyWidgetState extends State<MyWidget> {
DateTime selectedDate = DateTime.now();
Future<void> _selectDate(BuildContext context) async {
final DateTime picked = await showDatePicker(
context: context,
initialDate: selectedDate,
firstDate: DateTime(2015, 8),
lastDate: DateTime(2101));
if (picked != null && picked != selectedDate)
setState(() {
selectedDate = picked;
});
}
#override
initState() {
super.initState();
selectedDate = DateTime.now();
}
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Demo App"),
),
body: ListView(padding: const EdgeInsets.all(16.0), children: [
Container(
height: 100,
child: FlutterLogo(),
),
SizedBox(height: 10.0),
InputDatePickerFormField(
firstDate: DateTime(2015, 8),
lastDate: DateTime(2101),
initialDate: selectedDate,
onDateSubmitted: (date) {
setState(() {
selectedDate = date;
});
},
),
// Text("Selected Date: $selectedDate"),
ElevatedButton(
onPressed: () => _selectDate(context),
child: Text('Select date'),
)
]),
);
}
}
Output:
This behavior means that you can not manually change the date select use your picker to change it
I have two separate buttons, one to select a date and one to select a time. How am I able to select both the date and then time by only having a single button?
For example, one the click of a "Schedule" button, a Datepicker will popup. Once the user selects a date and clicks "OK" in the Datepicker, the Timepicker will be called or popup.
This is the code for my time and date button widgets:
DateTime _date = new DateTime.now();
TimeOfDay _time = new TimeOfDay.now();
Future<Null> _selectDate(BuildContext context) async {
final DateTime picked = await showDatePicker(
context: context,
initialDate: _date,
firstDate: new DateTime(2019),
lastDate: new DateTime(2021),
);
if(picked != null && picked != _date) {
print('Date selected: ${_date.toString()}');
setState((){
_date = picked;
});
}
}
Future<Null> _selectTime(BuildContext context) async {
final TimeOfDay picked = await showTimePicker(
context: context,
initialTime: _time,
);
if(picked != null && picked != _time) {
print('Time selected: ${_time.toString()}');
setState((){
_time = picked;
});
}
}
Widgets:
final buttonRow = new Wrap(children: <Widget>[
new RaisedButton(
child: new Text('Select Date'),
onPressed: (){_selectDate(context);}
),
new RaisedButton(
child: new Text('Select Time'),
onPressed: (){_selectTime(context);}
)
]);
RaisedButton(
child: new Text('Select Date and Time'),
onPressed: (){ _selectDateAndTime(context); }
)
/* ... */
Future<Null> _selectDateAndTime(BuildContext context) async {
await _selectDate(context);
await _selectTime(context);
}