时间select器秒

我使用Xamarin Forms和我的应用程序中的某个地方,我需要用户能够以HH:mm:ss格式input时间。 所以,基本上我需要一个这样的控制:

时间选择器秒

通过使用自定义的iOS渲染,我已经能够从TimePicker中删除AM / PM部分来实现这样的事情:

在这里输入图像说明

这是我的渲染器代码:

public class TimePickerSecondsRenderer : TimePickerRenderer { protected override void OnElementChanged(ElementChangedEventArgs<TimePicker> e) { base.OnElementChanged(e); var timePicker = (UIDatePicker)Control.InputView; timePicker.Locale = new NSLocale("CA"); } } 

我认为这是朝着正确的方向迈出的一小步,但是在添加第三列的秒数以及每列的标签方面,我真的感到不知所措。

我看了一下这个post,但是到目前为止还没有真正帮到我。

有没有人设法通过Xamarin Forms项目来实现这种控制? 你介意分享一些指针吗?

我终于得到了一个工作的实施。 结果如下:

在这里输入图像说明

唯一的缺点是标签“hr”,“min”和“sec”在他们自己的专栏中。 因此,如果用户试图与他们交互,则会有反弹的效果。 我会试着看看我以后能不能改进。 build议欢迎!

当然,代码(如果它可以被某人使用):

