如何实现间隔为30分钟的Xamarin Forms Timepicker?
实现30分钟间隔的Xamarin Forms TimePicker
嘿,很高兴你已经搞定了把TimePicker改成Spinner模式,还有15分钟间隔的版本!要改成30分钟间隔其实非常简单,咱们基于你现有的代码调整就行,我给你一步步拆解:
第一步:自定义带间隔属性的TimePicker控件
先创建一个继承自TimePicker的自定义控件,添加一个Interval属性,这样不仅能实现30分钟间隔,以后要改其他间隔也更灵活:
using Xamarin.Forms; namespace YourAppNamespace.Controls { public class CustomTimePicker : TimePicker { public static readonly BindableProperty IntervalProperty = BindableProperty.Create( nameof(Interval), typeof(int), typeof(CustomTimePicker), defaultValue: 30, // 默认30分钟间隔 propertyChanged: OnIntervalChanged); public int Interval { get => (int)GetValue(IntervalProperty); set => SetValue(IntervalProperty, value); } private static void OnIntervalChanged(BindableObject bindable, object oldValue, object newValue) { // 可选:添加间隔值的合法性校验,比如必须是60的约数 if (newValue is int interval && (interval <= 0 || 60 % interval != 0)) { throw new ArgumentException("Interval must be a positive divisor of 60"); } } } }
第二步:Android端自定义渲染器
Android端需要手动修改Spinner的分钟选项列表,你之前实现15分钟间隔时应该已经有类似逻辑,现在把间隔改成30就行:
using Android.Content; using Android.Widget; using YourAppNamespace.Controls; using YourAppNamespace.Droid.Renderers; using Xamarin.Forms; using Xamarin.Forms.Platform.Android; [assembly: ExportRenderer(typeof(CustomTimePicker), typeof(CustomTimePickerRenderer))] namespace YourAppNamespace.Droid.Renderers { public class CustomTimePickerRenderer : TimePickerRenderer { public CustomTimePickerRenderer(Context context) : base(context) { } protected override void OnElementChanged(ElementChangedEventArgs<TimePicker> e) { base.OnElementChanged(e); if (Control == null || !(Element is CustomTimePicker customPicker)) return; // 确保保持Spinner模式(你之前已经实现这部分,这里再确认下) Control.SetIs24HourView(Java.Lang.Boolean.True); var androidTimePicker = (Android.Widget.TimePicker)Control; // 针对不同Android版本设置Spinner模式(你之前的代码应该已经覆盖了) if (Android.OS.Build.VERSION.SdkInt >= Android.OS.BuildVersionCodes.M) { androidTimePicker.SetInputType(Android.Text.InputTypes.Null); } else { try { var delegateField = androidTimePicker.Class.GetDeclaredField("mTimePickerDelegate"); delegateField.Accessible = true; var spinnerDelegateClass = Java.Lang.Class.ForName("android.widget.TimePickerSpinnerDelegate"); if (delegateField.Get(androidTimePicker).Class != spinnerDelegateClass) { var constructor = spinnerDelegateClass.GetConstructor(typeof(Android.Widget.TimePicker), typeof(Context)); delegateField.Set(androidTimePicker, constructor.NewInstance(androidTimePicker, Context)); androidTimePicker.CurrentHour = Java.Lang.Integer.ValueOf(DateTime.Now.Hour); androidTimePicker.CurrentMinute = Java.Lang.Integer.ValueOf(DateTime.Now.Minute); } } catch (Exception ex) { // 可选:记录日志 } } // 核心:设置30分钟间隔的分钟选项 var minutePicker = androidTimePicker.FindViewById<NumberPicker>(Resources.GetIdentifier("minute", "id", "android")); if (minutePicker == null) return; int interval = customPicker.Interval; var minuteOptions = new List<int>(); // 生成0、30两个选项(30分钟间隔) for (int i = 0; i < 60; i += interval) { minuteOptions.Add(i); } minutePicker.MinValue = 0; minutePicker.MaxValue = minuteOptions.Count - 1; minutePicker.DisplayedValues = minuteOptions.Select(m => m.ToString("D2")).ToArray(); // 初始化选中最接近当前时间的选项 int currentMinute = customPicker.Time.Minute; int closestMinute = minuteOptions.OrderBy(m => Math.Abs(m - currentMinute)).First(); minutePicker.Value = minuteOptions.IndexOf(closestMinute); } } }
第三步:iOS端自定义渲染器
iOS端更简单,直接设置UIDatePicker的MinuteInterval属性就行:
using YourAppNamespace.Controls; using YourAppNamespace.iOS.Renderers; using UIKit; using Xamarin.Forms; using Xamarin.Forms.Platform.iOS; [assembly: ExportRenderer(typeof(CustomTimePicker), typeof(CustomTimePickerRenderer))] namespace YourAppNamespace.iOS.Renderers { public class CustomTimePickerRenderer : TimePickerRenderer { protected override void OnElementChanged(ElementChangedEventArgs<TimePicker> e) { base.OnElementChanged(e); if (Control == null || !(Element is CustomTimePicker customPicker)) return; var datePicker = (UIDatePicker)Control.InputView; datePicker.DatePickerMode = UIDatePickerMode.Time; datePicker.MinuteInterval = customPicker.Interval; // 直接设置为30 } } }
第四步:在XAML中使用
最后在你的XAML页面里引用这个自定义控件,设置Interval="30"即可:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:controls="clr-namespace:YourAppNamespace.Controls" x:Class="YourAppNamespace.Views.YourPage"> <StackLayout> <!-- 30分钟间隔的TimePicker --> <controls:CustomTimePicker Interval="30" /> </StackLayout> </ContentPage>
这样就搞定啦!本质上就是把15分钟间隔的选项列表从4个(0、15、30、45)改成2个(0、30),其他逻辑和你之前实现的15分钟版本几乎一致。
内容的提问来源于stack exchange,提问作者RMSPereira
相关产品推荐
相关产品推荐

