When I switch showDatePicker
to input mode (initialEntryMode: DatePickerEntryMode.input
) using an Arabic locale, typing dates with Eastern-Arabic digits (e.g. ٢٠٢٠/١١/١١
) doesn’t work. The field rejects every character and displays an error message in Arabic:
Which roughly translates to “Invalid date format.”
final picked = await showDatePicker(
context: context,
locale: const Locale('ar'),
initialEntryMode: DatePickerEntryMode.input,
firstDate: DateTime(2000),
lastDate: DateTime(2100),
initialDate: DateTime.now(),
);
example of my input: ٢٠٢٠/١١/١١
You might wanna consider filing an issue on Flutter’s github
You can try:
- Input formatter
static const Map<String, String> _arabicToWesternDigits = {
'٠': '0',
'١': '1',
'٢': '2',
'٣': '3',
'٤': '4',
'٥': '5',
'٦': '6',
'٧': '7',
'٨': '8',
'٩': '9',
};
Flutter’s date picker input validation doesn’t automatically convert Eastern-Arabic numerals to Western-Arabic numerals that the parsing logic expects.
showDatePicker doesn’t have 1. Input formatter or on change !
Try this code:
import 'package:flutter/services.dart';
class ArabicDigitsInputFormatter extends TextInputFormatter {
static const Map<String, String> _arabicToWesternDigits = {
'٠': '0',
'١': '1',
'٢': '2',
'٣': '3',
'٤': '4',
'٥': '5',
'٦': '6',
'٧': '7',
'٨': '8',
'٩': '9',
};
@override
TextEditingValue formatEditUpdate(
TextEditingValue oldValue,
TextEditingValue newValue,
) {
String convertedText = newValue.text;
// Convert Eastern-Arabic digits to Western-Arabic digits
_arabicToWesternDigits.forEach((arabic, western) {
convertedText = convertedText.replaceAll(arabic, western);
});
return TextEditingValue(
text: convertedText,
selection: TextSelection.collapsed(offset: convertedText.length),
);
}
}
// Usage example with a custom TextField for date input
class ArabicDateInputField extends StatefulWidget {
final Function(DateTime?) onDateSelected;
const ArabicDateInputField({Key? key, required this.onDateSelected}) : super(key: key);
@override
State<ArabicDateInputField> createState() => _ArabicDateInputFieldState();
}
class _ArabicDateInputFieldState extends State<ArabicDateInputField> {
final TextEditingController _controller = TextEditingController();
@override
Widget build(BuildContext context) {
return TextField(
controller: _controller,
inputFormatters: [
ArabicDigitsInputFormatter(),
// Add other formatters as needed
],
decoration: InputDecoration(
labelText: 'التاريخ',
hintText: 'yyyy/mm/dd',
suffixIcon: IconButton(
icon: Icon(Icons.calendar_today),
onPressed: () async {
final picked = await showDatePicker(
context: context,
locale: const Locale('ar'),
initialEntryMode: DatePickerEntryMode.input,
firstDate: DateTime(2000),
lastDate: DateTime(2100),
initialDate: DateTime.now(),
);
if (picked != null) {
_controller.text = '${picked.year}/${picked.month.toString().padLeft(2, '0')}/${picked.day.toString().padLeft(2, '0')}';
widget.onDateSelected(picked);
}
},
),
),
onSubmitted: (value) {
try {
final parts = value.split('/');
if (parts.length == 3) {
final date = DateTime(
int.parse(parts[0]),
int.parse(parts[1]),
int.parse(parts[2]),
);
widget.onDateSelected(date);
}
} catch (e) {
// Handle parsing error
}
},
);
}
}