Hikari
Hikari

Reputation: 599

Xamarin.Forms Android DatePicker/TimePicker button listener

I need to know if a user tapped on the Cancel or Ok button in a Date/Time picker of an xamarin.Forms Android app.

I have tried to add a function to the Click event but this is never triggered.

This is my code (similar for the TimePicker):

using Android.Content;
using MyApp.Droid;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using MyApp.Models;
using Java.Util;

[assembly: ExportRenderer(typeof(DatePicker), typeof(DatePickerCustomRenderer))]

namespace MyApp.Droid {
    public class DatePickerCustomRenderer : DatePickerRenderer {

        public DatePickerCustomRenderer(Context context) : base(context) { } 

        protected override void OnElementChanged(ElementChangedEventArgs<DatePicker> e) {
            base.OnElementChanged(e);

            Locale locale = new Locale(Utente.FormatoPerDateTimePicker);
            Control.TextLocale = locale;

            Control.Click += Control_Click;
        }

        private void Control_Click(object sender, System.EventArgs e) {
            // This function is never called :(
            throw new System.NotImplementedException();
        }
    }
}

How can I do this?

Upvotes: 4

Views: 3976

Answers (3)

Nick Kovalsky
Nick Kovalsky

Reputation: 6462

Using the following Android DatePicker custom renderer you have total control over OK and CANCEL.

using Android.App;
using Android.Content;
using ???.Android.Renderers;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
using DatePicker = Xamarin.Forms.DatePicker;

[assembly: ExportRenderer(typeof(DatePicker), typeof(FixedDatePickerRenderer))]    
namespace ???.Android.Renderers
{
    public class FixedDatePickerRenderer : Xamarin.Forms.Platform.Android.DatePickerRenderer
    {
        public FixedDatePickerRenderer(Context context) : base(context)
        {
        }

        protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.DatePicker> e)
        {
            base.OnElementChanged(e);

            //Disposing
            if (e.OldElement != null)
            {
                _element = null;
            }

            //Creating
            if (e.NewElement != null)
            {
                _element = e.NewElement;
            }
        }

        protected Xamarin.Forms.DatePicker _element;

        protected override DatePickerDialog CreateDatePickerDialog(int year, int month, int day)
        {
            var dialog = new DatePickerDialog(Context, (o, e) =>
            {
                _element.Date = e.Date;
                ((IElementController)_element).SetValueFromRenderer(VisualElement.IsFocusedPropertyKey, false);
            }, year, month, day);

            dialog.SetButton((int)DialogButtonType.Positive, Context.Resources.GetString(global::Android.Resource.String.Ok), OnOk);
            dialog.SetButton((int)DialogButtonType.Negative, Context.Resources.GetString(global::Android.Resource.String.Cancel), OnCancel);

            return dialog;
        }

        private void OnCancel(object sender, DialogClickEventArgs e)
        {
            _element.Unfocus();
            //((FixedDatePicker) _element)?.CallOnCancel();
        }
        private void OnOk(object sender, DialogClickEventArgs e)
        {
            //need to set date from native control manually now
            _element.Date = ((DatePickerDialog)sender).DatePicker.DateTime;
            _element.Unfocus();
            //((FixedDatePicker)_element)?.CallOnOk();
        }

    }

}


 

Just for people looking for a complete solution to avoid searching for iOS, there's an option already included out-of-the box: https://learn.microsoft.com/en-us/xamarin/xamarin-forms/platform/ios/datepicker-selection

Upvotes: 3

Wasim
Wasim

Reputation: 11

Nick Kovalsky' solution (using a custom renderer) above for Android works fine for me.

For iOS, the iOS specifics out-of-the-box solution didn't work for me, https://learn.microsoft.com/en-us/xamarin/xamarin-forms/platform/ios/datepicker-selection

I've used the custom renderer approach for iOS also, Looking at the Xamarin custom renderer (On iOS platform), we can see the InputAccessoryView is set to UIToolbar, and the toolbar contains the Done button (UIBarButtonItem). So, we can use the Done button and listen for click event,
https://github.com/xamarin/Xamarin.Forms/blob/master/Xamarin.Forms.Platform.iOS/Renderers/DatePickerRenderer.cs

[assembly: ExportRenderer(typeof(CustomDatePicker), typeof(MyApp.iOS.CustomRenderers.CustomDatePickerRenderer))]
public class CustomDatePickerRenderer : DatePickerRenderer
    {      
        CustomDatePicker _datePickerElement ;

        protected override void OnElementChanged(ElementChangedEventArgs<DatePicker> e)
        {
            base.OnElementChanged(e);

            if (e.NewElement is CustomDatePicker datePickerElement && Control != null)
            {
                _datePickerElement = datePickerElement;                

                var toolbar = Control.InputAccessoryView as UIToolbar;
                foreach (var button in toolbar?.Items)
                {
                    if (button.Style == UIBarButtonItemStyle.Done)
                    {
                        button.Clicked -= OnDoneButtonClicked;
                        button.Clicked += OnDoneButtonClicked;
                    }
                }
            }
        }

        private void OnDoneButtonClicked(object sender, EventArgs e)
        {
            if(_datePickerElement.NullableDate != _datePickerElement.Date)
            {
                _datePickerElement.NullableDate = _datePickerElement.Date;
            }            
        }

    }

Upvotes: 1

Elvis Xia - MSFT
Elvis Xia - MSFT

Reputation: 10831

I need to know if a user tapped on the "cancel" or on the "ok" button in a date/time picker of an xamarin.Forms Android app.

With Xamarin.Form's DatePicker, you can't do that. Xamarin.Forms.DatePicker is renderered into an EditText control. The pop up DatePickerDialog is unfortunately not exposed to user. You can see that from Source Codes of DatePickerRenderer.

So if you really want to detect the OK/Cancel button click events. You need to implement your own DatePickerRenderer according to the source codes.

Upvotes: 2

Related Questions