在android中以分钟间隔显示TimePicker

我的应用程序显示一个TimePickerDialog来设置一个时间。 我希望timePickerDialog以5分钟的间隔显示分钟。

这与这个代码工作正常:

private final int TIME_PICKER_INTERVAL=5; private boolean mIgnoreEvent=false; … public TimePickerDialogs(Context arg0, OnTimeSetListener callBack, int hourOfDay, int minute, boolean is24HourView) { super(arg0, callBack, hourOfDay, minute, is24HourView); formato=Statics.formato; } @Override public void onTimeChanged(TimePicker view, int hourOfDay, int minute) { //super.onTimeChanged(arg0, arg1, arg2); if (mIgnoreEvent) return; if (minute%TIME_PICKER_INTERVAL!=0){ int minuteFloor=minute-(minute%TIME_PICKER_INTERVAL); minute=minuteFloor + (minute==minuteFloor+1 ? TIME_PICKER_INTERVAL : 0); if (minute==60) minute=0; mIgnoreEvent=true; view.setCurrentMinute(minute); mIgnoreEvent=false; } } 

尽pipe只能以5分钟的间隔select分钟,但timepickerdialog看起来像:

小时和分钟

不知道如何分钟也能显示5分钟的范围,如图所示:

小时和分钟 -  5

我已经search,但无法find解决scheme。

使用下面的自定义类称为CustomTimePickerDialog ,我认为解决您的问题。

 import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; import android.app.TimePickerDialog; import android.content.Context; import android.content.DialogInterface; import android.widget.NumberPicker; import android.widget.TimePicker; public class CustomTimePickerDialog extends TimePickerDialog { private final static int TIME_PICKER_INTERVAL = 5; private TimePicker mTimePicker; private final OnTimeSetListener mTimeSetListener; public CustomTimePickerDialog(Context context, OnTimeSetListener listener, int hourOfDay, int minute, boolean is24HourView) { super(context, TimePickerDialog.THEME_HOLO_LIGHT, null, hourOfDay, minute / TIME_PICKER_INTERVAL, is24HourView); mTimeSetListener = listener; } @Override public void updateTime(int hourOfDay, int minuteOfHour) { mTimePicker.setCurrentHour(hourOfDay); mTimePicker.setCurrentMinute(minuteOfHour / TIME_PICKER_INTERVAL); } @Override public void onClick(DialogInterface dialog, int which) { switch (which) { case BUTTON_POSITIVE: if (mTimeSetListener != null) { mTimeSetListener.onTimeSet(mTimePicker, mTimePicker.getCurrentHour(), mTimePicker.getCurrentMinute() * TIME_PICKER_INTERVAL); } break; case BUTTON_NEGATIVE: cancel(); break; } } @Override public void onAttachedToWindow() { super.onAttachedToWindow(); try { Class<?> classForid = Class.forName("com.android.internal.R$id"); Field timePickerField = classForid.getField("timePicker"); mTimePicker = (TimePicker) findViewById(timePickerField.getInt(null)); Field field = classForid.getField("minute"); NumberPicker minuteSpinner = (NumberPicker) mTimePicker .findViewById(field.getInt(null)); minuteSpinner.setMinValue(0); minuteSpinner.setMaxValue((60 / TIME_PICKER_INTERVAL) - 1); List<String> displayedValues = new ArrayList<>(); for (int i = 0; i < 60; i += TIME_PICKER_INTERVAL) { displayedValues.add(String.format("%02d", i)); } minuteSpinner.setDisplayedValues(displayedValues .toArray(new String[displayedValues.size()])); } catch (Exception e) { e.printStackTrace(); } } } 

这里是演示的截图。

在这里输入图像描述

有这个真棒库MaterialDateTimePicker创build美丽的风格材料时间select器。

您可以使用以下方法之一来定义您的时间间隔:

  • setSelectableTimes(Timepoint [] times)您可以传递一组时间点。 这些值是选取器中唯一有效的select。 setMinTime(Timepoint time)和setMaxTime(Timepoint time)将进一步修剪这个列表。

  • setTimeInterval(int hourInterval,int minInterval,int secondInterval)设置TimePickerDialog中可选时间的间隔。 这是setSelectableTimes方便的包装

正如@dedev84所说,你可以用你自己定制的TimePickerDialog来做到这一点。

不过,看看你可以find的源代码:

  1. TimePickerDialog是一个框架布局,请参阅此文件 。 它只包含一个TimePicker
  2. TimePicker小部件只是一个线性布局,请参阅此文件 。 你可以看到微调是一个NumberPicker
  3. 参考NumberPicker的代码,你会发现它有一个公共方法setDisplayedValues(String [] displayedValues)

     /** * Sets the values to be displayed. * * @param displayedValues The displayed values. */ public void setDisplayedValues(String[] displayedValues) 

所以,有了这些信息,我想你可以简单地定制你自己的时间select器对话框,并显示有限的分钟数。

查看TimePickerDialog的代码,它没有出现,他们给你一个方法来直接修改TimePicker然后它显示给用户,你看到“错误的分钟”,你在图片中显示。 请参阅TimePickerDialog.java

我的build议是创build您自己的TimePickerDialog,将devise从Androiddevise中解放出来。 起初可能听起来令人望而生畏,但是

  1. 通过这种方式,您可以自定义实现,包括初始化TimePicker值以显示分钟(如上所述),还可以
  2. 它实际上不应该很难,Android TimePickerDialog.java本身只有160行,非常易于pipe理。

我已经对上面接受的答案做了一个补充。 问题在于,至less在某些版本的Android中,当您更改选定的时间时,它将用不正确的时间值replace对话框标题。 你不能重写违规方法updateTitle(),但是你可以在onTimeChanged()方法上拦截调用,不要调用super或者用固定的参数来调用它。

我将setTitle()方法用非零的stringID键入,但是你可以为布尔本身或其他types设置一个getter / setter。

 @Override public void onTimeChanged(TimePicker view, int hourOfDay, int minute) { if (autoTitle) { // Super will call a private updateTitle() method, so lets make // sure it has the right minute value. super.onTimeChanged(view, hourOfDay, minute * TIME_PICKER_INTERVAL); } else { // do nothing } } @Override public void setTitle(int id) { super.setTitle(id); autoTitle = (id == 0); } ... private boolean autoTitle = true; 

每隔30分钟挣扎一小时。 如果没有看到@Lee的评论,可能会更加挣扎。 所以只需发表完整的30分钟对话代码:

 public class IntervalTimePickerDialog extends TimePickerDialog { private static final String TAG = "IntervalPickerDialog"; private final static int TIME_PICKER_INTERVAL = 30; private TimePicker timePicker; private final OnTimeSetListener callback; private int lastHour = -1; private int lastMinute = -1; public IntervalTimePickerDialog(Context context, int themeId, OnTimeSetListener callBack, int hourOfDay, int minute, boolean is24HourView) { super(context, themeId, callBack, hourOfDay, minute / TIME_PICKER_INTERVAL, is24HourView); lastHour = hourOfDay; lastMinute = minute; this.callback = callBack; } @Override public void onClick(DialogInterface dialog, int which) { if (callback != null && timePicker != null) { timePicker.clearFocus(); callback.onTimeSet(timePicker, timePicker.getCurrentHour(), timePicker.getCurrentMinute() * TIME_PICKER_INTERVAL); } } @Override protected void onStop() { } @Override public void onAttachedToWindow() { super.onAttachedToWindow(); try { Class<?> classForid = Class.forName("com.android.internal.R$id"); Field timePickerField = classForid.getField("timePicker"); this.timePicker = (TimePicker) findViewById(timePickerField.getInt(null)); Field field = classForid.getField("minute"); NumberPicker mMinuteSpinner = (NumberPicker) timePicker.findViewById(field.getInt(null)); mMinuteSpinner.setMinValue(0); mMinuteSpinner.setMaxValue((60 / TIME_PICKER_INTERVAL) - 1); List<String> displayedValues = new ArrayList<>(); for (int i = 0; i < 60; i += TIME_PICKER_INTERVAL) { displayedValues.add(String.format("%02d", i)); } mMinuteSpinner.setDisplayedValues(displayedValues.toArray(new String[0])); } catch (Exception e) { e.printStackTrace(); } } @Override public void onTimeChanged(TimePicker view, int hourOfDay, int minute) { super.onTimeChanged(view, hourOfDay, minute); if (lastHour != hourOfDay && lastMinute != minute) { view.setCurrentHour(lastHour); lastMinute = minute; } else { lastHour = hourOfDay; lastMinute = minute; } } 

上面的答案对老版本的Android来说确实很好,但是在Android 7 Nougat中对我来说却不起作用,基本上dateselect器完全改变为使用时钟模式…我将这里提出的代码与https ://gist.github.com/jeffdgr8/6bc5f990bf0c13a7334ce385d482af9f ,那么它默认设置TimePickerDialog的模式来显示微调控件,它运行的代码只显示15分钟的间隔在我的情况。

代码张贴在这里https://gist.github.com/smaugho/14dae83f3284fa05455ee0a9e4f13099

 public class CustomTimePickerDialog extends TimePickerDialog { private final static int TIME_PICKER_INTERVAL = 15; private TimePicker timePicker; private final OnTimeSetListener callback; public HorekoTimePicker(Context context, OnTimeSetListener callBack, int hourOfDay, int minute, boolean is24HourView) { super(context, callBack, hourOfDay, minute/TIME_PICKER_INTERVAL, is24HourView); this.callback = callBack; fixSpinner(context, hourOfDay, minute, is24HourView); } /** * Workaround for this bug: https://code.google.com/p/android/issues/detail?id=222208 * In Android 7.0 Nougat, spinner mode for the TimePicker in TimePickerDialog is * incorrectly displayed as clock, even when the theme specifies otherwise, such as: * * <resources> * <style name="Theme.MyApp" parent="Theme.AppCompat.Light.NoActionBar"> * <item name="android:timePickerStyle">@style/Widget.MyApp.TimePicker</item> * </style> * * <style name="Widget.MyApp.TimePicker" parent="android:Widget.Material.TimePicker"> * <item name="android:timePickerMode">spinner</item> * </style> * </resources> * * May also pass TimePickerDialog.THEME_HOLO_LIGHT as an argument to the constructor, * as this theme has the TimePickerMode set to spinner. * * Taken from: https://gist.github.com/jeffdgr8/6bc5f990bf0c13a7334ce385d482af9f */ 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 final int MODE_SPINNER = 1; 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) 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 { // TimePickerSpinnerDelegate was initially misnamed TimePickerClockDelegate in API 21! spinnerDelegateClass = Class.forName("android.widget.TimePickerClockDelegate"); } // In 7.0 Nougat for some reason the timePickerMode is ignored and the delegate is 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); } setTimeIntervals(); } } 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; } @Override protected void onStop() { } /* * Feature #363: (Un)availability times in 15min interval * https://abix.webhop.net/redmine/issues/363 * Solution extracted from * http://stackoverflow.com/questions/20214547/show-timepicker-with-minutes-intervals-in-android */ @Override public void onClick(DialogInterface dialog, int which) { super.onClick(dialog, which); if (callback != null && timePicker != null) { timePicker.clearFocus(); callback.onTimeSet(timePicker, timePicker.getCurrentHour(), timePicker.getCurrentMinute()*TIME_PICKER_INTERVAL); } } private void setTimeIntervals() { try { Class<?> classForid = Class.forName("com.android.internal.R$id"); Field field = classForid.getField("minute"); NumberPicker mMinuteSpinner = (NumberPicker) timePicker.findViewById(field.getInt(null)); mMinuteSpinner.setMinValue(0); mMinuteSpinner.setMaxValue((60 / TIME_PICKER_INTERVAL) - 1); List<String> displayedValues = new ArrayList<String>(); for (int i = 0; i < 60; i += TIME_PICKER_INTERVAL) { displayedValues.add(String.format("%02d", i)); } mMinuteSpinner.setDisplayedValues(displayedValues.toArray(new String[0])); } catch (Exception e) { e.printStackTrace(); } } 

}

 /** * Set TimePicker interval by adding a custom minutes list * * @param timePicker */ private void setTimePickerInterval(TimePicker timePicker) { try { NumberPicker minutePicker = (NumberPicker) timePicker.findViewById(Resources.getSystem().getIdentifier( "minute", "id", "android")); minutePicker.setMinValue(0); minutePicker.setMaxValue((60 / TIME_PICKER_INTERVAL) - 1); List<String> displayedValues = new ArrayList<String>(); for (int i = 0; i < 60; i += TIME_PICKER_INTERVAL) { displayedValues.add(String.format("%02d", i)); } minutePicker.setDisplayedValues(displayedValues.toArray(new String[0])); } catch (Exception e) { Log.e(TAG, "Exception: " + e); } } 

基于上面显示的Tanmay Mandal的回答,我已经实现了TimePicker Widget(而不是TimePickerDialog)的解决scheme。 这里的技巧是用一个LinearLayout元素的活动布局replace原始的TimePicker元素,以便以编程方式添加我们的自定义TimePicker。 看下面的例子:

 import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; import android.content.Context; import android.widget.NumberPicker; import android.widget.TimePicker; public class MyTimePicker extends TimePicker { private static final int TIME_PICKER_INTERVAL = 5; public MyTimePicker(Context context) { super(context); } @Override public Integer getCurrentMinute() { return super.getCurrentMinute()*TIME_PICKER_INTERVAL; } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); try { Class<?> classForid = Class.forName("com.android.internal.R$id"); Field field = classForid.getField("minute"); NumberPicker mMinuteSpinner = (NumberPicker) findViewById(field.getInt(null)); mMinuteSpinner.setMinValue(0); mMinuteSpinner.setMaxValue((60 / TIME_PICKER_INTERVAL) - 1); List<String> displayedValues = new ArrayList<String>(); for (int i = 0; i < 60; i += TIME_PICKER_INTERVAL) displayedValues.add(String.format("%02d", i)); mMinuteSpinner.setDisplayedValues(displayedValues.toArray(new String[0])); } catch (Exception e) { e.printStackTrace(); } } } 

而对于我们的活动:

  @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); LinearLayout ll = (LinearLayout) findViewById(R.id.myLinearLayout); ll.removeAllViews(); MyTimePicker tp = new MyTimePicker(this); tp.setIs24HourView(true); Calendar cal = Calendar.getInstance(); // Current time tp.setCurrentHour(cal.get(Calendar.HOUR_OF_DAY)); tp.setCurrentMinute(cal.get(Calendar.MINUTE)/5); // Aprox current minute ll.addView(tp); } 

如果你不想在android 5+中使用同一时间select器(不是时钟)对话框,只需更改主题。 您可以直接在构造函数中进行更改:

  public CustomTimePickerDialog(Context context, OnTimeSetListener callBack, int hourOfDay, int minute, boolean is24HourView, int time_interval) { super(context, TimePickerDialog.THEME_HOLO_LIGHT, callBack, hourOfDay, minute / time_interval, is24HourView); this.TIME_PICKER_INTERVAL = time_interval; this.callback = callBack; }