郎朗坤
对于lolipop和更高版本的android,您可以使用此修改过的RangeTimePickerDialog类(从lolipop,Timepicker默认使用时钟模式(材料设计),因此旧的自定义类将无法使用。我们可以将模式更改为Spinner以获取最新版本,并可以重用该类)public class RangeTimePickerDialog extends TimePickerDialog { private int minHour = -1; private int minMinute = -1; private int maxHour = 25; private int maxMinute = 25; private int currentHour = 0; private int currentMinute = 0; private Calendar calendar = Calendar.getInstance(); private DateFormat dateFormat; public RangeTimePickerDialog(Context context, int dialogTheme, OnTimeSetListener callBack, int hourOfDay, int minute, boolean is24HourView) { super(context, callBack, hourOfDay, minute, is24HourView); currentHour = hourOfDay; currentMinute = minute; dateFormat = DateFormat.getTimeInstance(DateFormat.SHORT); fixSpinner(context, hourOfDay, minute, is24HourView); try { Class<?> superclass = getClass().getSuperclass(); Field mTimePickerField = superclass.getDeclaredField("mTimePicker"); mTimePickerField.setAccessible(true); TimePicker mTimePicker = (TimePicker) mTimePickerField.get(this); mTimePicker.setOnTimeChangedListener(this); } catch (NoSuchFieldException e) { } catch (IllegalArgumentException e) { } catch (IllegalAccessException e) { } } public void setMin(int hour, int minute) { minHour = hour; minMinute = minute; } public void setMax(int hour, int minute) { maxHour = hour; maxMinute = minute; } @Override public void onTimeChanged(TimePicker view, int hourOfDay, int minute) { boolean validTime = true; if (hourOfDay < minHour || (hourOfDay == minHour && minute < minMinute)){ validTime = false; } if (hourOfDay > maxHour || (hourOfDay == maxHour && minute > maxMinute)){ validTime = false; } if (validTime) { currentHour = hourOfDay; currentMinute = minute; } updateTime(currentHour, currentMinute); updateDialogTitle(view, currentHour, currentMinute); } private void updateDialogTitle(TimePicker timePicker, int hourOfDay, int minute) { calendar.set(Calendar.HOUR_OF_DAY, hourOfDay); calendar.set(Calendar.MINUTE, minute); String title = dateFormat.format(calendar.getTime()); setTitle(title); } private void fixSpinner(Context context, int hourOfDay, int minute, boolean is24HourView) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { // android:timePickerMode spinner and clock began in Lollipop try { // Get the theme's android:timePickerMode //two modes are available clock mode and spinner mode ... selecting spinner mode for latest versions final int MODE_SPINNER = 2; Class<?> styleableClass = Class.forName("com.android.internal.R$styleable"); Field timePickerStyleableField = styleableClass.getField("TimePicker"); int[] timePickerStyleable = (int[]) timePickerStyleableField.get(null); final TypedArray a = context.obtainStyledAttributes(null, timePickerStyleable, android.R.attr.timePickerStyle, 0); Field timePickerModeStyleableField = styleableClass.getField("TimePicker_timePickerMode"); int timePickerModeStyleable = timePickerModeStyleableField.getInt(null); final int mode = a.getInt(timePickerModeStyleable, MODE_SPINNER); a.recycle(); if (mode == MODE_SPINNER) { TimePicker timePicker = (TimePicker) findField(TimePickerDialog.class, TimePicker.class, "mTimePicker").get(this); Class<?> delegateClass = Class.forName("android.widget.TimePicker$TimePickerDelegate"); Field delegateField = findField(TimePicker.class, delegateClass, "mDelegate"); Object delegate = delegateField.get(timePicker); Class<?> spinnerDelegateClass; if (Build.VERSION.SDK_INT != Build.VERSION_CODES.LOLLIPOP) { spinnerDelegateClass = Class.forName("android.widget.TimePickerSpinnerDelegate"); } else { spinnerDelegateClass = Class.forName("android.widget.TimePickerClockDelegate"); } if (delegate.getClass() != spinnerDelegateClass) { delegateField.set(timePicker, null); // throw out the TimePickerClockDelegate! timePicker.removeAllViews(); // remove the TimePickerClockDelegate views Constructor spinnerDelegateConstructor = spinnerDelegateClass.getConstructor(TimePicker.class, Context.class, AttributeSet.class, int.class, int.class); spinnerDelegateConstructor.setAccessible(true); // Instantiate a TimePickerSpinnerDelegate delegate = spinnerDelegateConstructor.newInstance(timePicker, context, null, android.R.attr.timePickerStyle, 0); delegateField.set(timePicker, delegate); // set the TimePicker.mDelegate to the spinner delegate // Set up the TimePicker again, with the TimePickerSpinnerDelegate timePicker.setIs24HourView(is24HourView); timePicker.setCurrentHour(hourOfDay); timePicker.setCurrentMinute(minute); timePicker.setOnTimeChangedListener(this); } } } catch (Exception e) { throw new RuntimeException(e); } } } private static Field findField(Class objectClass, Class fieldClass, String expectedName) { try { Field field = objectClass.getDeclaredField(expectedName); field.setAccessible(true); return field; } catch (NoSuchFieldException e) {} // ignore // search for it if it wasn't found under the expected ivar name for (Field searchField : objectClass.getDeclaredFields()) { if (searchField.getType() == fieldClass) { searchField.setAccessible(true); return searchField; } } return null; }}
米脂
您可以以此为起点。我扩展了TimePickerDialog并添加了2个方法setMin和setMax。在onTimeChanged方法中,我检查新时间相对于最小/最大时间是否有效。它仍然需要抛光...public class BoundTimePickerDialog extends TimePickerDialog { private int minHour = -1, minMinute = -1, maxHour = 100, maxMinute = 100; private int currentHour, currentMinute; public BoundTimePickerDialog(Context context, OnTimeSetListener callBack, int hourOfDay, int minute, boolean is24HourView) { super(context, callBack, hourOfDay, minute, is24HourView); } public void setMin(int hour, int minute) { minHour = hour; minMinute = minute; } public void setMax(int hour, int minute) { maxHour = hour; maxMinute = minute; } @Override public void onTimeChanged(TimePicker view, int hourOfDay, int minute) { super.onTimeChanged(view, hourOfDay, minute); boolean validTime; if(hourOfDay < minHour) { validTime = false; } else if(hourOfDay == minHour) { validTime = minute >= minMinute; } else if(hourOfDay == maxHour) { validTime = minute <= maxMinute; } else { validTime = true; } if(validTime) { currentHour = hourOfDay; currentMinute = minute; } else { updateTime(currentHour, currentMinute); } }}