24小时TimePicker与聚焦和非聚焦事件

时间:2018-03-07 18:21:47

标签: c# xamarin.forms xamarin.android

我尝试在XF项目中实施此处24 Hour TimePicker所提供的24小时Time Picker

但它并没有触发Android上的FocusUnfocused事件。有没有人实现过这个?

1 个答案:

答案 0 :(得分:3)

解释

此自定义控件的作者忘记在Android自定义渲染器中触发FocusedUnfocused

我们可以在ElementController.SetValueFromRenderer(VisualElement.IsFocusedPropertyKey, [true/false]);触发时通过Android自定义渲染器调用FocusChanged来触发这些事件。

此自定义Android控件在设置时间后也无法清晰对焦,因此我们也会ClearFocus()添加OnTimeSet

Xamarin.Forms 2.4 Code

因为样本是用Xamarin.Forms v2.4编写的,所以如果你继续使用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+回答

Xamarin.Forms v2.5已弃用Forms.Context,并且还需要将重载的构造函数用于自定义渲染器。

要替换Forms.Context,我们需要安装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();
        }
    }
}