'How to show date picker on the onclick of text field instead of keyboard in flutter?
Wish to show date picker when clicking on the TextFormField
instead of the keyboard. I have tried using GestureDetector
but not working as I expected.
DateTime _date = new DateTime.now();
TimeOfDay _time = new TimeOfDay.now();
Future<Null> _selectedDate(BuildContext context) async {
final DateTime picked = await showDatePicker(
context: context,
initialDate: _date,
firstDate: new DateTime(2016),
lastDate: new DateTime(2019));
if (picked != null && picked != _date) {
print("Date selected ${_date.toString()}");
setState(() {
_date = picked;
});
}
}
......
new GestureDetector(
onTap: (){
_selectedTime(context);
},
child:
new TextFormField(
initialValue: convertToDate(_date),
decoration: const InputDecoration(
icon: const Icon(Icons.calendar_today),
hintText: 'Enter your date of event',
labelText: 'Date',
),
keyboardType: null,
),
),
Solution 1:[1]
You can wrap your TextFormField
with an AbsorbPointer
(see documentation). It will "absorb" the incoming standard behavior on the child so clicking the TextFormField would do nothing. If you now wrap the AbsorbPointer
using a GestureDetector
you can use the onTap()
method to call your showDatePicker method.
DateTime selectedDate = DateTime.now();
TextEditingController _date = new TextEditingController();
Future<Null> _selectDate(BuildContext context) async {
final DateTime picked = await showDatePicker(
context: context,
initialDate: selectedDate,
firstDate: DateTime(1901, 1),
lastDate: DateTime(2100));
if (picked != null && picked != selectedDate)
setState(() {
selectedDate = picked;
_date.value = TextEditingValue(text: picked.toString());
});
}
// inside Widget build
GestureDetector(
onTap: () => _selectDate(context),
child: AbsorbPointer(
child: TextFormField(
controller: _date,
keyboardType: TextInputType.datetime,
decoration: InputDecoration(
hintText: 'Date of Birth',
prefixIcon: Icon(
Icons.dialpad,
color: _icon,
),
),
),
),
);
Solution 2:[2]
You can wrap your TextField
with AbsorbPointer
, so your widget tree would look something like this:
GestureDetector(
onTap:()=>showDialog(),
child:AbsorbPointer(
child: MyTextField(),
)
)
Solution 3:[3]
The other answers here have many widgets to get the job done. But this can simply done by using TextFormField
only. Just set the widget to read only (so that it doesn't take inputs) and then define an onTap. The controller attached to it will take the value from the date picker.
First create a TextFormField
widget like this:
TextFormField(
readOnly: true, //this is important
onTap: _selectDate, //the method for opening data picker
controller: _textcontroller, //the controller
),
Now write the _selectDate
function:
DateTime dateTime = DateTime.now();
_selectDate() async {
final DateTime? picked = await showDatePicker(
context: context,
initialDate: dateTime,
initialDatePickerMode: DatePickerMode.day,
firstDate: DateTime.now(),
lastDate: DateTime(2101));
if (picked != null) {
dateTime = picked;
//assign the chosen date to the controller
_textController.text = DateFormat.yMd().format(dateTime);
}
}
Personally I think this is the easiest solution.
Solution 4:[4]
Try this
GestureDetector(
onTap: () => _selectDate(context),
child: AbsorbPointer(
child: TextField(
controller: textController,
decoration: InputDecoration(
focusedBorder: InputBorder.none,
enabledBorder: InputBorder.none,
contentPadding: EdgeInsets.all(10.0),
labelText: widget.hintText,
labelStyle: TextStyle(
color: Colors.black,
fontSize: 16),
// pass the hint text parameter here
hintStyle: TextStyle(
color: Colors.black,
fontSize: 16),
suffixIcon: Icon(
Icons.calendar_today),
),
style: TextStyle(color: Colors.black, fontSize: 18),
),
),
);
Future<Null> _selectDate(BuildContext context) async {
final DateTime? picked = await showDatePicker(
context: context,
initialDate: selectedDate,
firstDate: DateTime(1901, 1),
lastDate: DateTime(2100));
if (picked != null && picked != selectedDate)
setState(() {
selectedDate = picked;
String convertedDateTime = "${picked.year.toString()}-${picked.month.toString().padLeft(2,'0')}-${picked.day.toString().padLeft(2,'0')}";
// widget.textController.value = TextEditingValue(text: picked.toString());
widget.textController.value = TextEditingValue(text: convertedDateTime);;
});
}
Result
Solution 5:[5]
TextField(
controller: TextEditingController()
..text = reservationProvider.date,
decoration: InputDecoration(
suffixIcon: ImageIcon(
AssetImage('images/calendar_today.png'),
color: Colors.black,
)),
readOnly: true,
onTap: () async {
final date = await showDatePicker(
context: context,
firstDate: DateTime(1960),
initialDate: DateTime.now(),
lastDate: DateTime(2100));
if (date != null) {
print(date);
}
},
),
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | novas1r1 |
Solution 2 | Shady Aziza |
Solution 3 | Shourya Shikhar |
Solution 4 | Quick learner |
Solution 5 | Robert Christopher |