Categories
Coding

Xamarin Android Date Picker

Flicking through Mastering Xamarin Forms by Ed Snider recently I noticed that the instructions for adding an Android date picker seem to be missing – the iOS ones are there.

Ed does include the code for the Android version in his downloadable examples but they use the old, deprecated, Android.App Dialog Fragment and Fragment Manager rather than the Android.Support.V4.App versions.

A quick Web search didn’t turn up any updated samples so I’ve included my own revised versions of his code here…

Just create a Renderers folder in your Android project and include the two code files below. I’m assuming that you’ve already followed the book and got the iOS project going.

The key changes are using the GetFragmentManager() method in the ShowDatePickerDialogFragment of the Render rather than the Fragment property of the Activity and deriving DatePickerFragment from Android.Support.V4.App.DialogFragment rather than Android.App.DialogFragment.

DatePickerEntryCellRenders.cs …

using System;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using Android.App;
using Android.Content;
using Android.Views;
using Android.Widget;
using View = Android.Views.View;
using TripLog.Controls;
using TripLog.Droid.Renderers;


[assembly: ExportRenderer(typeof(DatePickerEntryCell), typeof(DatePickerEntryCellRenderer))]
namespace TripLog.Droid.Renderers
{
    public class DatePickerEntryCellRenderer : EntryCellRenderer
    {
        protected override View GetCellCore(Cell item, View convertView, ViewGroup parent, Context context)
        {
            var cell = (LinearLayout)base.GetCellCore(item, convertView, parent, context);
            var datepickerCell = (DatePickerEntryCell)item;

            EditText textView = null;

            if (cell != null)
            {
                textView = ((EntryCellView)cell).EditText;
            }

            // Default datepicker display attributes
            var displayFormat = "d";
            var date = DateTime.Today;
            var currentDate = DateTime.MinValue;

            Action<DateTime> pickedDateCallback = pickedDate =>
            {
                if (datepickerCell != null)
                {
                    datepickerCell.Date = pickedDate;
                }

                if (textView != null)
                {
                    textView.Text = pickedDate.ToString(displayFormat);
                }
            };

            if (textView != null)
            {
                // Hide keyboard since we're using the datepicker dialog
                textView.InputType = 0;

                if (!textView.HasOnClickListeners)
                {
                    // Show the datepicker when focusing on the cell
                    textView.FocusChange += (s, e) =>
                    {
                        DateTime.TryParse(textView.Text, out currentDate);

                        if (currentDate == DateTime.MinValue)
                        {
                            currentDate = DateTime.Now;
                        }

                        if (!textView.HasFocus)
                        {
                            return;
                        }

                        ShowDatePickerDialogFragment(context, currentDate, pickedDateCallback);
                    };

                    // Show the datepicker when clicking on the cell
                    textView.Click += (s, e) =>
                    {
                        DateTime.TryParse(textView.Text, out currentDate);

                        if (currentDate == DateTime.MinValue)
                        {
                            currentDate = DateTime.Now;
                        }

                        ShowDatePickerDialogFragment(context, currentDate, pickedDateCallback);
                    };
                }

                if (datepickerCell != null)
                {
                    textView.Text = datepickerCell.Date.ToString(displayFormat);
                }
            }

            return cell;
        }

        private void ShowDatePickerDialogFragment(Context context, DateTime date, Action<DateTime> dateSetCallback)
        {
            var fragTransaction = ((Activity)context).GetFragmentManager().BeginTransaction();
            var dialog = new DatePickerDialogFragment(context, date, dateSetCallback);
            dialog.Show(fragTransaction, "datepicker_dialog");
        }
    }
}

DatePickerDialogFragment …

using System;
using Android.App;
using Android.Content;
using Android.OS;
using DialogFragment = Android.Support.V4.App.DialogFragment;

namespace TripLog.Droid.Renderers
{
    public class DatePickerDialogFragment : DialogFragment
    {
        private readonly Context context;
        private readonly DateTime date;
        private readonly Action<DateTime> dateSetCallback;

        
        public DatePickerDialogFragment(Context context, DateTime date, Action<DateTime> dateSetCallback)
        {
            this.context = context;
            this.date = date;
            this.dateSetCallback = dateSetCallback;
        }

        public override Dialog OnCreateDialog(Bundle savedInstanceState)
        {
            return new DatePickerDialog(context, OnDateSet, date.Year, date.Month - 1, date.Day);
        }

        private void OnDateSet(object sender, DatePickerDialog.DateSetEventArgs args)
        {
            dateSetCallback(args.Date);
        }
    }
}

The book is well worth a read. You can find it here. At the time of writing the Kindle version in the is only £10 from Amazon in the UK, which seems like good value given the high cost of so many technical books.

Not taking any money from this, I promise, just posting what I hope is useful information.

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.