24 hours TimePicker with Focused and Unfocused events

房东的猫 提交于 2019-12-12 19:49:26

问题


I tried implementing 24 Hour Time Picker as given here 24 Hour TimePicker in XF project.

But it doesn't fire the Focus and Unfocused event on Android. Has anyone implemented this?


回答1:


Explanation

The author of this custom control forgot to fire Focused and Unfocused in the Android Custom Renderer.

We can fire these events by calling ElementController.SetValueFromRenderer(VisualElement.IsFocusedPropertyKey, [true/false]); from the Android Custom Renderer when FocusChanged fires.

This custom Android control also doesn't clear focus once the time is set, so we'll add ClearFocus() to OnTimeSet too.

Xamarin.Forms 2.4 Code

Because the sample was written in Xamarin.Forms v2.4, here's the answer if you are continuing with Xamarin.Forms v2.4.

using System;

using Android.App;
using Android.Content;
using Android.Runtime;

using TimePickerDemo.CustomControls;
using TimePickerDemo.Droid;

using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;

[assembly: ExportRenderer(typeof(CustomTimePicker24H), typeof(CustomTimePicker24HRenderer))]
namespace TimePickerDemo.Droid
{
    public class CustomTimePicker24HRenderer : ViewRenderer<Xamarin.Forms.TimePicker, Android.Widget.EditText>, TimePickerDialog.IOnTimeSetListener, IJavaObject, IDisposable
    {
        private TimePickerDialog dialog = null;

        IElementController ElementController => Element as IElementController;

        protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.TimePicker> e)
        {
            base.OnElementChanged(e);
            this.SetNativeControl(new Android.Widget.EditText(Forms.Context));
            this.Control.Click += Control_Click;
            this.Control.Text = DateTime.Now.ToString("HH:mm");
            this.Control.KeyListener = null;
            this.Control.FocusChange += Control_FocusChange;
        }

        void Control_FocusChange(object sender, Android.Views.View.FocusChangeEventArgs e)
        {
            if (e.HasFocus)
            {
                ShowTimePicker();
                ElementController.SetValueFromRenderer(VisualElement.IsFocusedPropertyKey, true);
            }
            else
            {
                ElementController.SetValueFromRenderer(VisualElement.IsFocusedPropertyKey, false);
            }
        }

        void Control_Click(object sender, EventArgs e)
        {
            ShowTimePicker();
        }

        private void ShowTimePicker()
        {
            if (dialog == null)
            {
                dialog = new TimePickerDialog(Forms.Context, this, DateTime.Now.Hour, DateTime.Now.Minute, true);
            }

            dialog.Show();
        }

        public void OnTimeSet(Android.Widget.TimePicker view, int hourOfDay, int minute)
        {
            var time = new TimeSpan(hourOfDay, minute, 0);
            this.Element.SetValue(Xamarin.Forms.TimePicker.TimeProperty, time);

            this.Control.Text = time.ToString(@"hh\:mm");

            this.ClearFocus();
        }
    }
}

Xamarin.Forms 2.5+ Answer

Xamarin.Forms v2.5 deprecated Forms.Context and also requires an overloaded constructor to be used for Custom Renderers.

To replace Forms.Context, we'll need to install the Plugin.CurrentActivity NuGet Package.

using System;

using Android.App;
using Android.Content;
using Android.Runtime;

using TimePickerDemo.CustomControls;
using TimePickerDemo.Droid;

using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;

[assembly: ExportRenderer(typeof(CustomTimePicker24H), typeof(CustomTimePicker24HRenderer))]
namespace TimePickerDemo.Droid
{
    public class CustomTimePicker24HRenderer : ViewRenderer<Xamarin.Forms.TimePicker, Android.Widget.EditText>, TimePickerDialog.IOnTimeSetListener, IJavaObject, IDisposable
    {
        private TimePickerDialog dialog = null;

        public CustomTimePicker24HRenderer(Context context) : base(context)
        {

        }

        Context CurrentContext => Plugin.CurrentActivity.CrossCurrentActivity.Current.Activity;
        IElementController ElementController => Element as IElementController;

        protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.TimePicker> e)
        {
            base.OnElementChanged(e);
            this.SetNativeControl(new Android.Widget.EditText(CurrentContext));
            this.Control.Click += Control_Click;
            this.Control.Text = DateTime.Now.ToString("HH:mm");
            this.Control.KeyListener = null;
            this.Control.FocusChange += Control_FocusChange;
        }

        void Control_FocusChange(object sender, Android.Views.View.FocusChangeEventArgs e)
        {
            if (e.HasFocus)
            {
                ShowTimePicker();
                ElementController.SetValueFromRenderer(VisualElement.IsFocusedPropertyKey, true);
            }
            else
            {
                ElementController.SetValueFromRenderer(VisualElement.IsFocusedPropertyKey, false);
            }
        }

        void Control_Click(object sender, EventArgs e)
        {
            ShowTimePicker();
        }

        private void ShowTimePicker()
        {
            if (dialog == null)
            {
                dialog = new TimePickerDialog(CurrentContext, this, DateTime.Now.Hour, DateTime.Now.Minute, true);
            }

            dialog.Show();
        }

        public void OnTimeSet(Android.Widget.TimePicker view, int hourOfDay, int minute)
        {
            var time = new TimeSpan(hourOfDay, minute, 0);
            this.Element.SetValue(Xamarin.Forms.TimePicker.TimeProperty, time);

            this.Control.Text = time.ToString(@"hh\:mm");

            this.ClearFocus();
        }
    }
}


来源:https://stackoverflow.com/questions/49158815/24-hours-timepicker-with-focused-and-unfocused-events

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!