MvvmCross – Xamarin.Android Popup DatePicker on EditText Click
24 Apr 2014Goal
When the user clicks on an EditText
box in a MvvmCross Xamarin.Android app show a date picker popup.
Research
- http://blog.ostebaronen.dk/2013/02/using-dialogs-in-mono-for-android.html
- http://stackoverflow.com/questions/14933330/datepicker-how-to-popup-datepicker-when-click-on-edittext
- http://docs.xamarin.com/recipes/android/other_ux/fragment/select_a_date_in_a_fragment/
Solution
All of the solutions I kept finding to this problem always had the user clicking on a button to show the DatePicker popup, and I really wanted the user to be able to show the date picker when they pressed on the EditText
box, much like Android does in the default Calendar app.
From the above articles I was able to piece together a solution, the highlights:
- Instead of setting the click event on a button set it to the
EditText
box.
datePickerText = view.FindViewById<EditText>(Resource.Id.DatePickerEditText);
datePickerText.Click += delegate
{
var dialog = new DatePickerDialogFragment(Activity, Convert.ToDateTime(datePickerText.Text), this);
dialog.Show(FragmentManager, "date");
};
-
Ensure when the user presses on the
EditText
box that the system does not display the default keyboard by settingdatePickerText.Focusable = false;
. -
For MvvmCross binding we only need to bind to the
datePickerText
.
The full solution:
public class EnterTimeView : MvxFragment, DatePickerDialog.IOnDateSetListener
{
private EditText datePickerText;
public EnterTimeView()
{
this.RetainInstance = true;
}
public override Android.Views.View OnCreateView(Android.Views.LayoutInflater inflater, Android.Views.ViewGroup container, Android.OS.Bundle savedInstanceState)
{
this.HasOptionsMenu = true;
var ignored = base.OnCreateView(inflater, container, savedInstanceState);
var view = inflater.Inflate(Resource.Layout.EnterTimeView, container, false);
datePickerText = view.FindViewById<EditText>(Resource.Id.DatePickerEditText);
datePickerText.Focusable = false;
datePickerText.Click += delegate
{
var dialog = new DatePickerDialogFragment(Activity, Convert.ToDateTime(datePickerText.Text), this);
dialog.Show(FragmentManager, "date");
};
var set = this.CreateBindingSet<EnterTimeView, EnterTimeViewModel>();
set.Bind(datePickerText).To(vm => vm.Date);
set.Apply();
return view;
}
public void OnDateSet(Android.Widget.DatePicker view, int year, int monthOfYear, int dayOfMonth)
{
datePickerText.Text = new DateTime(year, monthOfYear + 1, dayOfMonth).ToString();
}
private class DatePickerDialogFragment : Android.Support.V4.App.DialogFragment
{
private readonly Context _context;
private DateTime _date;
private readonly DatePickerDialog.IOnDateSetListener _listener;
public DatePickerDialogFragment(Context context, DateTime date, DatePickerDialog.IOnDateSetListener listener)
{
_context = context;
_date = date;
_listener = listener;
}
public override Dialog OnCreateDialog(Bundle savedState)
{
var dialog = new DatePickerDialog(_context, _listener, _date.Year, _date.Month - 1, _date.Day);
return dialog;
}
}
}