[android.widget.TimePicker $ TimePickerDelegate.getMinute()'上的空对象引用

问题描述 投票:0回答:1

我们尝试在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());

我们需要获取分钟选择器。截图:

Screenshot of the error

xamarin xamarin.android
1个回答
0
投票

尝试创建自定义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();
© www.soinside.com 2019 - 2024. All rights reserved.