在android中以分钟间隔显示时间选择器
我的应用程序显示一个TimePickerDialog来设置时间。 我希望timePickerDialog以5分钟的间隔显示分钟数 这适用于以下代码:在android中以分钟间隔显示时间选择器,android,intervals,android-timepicker,Android,Intervals,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 minut
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;
}
}
虽然间隔为五分钟时只能选择分钟,但timepickerdialog如下所示:
不知道分钟数如何显示5分钟的范围,如下图所示:
我已经搜索了,但找不到解决方案。查看
TimePickerDialog
的代码,它似乎没有给您提供一种直接修改TimePicker
的方法,然后将其显示给用户,您会看到图片中显示的“错误分钟数”。看
我的建议是创建自己的TimePickerDialog,基于Android的设计。一开始听起来可能让人望而生畏,但是
时间选择器
值以显示分钟数(如上所述),以及正如@anddev84所说,您可以使用自己定制的TimePickerDialog来完成 但是,请查看您可以找到的源代码:
因此,有了这些信息,我想您可以简单地自定义自己的时间选择器对话框,并显示有限的分钟。使用以下名为
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();
}
}
}
import java.lang.reflect.Field;
导入java.util.ArrayList;
导入java.util.List;
导入android.app.TimePickerDialog;
导入android.content.Context;
导入android.content.DialogInterface;
导入android.widget.NumberPicker;
导入android.widget.TimePicker;
公共类CustomTimePickerDialog扩展了TimePickerDialog{
专用最终静态整数时间选择器间隔=5;
私人时间选择器;
私有最终OnTimeSetListener MTTimeSetListener;
公共CustomTimePickerDialog(上下文上下文、OnTimeSetListener侦听器、,
int hourOfDay,int minute,布尔值为24小时视图){
super(上下文,TimePickerDialog.THEME\u HOLO\u LIGHT,null,hourOfDay,
分钟/时间\u选择器\u间隔,IS24小时视图);
mTimeSetListener=监听器;
}
@凌驾
public void updateTime(inthourofday,intminuteofhour){
mTimePicker.setCurrentHour(hourOfDay);
mTimePicker.setCurrentMinute(小时分钟/时间\u选择器\u间隔);
}
@凌驾
public void onClick(DialogInterface dialog,int which){
开关(哪个){
外壳按钮_正极:
如果(mTimeSetListener!=null){
mTimeSetListener.onTimeSet(mTimePicker,mTimePicker.getCurrentHour(),
mTimePicker.getCurrentMinute()*时间\u选取器\u间隔);
}
打破
外壳按钮\u负片:
取消();
打破
}
}
@凌驾
公共空间和附加的Towindow(){
super.onAttachedToWindow();
试一试{
Class classForid=Class.forName(“com.android.internal.R$id”);
Field timePickerField=classForid.getField(“timePicker”);
mTimePicker=(TimePicker)findviewbyd(timePickerField.getInt(null));
Field=classForid.getField(“分钟”);
NumberPicker分钟数Pinner=(NumberPicker)mTimePicker
.findviewbyd(field.getInt(null));
minuteSpinner.setMinValue(0);
minuteSpinner.setMaxValue((60次/选择器间隔)-1);
List displayedValues=new ArrayList();
对于(int i=0;i<60;i+=时间\u选择器\u间隔){
displayedValues.add(String.format(“%02d”,i));
}
minuteSpinner.setDisplayedValues(displayedValues
.toArray(新字符串[displayedValues.size()]);
}捕获(例外e){
e、 printStackTrace();
}
}
}
这是演示屏幕截图
基于上述Tanmay Mandal的回答,我为TimePicker小部件(而不是TimePickerDialog)实现了一个解决方案。这里的技巧是用活动布局中的原始TimePicker元素替换LinearLayout元素,以便以编程方式添加自定义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();
}
}
}
如果你不习惯在android 5+中使用相同的时间选择器(而不是时钟)对话框,只需更改主题即可。您可以直接在构造函数中更改:
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;
}
我对上面的优秀答案做了补充。它的问题是,至少在某些版本的Android中,当您更改所选时间时,它会用错误的时间值替换对话框标题。您不能重写有问题的方法updateTitle(),但可以在onTimeChanged()处截获调用,而不调用super或使用固定参数调用它
我键入了setTitle()方法是否是用非零字符串ID调用的,但是您可以为布尔值本身或其他任何东西使用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;
}
}
公共类IntervalTimePickerDialog扩展了TimePickerDialog{
私有静态最终字符串标记=“IntervalPickerDialog”;
专用最终静态整数时间选择器间隔=30;
私人时间选择器;
普里瓦特
@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;
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;
}
}
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);
}
}