渲染器

 [assembly: ExportRendererAttribute(typeof(MyTimePicker), typeof(MyTimePickerRenderer))] namespace MyProject.iOS.Renderers { public class MyTimePickerRenderer : PickerRenderer { internal static IDevice Device; internal const int ComponentCount = 6; private const int _labelSize = 30; private MyTimePicker _myTimePicker; public MyTimePickerRenderer() { // This is dependent on XForms (see Update note) Device = Resolver.Resolve<IDevice>(); } protected override void OnElementChanged (ElementChangedEventArgs<Picker> e) { base.OnElementChanged (e); if (Control != null) { Control.BorderStyle = UITextBorderStyle.None; _myTimePicker = e.NewElement as MyTimePicker; var customModelPickerView = new UIPickerView { Model = new MyTimePickerView(_myTimePicker) }; SelectPickerValue(customModelPickerView, _myTimePicker); CreatePickerLabels(customModelPickerView); Control.InputView = customModelPickerView; } } private void SelectPickerValue(UIPickerView customModelPickerView, MyTimePicker myTimePicker) { customModelPickerView.Select(new nint(myTimePicker.SelectedTime.Hours), 0, false); customModelPickerView.Select(new nint(myTimePicker.SelectedTime.Minutes), 2, false); customModelPickerView.Select(new nint(myTimePicker.SelectedTime.Seconds), 4, false); } private void CreatePickerLabels(UIPickerView customModelPickerView) { nfloat verticalPosition = (customModelPickerView.Frame.Size.Height / 2) - (_labelSize / 2); nfloat componentWidth = new nfloat(Device.Display.Width / ComponentCount / Device.Display.Scale); var hoursLabel = new UILabel(new CGRect(componentWidth, verticalPosition, _labelSize, _labelSize)); hoursLabel.Text = "hrs"; var minutesLabel = new UILabel(new CGRect((componentWidth * 3) + (componentWidth / 2), verticalPosition, _labelSize, _labelSize)); minutesLabel.Text = "mins"; var secondsLabel = new UILabel(new CGRect((componentWidth * 5) + (componentWidth / 2), verticalPosition, _labelSize, _labelSize)); secondsLabel.Text = "secs"; customModelPickerView.AddSubview(hoursLabel); customModelPickerView.AddSubview(minutesLabel); customModelPickerView.AddSubview(secondsLabel); } protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) { base.OnElementPropertyChanged(sender, e); if (Control == null) { return; } if (e.PropertyName == "SelectedIndex") { var customModelPickerView = (UIPickerView)Control.InputView; SelectPickerValue(customModelPickerView, _myTimePicker); } } public class MyTimePickerView : UIPickerViewModel { private readonly MyTimePicker _myTimePicker; public MyTimePickerView(MyTimePicker picker) { _myTimePicker = picker; } public override nint GetComponentCount(UIPickerView pickerView) { return new nint(MyTimePickerRenderer.ComponentCount); } public override nint GetRowsInComponent(UIPickerView pickerView, nint component) { if (component == 0) { // Hours return new nint(24); } if (component % 2 != 0) { // Odd components are labels for hrs, mins and secs return new nint(1); } // Minutes & seconds return new nint(60); } public override string GetTitle(UIPickerView pickerView, nint row, nint component) { if (component == 0) { return row.ToString(); } else if (component == 1) { return null; } else if (component == 3) { return null; } else if (component == 5) { return null; } return row.ToString("00"); } public override void Selected(UIPickerView pickerView, nint row, nint component) { var selectedHours = pickerView.SelectedRowInComponent(0); var selectedMinutes = pickerView.SelectedRowInComponent(2); var selectedSeconds = pickerView.SelectedRowInComponent(4); var time = new TimeSpan((int)selectedHours, (int)selectedMinutes, (int)selectedSeconds); _myTimePicker.SelectedTime = time; } public override nfloat GetComponentWidth(UIPickerView pickerView, nint component) { var screenWidth = MyTimePickerRenderer.Device.Display.Width; var componentWidth = screenWidth / MyTimePickerRenderer.ComponentCount / MyTimePickerRenderer.Device.Display.Scale; return new nfloat(componentWidth); } } } 

自定义可绑定select器类

 public class MyTimePicker : Picker { public static readonly BindableProperty SelectedTimeProperty = BindableProperty.Create<MyTimePicker, TimeSpan>(p => p.SelectedTime, TimeSpan.MinValue, BindingMode.TwoWay,propertyChanged: OnSelectedTimePropertyPropertyChanged); public MyTimePicker() { // Ugly hack since Xamarin Forms' Picker uses only one component internally // This is a list of all possible timespan from 0:00:00 to 23:59:59 for (int hour = 0; hour < 24; hour++) { for (int minute = 0; minute < 60; minute ++) { for (int second = 0; second < 60; second++) { Items.Add(string.Format("{0:D2}:{1:D2}:{2:D2}", hour, minute, second)); } } } base.SelectedIndexChanged += (o, e) => { if (base.SelectedIndex < 0) { SelectedTime = TimeSpan.MinValue; return; } int index = 0; foreach (var item in Items) { if (index == SelectedIndex) { SelectedTime = TimeSpan.Parse(item); break; } index++; } }; } public TimeSpan SelectedTime { get { return (TimeSpan)GetValue(SelectedTimeProperty); } set { SetValue(SelectedTimeProperty, value); } } private static void OnSelectedTimePropertyPropertyChanged(BindableObject bindable, TimeSpan value, TimeSpan newValue) { var picker = (MyTimePicker)bindable; var itemMatch = picker.Items.FirstOrDefault(x => x == newValue.ToString()); var index = picker.Items.IndexOf(itemMatch); picker.SelectedIndex = index; } } 

XAML用法

 <myControls:MyTimePicker SelectedTime="{Binding SelectedTime}" /> 

其中SelectedTime是您的ViewModel属性用于绑定。 必须是TimeSpantypes。

我相信它可以改善,所以如果你有任何build议,请留下评论。

UPDATE

我已经更新了渲染器代码。

  • “hrs”,“mins”和“secs”现在是标签,不再是自己的列。 这意味着用户不再可以与它们交互(不再有弹跳效果)
  • 我还修复了一个错误,如果从ViewModel设置了select器值,那么在打开键盘时,select仍然是00:00:00
  • 更好地支持iPhone Plus分辨率

请注意,此代码依赖于XForms( https://github.com/XLabs/Xamarin-Forms-Labs )获取设备屏幕大小,因为这是我用于我的项目的框架,但它可以很容易地改性。