Show TimePicker with minutes intervals in android
Solution 1
Use the following the custom class called CustomTimePickerDialog
, which I think solve your problem.
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();
}
}
}
Here is the demonstrating screenshot.
Solution 2
There is this awesome library MaterialDateTimePicker that creates beautiful styled material timepickers.
You can use one of the following methods to define your interval:
setSelectableTimes(Timepoint[] times) You can pass in an array of Timepoints. These values are the only valid selections in the picker. setMinTime(Timepoint time) and setMaxTime(Timepoint time) will further trim this list down.
setTimeInterval(int hourInterval, int minuteInterval, int secondInterval) Set the interval for selectable times in the TimePickerDialog. This is a convenience wrapper around setSelectableTimes
Solution 3
/**
* 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);
}
}
Solution 4
As @anddev84 said, you can do it with your own customized TimePickerDialog.
However, take a look of the source code you can find:
- TimePickerDialog is a frame layout, see this file. And it just contains a TimePicker
- The TimePicker widget is just a linear layout, see this file. And you can see the minute spinner is a NumberPicker
-
Refer to the code of NumberPicker, you will find it has a public method setDisplayedValues(String[] displayedValues)
/** * Sets the values to be displayed. * * @param displayedValues The displayed values. */ public void setDisplayedValues(String[] displayedValues)
So, with these information, I suppose you can simply customize your own time picker dialog with limited minutes displayed.
Solution 5
Struggled with 30 min interval more then hour. Might struggle more if wouldn't see the comment of @Lee. So just post a full code of dialog with 30 min interval:
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;
}
}
Sergio76
Updated on July 09, 2022Comments
-
Sergio76 almost 2 years
My application show a TimePickerDialog to set a time. I want that the timePickerDialog show the minutes with an interval of 5 minutes.
This works fine with this code:
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; } }
Although only minutes can be selected with an interval of five minutes, the timepickerdialog looks like:
do not know how the minutes also show the range of 5 minutes, as in this picture:
I have searched but can not find the solution.
-
Rajiv yadav over 10 yearsNumberPicker is not available in pre honeycomb. Suggest me some solution for that
-
arlomedia almost 10 yearsThis worked perfectly for me, thank you! I modified the constructor to take an interval argument and replaced the TIME_PICKER_INTERVAL constant with an interval variable ... but realistically I don't expect to ever need an interval other than 5.
-
Lee Yi Hong almost 10 yearsI works ok for 15 minutes interval but not on 30 minutes interval
-
Lee Yi Hong almost 10 yearsOk, I manage to solve the 30 minutes interval by adding a onTimeChanged check with last save hours and minutes. If both are different, it will only change the minutes instead of both of them by using
view.setCurrentHour(lastSavedHour)
. I am not sure if this is a good way of doing it... But if there are better solution do feel free to let me know :) -
otgw over 9 yearsI feel the need to clarify @LeeYiHong's comment because I was confused until I implemented it. It works. It just has an annoying bug. For example if you change from 14:00 to :30, the hour goes back to 13.
-
Leon Lucardie over 9 yearsThis piece of code doesn't work for the Android 5.0 version of the TimePickerDialog, since it doesn't use the NumberPicker widget for minute selection.
-
Ryan C about 9 years@LeonLucardie if you change the super call to be
super(context, TimePickerDialog.THEME_HOLO_LIGHT, callBack, hourOfDay, minute, is24HourView);
it will work with Android 5.0. Passing the theme makes it use the picker style timeDialog. I've submitted an edit to the answer. -
Stornu2 about 9 yearsTHANKS!! you are a genius
-
Khay about 9 years@LeonLucardie - this pice of code will work fine if you change your CustomTimePicker style in xml from clock to Analog . Although even i'm in need to find out which widget does time picker in clock style uses ? any idea anyone?
-
gellezzz almost 9 yearsYour TimePicker class have error: NumberPicker mMinuteSpinner = (NumberPicker) mMinuteSpinner.setMinValue(0);
-
MJim almost 9 yearsUps, you are right. I forgot a code line. Bug solved now. Thanks!
-
Fearghal almost 9 yearsHi - how do I init this class on th UI - do i init a it using a timepicker component eg CustomTimePickerDialog ctp = ...findViewById(R.id.timePicker); ?
-
Fearghal almost 9 yearsHow does this get attached to the UI, do i need a Time picker on in my xml layout?
-
MJim almost 9 yearsYou don't need any TimePicker in your xml layout. Just place a LinearLayout element at the position the TimePicker would be and let the Activity populate it as shown above.
-
John Sardinha about 8 yearsdoes that lib work on a fragment with another views in it, or just as a dialog?
-
Jeff Lockhart almost 8 yearsThis code works great, except there's one flaw. If
updateTime()
is called, the minutes are not normalized by dividing byTIME_PICKER_INTERVAL
before setting the minutes value on the TimePicker. -
Jeff Lockhart almost 8 yearsAlso, the implementation of
onClick()
has changed in the most recent versions of the API to handleBUTTON_NEGATIVE
. I'll update the answer to reflect these changes. -
Jeff Lockhart almost 8 yearsThis code also, inexplicably, doesn't work in 7.0 Nougat. The source code would seem it's mostly unchanged from 6.0.1 Marshmallow in terms of how it handles the
TimePickerMode
in the theme to choose betweenTimePickerSpinnerDelegate
andTimePickerClockDelegate
. But despite the mode being set to "spinner", on API 24 the clock layout is always used. This is an issue with the stockandroid.app.TimePickerDialog
though. -
Jeff Lockhart almost 8 yearsI created an issue in the Android bug tracker: code.google.com/p/android/issues/detail?id=222208
-
Jeff Lockhart almost 8 yearsI've written some workaround code for this issue with Nougat only displaying the clock. I can share if anyone else is experiencing the same problem.
-
Ghanshyam Nayma over 7 yearscan any one help me how to call this class. bcz simply I am calling this constructor and calling method dialog.show(). But getting exception android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running?
-
Ghanshyam Nayma over 7 yearscan any one help me how to call this class. bcz simply I am calling this constructor and calling method dialog.show(). But getting exception android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running?
-
Rajath over 7 years@JohnSardinha, it's a dialog based on the corresponding Android api, but needs an instance of the FragmentManager for it's show() function.
-
André Luiz Reis almost 6 yearsThis library works for me. Solved my problem. I can set intervals of 30 minutes, for example.
-
Daniel Wilson over 5 yearsI feel this will break in the future - Google is clamping down on accessing internals with reflection :(
-
Dan over 5 yearscan this lib be customized to use spinner instead of clock? Most solutions I have seen seem to use reflection and they do not work on all android versions.
-
user1510006 almost 5 yearsteam, I am getting this error, any help please. java.lang.NoSuchFieldException: TimePicker with Android 9 .
-
user1510006 almost 5 years@ Adrián Rivero : java.lang.NoSuchFieldException: TimePicker with Android 9 . I am getting this error, any help please.
-
user1510006 almost 5 years@ Yevhenii Kanivets , getting this error for Android 9 , any help please . java.lang.NoSuchFieldException: TimePicker
-
Yev Kanivets almost 5 years@user1510006 they've just changed the name of field to smth another (don't know which is the new name). This is exactly why reflection is the bad solution.
-
user1510006 almost 5 years@Yevhenii Kanivets , thank you for your reply, so, do we have another solution to keep the spinner UI ?
-
Riddhi Shah almost 5 yearshow can we achieve this in Clock Mode?
-
darkrider1287 over 4 yearsbeware that when retrieving the resulting time via an OnTimeChangedListener, the resulting "minute" var transmitted is INCORRECT, and will be equal to "minute selected / interval". for example, using an interval of 5 minutes, selecting 6:15 on the UI will yield an OnTimeChangedListener minute var of 3. 6:30 yields minute=6, etc.
-
Oluwasegun Wahaab over 4 years@RiddhiShah, this can be done in clock mode. Just omit the attribute TimePickerDialog.THEME_HOLO_LIGHT from the constructor and this makes the timepicker default to clock mode. your new call to super will be something like super(context, null, hourOfDay, minute / TIME_PICKER_INTERVAL, is24HourView);
-
Suresh Maidaragi almost 4 years@user1510006 try removing the line ` throw new RuntimeException(e);` from catch block this will work
-
arlomedia over 2 yearsWith compileSdkVersion 30 and Android 11, getting the minuteSpinner in onAttachedToWindow works differently:
mTimePicker = findViewById(Resources.getSystem().getIdentifier("timePicker", "id", "android"))
, thenval minuteSpinner = mTimePicker?.findViewById<NumberPicker>(Resources.getSystem().getIdentifier("minute", "id", "android"))
(Kotlin) -
ahmed saber about 2 yearsi have a problem when i make interval 30 For example if you change from 14:00 to :30, the hour goes back to 13.