24小时时间选择器选择时间

时间:2018-03-14 13:40:34

标签: xamarin.forms xamarin.android

我尝试在XF项目中实施24小时Time Picker给定here

此问题也是之前解决的FocusUnfocused事件的问题,请参阅here

现在我想设置Time PickerFocused的时间,比如我已经将{2}小时绑定到应该打开的Time属性并且选择了2小时,这是行不通的

我注意到上一次在Time Picker上被绑定(时间已被选中且点击了Ok),但我希望选中绑定的Time。 我正在使用Xamarin Forms 2.5.0.121934

Android渲染器

我使用了Constant.TimeToBeShowOnPicker.HoursConstant.TimeToBeShowOnPicker.Minutes 在代码中绑定Time else的第一个值,默认情况下它是0:00 hrs或你设置的任何值。

public class TimePicker24Hours : 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, Constant.TimeToBeShowOnPicker.Hours, Constant.TimeToBeShowOnPicker.Minutes, 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 XAML

<TimePicker x:Name="time_Picker" Time="{Binding SelectedTime}" IsVisible="false" PropertyChanged="TimePicker_PropertyChanged" />

当要求Time PickerFocus

时,会调用此方法
void EditTime_Tapped(object sender, System.EventArgs e)
{
    var eventArgs = e as TappedEventArgs;
    ViewModel.SelectedTaskItem = (SomeModel)eventArgs.Parameter;

    ViewModel.SelectedTime = TimeSpan.FromHours(ViewModel.SomeModel.Time);
    Constant.TimeToBeShowOnPicker = ViewModel.SelectedTime;

    Device.BeginInvokeOnMainThread(() =>
    {
        time_Picker.Focus();
    });
}

1 个答案:

答案 0 :(得分:1)

答案

要确保点按时间选择器时显示当前时间,我们需要在UpdateTime中加入ShowPicker()

默认时间值

我还注意到Control.Text始终默认为DateTime.Now。要解决此问题,我们只需在Control.Text中设置OnElementChanged

我已更新自定义渲染器以检查是否设置了Element.Time,如果已设置,则我们可以设置Control.Text = Element.Time.ToString(@"hh\:mm");

示例应用

我在这里创建了一个使用这个24小时时间选择器的示例Xamarin.Forms应用程序: https://github.com/brminnick/24HourTimePicker

iOS自定义渲染器

using System;

using Foundation;

using TimePickerDemo;
using TimePickerDemo.iOS;

using UIKit;

using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;

[assembly: ExportRenderer(typeof(CustomTimePicker24H), typeof(CustomTimePicker24HRenderer))]
namespace TimePickerDemo.iOS
{
    public class CustomTimePicker24HRenderer : TimePickerRenderer
    {
        protected override void OnElementChanged(ElementChangedEventArgs<TimePicker> e)
        {
            base.OnElementChanged(e);

            if (Control != null)
            {
                var timePicker = (UIDatePicker)Control.InputView;
                timePicker.Locale = new NSLocale("no_nb");

                if (Element != null && !Element.Time.Equals(default(TimeSpan)))
                    Control.Text = Element.Time.ToString(@"hh\:mm");
                else
                    Control.Text = DateTime.Now.ToString("HH:mm");
            }
        }
    }
}

Android自定义渲染器

using System;

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

using Java.Lang;

using TimePickerDemo;
using TimePickerDemo.Droid;

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

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

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

        }

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

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

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

            ClearFocus();
        }

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

            SetNativeControl(new Android.Widget.EditText(CurrentContext));

            if (Control != null)
            {
                Control.Click += Control_Click;
                Control.FocusChange += Control_FocusChange;

                if (Element != null && !Element.Time.Equals(default(TimeSpan)))
                    Control.Text = Element.Time.ToString(@"hh\:mm");
                else
                    Control.Text = DateTime.Now.ToString("HH:mm");
            }
        }

        void Control_FocusChange(object sender, 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();

        void ShowTimePicker()
        {
            if (_dialog == null)
                _dialog = new TimePickerDialog(CurrentContext, this, Element.Time.Hours, Element.Time.Minutes, true);

            _dialog.UpdateTime(Element.Time.Hours, Element.Time.Minutes);

            _dialog.Show();
        }
    }
}