我们尝试在Xamarin android中将TimerPickerDialog与Number Picker一起使用。由于我们有15分钟的时间间隔
在Android 10中-getMinute()
返回Null
var classForid = Java.Lang.Class.ForName("com.android.internal.R$id");
var timePickerField = classForid.GetField("timePicker");
[![timePicker][1]][1] = (TimePicker)FindViewById(timePickerField.GetInt(null));
var field = classForid.GetField("minute");
NumberPicker minuteSpinner = (NumberPicker)timePicker
.FindViewById(field.GetInt(null));
minuteSpinner.MinValue = 0;
minuteSpinner.MaxValue = (60 / TimePickerInterval) - 1;
List<string> displayedValues = new List<string>();
for (int i = 0; i < 60; i += TimePickerInterval)
{
displayedValues.Add(i.ToString());
}
minuteSpinner.SetDisplayedValues(displayedValues.ToArray());
我们需要获取分钟选择器。截图:
尝试创建自定义TimePickerDialog
,这是一个简单的示例,您可以检查一下:
创建CustomTimePickerDialog:
public class CustomTimePickerDialog : TimePickerDialog
{
private int _interval = 1;
public CustomTimePickerDialog(Context context, EventHandler<TimeSetEventArgs> callBack, int hourOfDay, int minute, bool is24HourView, int interval)
: base(context, ThemeHoloLight, (sender, e) =>
{
callBack(sender, new TimeSetEventArgs(e.HourOfDay, e.Minute * interval));
}, hourOfDay, minute / interval, is24HourView)
{
_interval = interval;
FixSpinner(context, hourOfDay, minute, is24HourView);
}
protected CustomTimePickerDialog(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
{
}
public override void SetView(Android.Views.View view)
{
base.SetView(view);
}
void SetupMinutePicker(Android.Views.View view)
{
var numberPicker = FindMinuteNumberPicker(view as ViewGroup);
if (numberPicker != null)
{
int i = _interval;
List<string> values = new List<string>();
values.Add("00");
while (i < 60)
{
if (i < 10)
values.Add("0" + i);
else
values.Add(i.ToString());
i += _interval;
}
numberPicker.MinValue = 0;
numberPicker.MaxValue = values.Count - 1;
numberPicker.SetDisplayedValues(values.ToArray());
}
}
protected override void OnCreate(Android.OS.Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
GetButton((int)DialogButtonType.Negative).Visibility = Android.Views.ViewStates.Gone;
this.SetCanceledOnTouchOutside(false);
}
private NumberPicker FindMinuteNumberPicker(ViewGroup viewGroup)
{
for (var i = 0; i < viewGroup.ChildCount; i++)
{
var child = viewGroup.GetChildAt(i);
var numberPicker = child as NumberPicker;
if (numberPicker != null)
{
if (numberPicker.MaxValue == 59)
{
return numberPicker;
}
}
var childViewGroup = child as ViewGroup;
if (childViewGroup != null)
{
var childResult = FindMinuteNumberPicker(childViewGroup);
if (childResult != null)
return childResult;
}
}
return null;
}
private void FixSpinner(Context context, int hourOfDay, int minute, bool is24HourView)
{
try
{
// Get the theme's android:timePickerMode
int MODE_SPINNER = 1;
var styleableClass = Java.Lang.Class.ForName("com.android.internal.R$styleable");
var timePickerStyleableField = styleableClass.GetField("TimePicker");
int[] timePickerStyleable = (int[])timePickerStyleableField.Get(null);
var a = context.ObtainStyledAttributes(null, timePickerStyleable, Android.Resource.Attribute.TimePickerStyle, 0);
var timePickerModeStyleableField = styleableClass.GetField("TimePicker_timePickerMode");
int timePickerModeStyleable = timePickerModeStyleableField.GetInt(null);
int mode = a.GetInt(timePickerModeStyleable, MODE_SPINNER);
a.Recycle();
Android.Widget.TimePicker timePicker = (Android.Widget.TimePicker)findField(Java.Lang.Class.FromType(typeof(TimePickerDialog)), Java.Lang.Class.FromType(typeof(Android.Widget.TimePicker)), "mTimePicker").Get(this);
var delegateClass = Java.Lang.Class.ForName("android.widget.TimePicker$TimePickerDelegate");
var delegateField = findField(Java.Lang.Class.FromType(typeof(Android.Widget.TimePicker)), delegateClass, "mDelegate");
var delegatee = delegateField.Get(timePicker);
Java.Lang.Class spinnerDelegateClass;
if (Build.VERSION.SdkInt != BuildVersionCodes.Lollipop)
{
spinnerDelegateClass = Java.Lang.Class.ForName("android.widget.TimePickerSpinnerDelegate");
}
else
{
// TimePickerSpinnerDelegate was initially misnamed TimePickerClockDelegate in API 21!
spinnerDelegateClass = Java.Lang.Class.ForName("android.widget.TimePickerClockDelegate");
}
// In 7.0 Nougat for some reason the timePickerMode is ignored and the delegate is TimePickerClockDelegate
if (delegatee.Class != spinnerDelegateClass)
{
delegateField.Set(timePicker, null); // throw out the TimePickerClockDelegate!
timePicker.RemoveAllViews(); // remove the TimePickerClockDelegate views
var spinnerDelegateConstructor = spinnerDelegateClass.GetConstructors()[0];
spinnerDelegateConstructor.Accessible = true;
// Instantiate a TimePickerSpinnerDelegate
delegatee = spinnerDelegateConstructor.NewInstance(timePicker, context, null, Android.Resource.Attribute.TimePickerStyle, 0);
delegateField.Set(timePicker, delegatee); // set the TimePicker.mDelegate to the spinner delegate
// Set up the TimePicker again, with the TimePickerSpinnerDelegate
timePicker.SetIs24HourView(Java.Lang.Boolean.ValueOf(is24HourView));
timePicker.Hour = hourOfDay;
timePicker.Minute = minute;
timePicker.SetOnTimeChangedListener(this);
}
// set interval
SetupMinutePicker(timePicker);
}
catch (Exception e)
{
throw new Java.Lang.RuntimeException(e.ToString());
}
}
private static Java.Lang.Reflect.Field findField(Java.Lang.Class objectClass, Java.Lang.Class fieldClass, String expectedName)
{
try
{
var field = objectClass.GetDeclaredField(expectedName);
field.Accessible = true;
return field;
}
catch (Java.Lang.NoSuchFieldException e) { } // ignore
// search for it if it wasn't found under the expected ivar name
foreach (var searchField in objectClass.GetDeclaredFields())
{
if (Java.Lang.Class.FromType(searchField.GetType()) == fieldClass)
{
searchField.Accessible = true;
return searchField;
}
}
return null;
}
}
像这样打电话:
CustomTimePickerDialog timePickerDlg = new CustomTimePickerDialog(this, new EventHandler<TimePickerDialog.TimeSetEventArgs>((o,e)=> { }),
hourOfDay, minute, true,15);// the 15 is the minute interval
timePickerDlg.Show();