6

我有一个 TimePickerDialog 用于设置时间,该时间设置为 TextView 以显示它。现在,我需要帮助将 TimePicker(在 TimePickerDialog 内)分钟间隔设置为 15 分钟。我看到有一篇与 TimePicker 相关的 15 分钟间隔问题的帖子,但我不知道如何将其应用于 TimePickerDialog,因为我不知道如何使用它在 TimePickerDialog 中创建的 TimePicker。我是 Android 新手,完全迷失在这件事上。提前致谢。

4

4 回答 4

15

使用来自@Rizwan 和这个其他线程的组合我想出了一个组合解决方案,它允许在TimePickerDialog. 主要问题是大部分功能都被 androidTimePickerDialogTimePickerclasses 隐藏了,而且它似乎不允许

  1. 扩展TimePickerDialog以使我们更容易访问
  2. 使用反射到达显示器内部并访​​问所需的位(见下文)
  3. 重新连接分钟'NumberPicker'以显示我们的值
  4. 重新连接TimePicker以接收和返回值,以NumberPicker尊重我们的自定义增量。
  5. 阻止onStop()以便它不会在关闭时重置值。

警告

到达 UI 内部的主要问题是元素被可能更改的 id 引用,甚至 id 的名称也不能保证永远相同。话虽如此,这是一个有效的、稳定的解决方案,并且可能在可预见的未来有效。在我看来,空的 catch 块应该警告 UI 已更改,并应回退到默认(增量 1 分钟)行为。

解决方案

    private class DurationTimePickDialog extends TimePickerDialog
    {
        final OnTimeSetListener mCallback;
        TimePicker mTimePicker;
        final int increment;

        public DurationTimePickDialog(Context context, OnTimeSetListener callBack, int hourOfDay, int minute, boolean is24HourView, int increment)
        {
            super(context, callBack, hourOfDay, minute/increment, is24HourView);
            this.mCallback = callBack;
            this.increment = increment;
        }

        @Override
        public void onClick(DialogInterface dialog, int which) {
                if (mCallback != null && mTimePicker!=null) {
                    mTimePicker.clearFocus();
                    mCallback.onTimeSet(mTimePicker, mTimePicker.getCurrentHour(),
                            mTimePicker.getCurrentMinute()*increment);
                }
        }

        @Override
        protected void onStop()
        {
            // override and do nothing
        }

        @Override
        protected void onCreate(Bundle savedInstanceState)
        {
            super.onCreate(savedInstanceState);
            try
            {
                Class<?> rClass = Class.forName("com.android.internal.R$id");
                Field timePicker = rClass.getField("timePicker");
                this.mTimePicker = (TimePicker)findViewById(timePicker.getInt(null));
                Field m = rClass.getField("minute");
                
                NumberPicker mMinuteSpinner = (NumberPicker)mTimePicker.findViewById(m.getInt(null));
                mMinuteSpinner.setMinValue(0);
                mMinuteSpinner.setMaxValue((60/increment)-1);
                List<String> displayedValues = new ArrayList<String>();
                for(int i=0;i<60;i+=increment)
                {
                    displayedValues.add(String.format("%02d", i));
                }
                mMinuteSpinner.setDisplayedValues(displayedValues.toArray(new String[0]));
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
        }
    }

}

构造函数接受增量值并保留一些其他引用。请注意,这省略了错误检查,我们更喜欢60%increment==0

onCreate使用 UI 字段的名称和反射来发现当前位置。同样,这省略了错误检查,并且应该是“故障安全”的,即如果出现问题,则恢复为默认行为。

重写onClick以将正确的分钟值返回给回调侦听器

onStop被覆盖以防止在对话框关闭时再次返回(不正确的)索引值。来吧,你自己试试。

其中大部分来自对 TimePickerDialog 源的深入研究。

安卓 11+ 更新

上面示例中使用的反射被标记为graylist-max-q,这意味着在 Android 10 (API 29 - Q) 之后将不再可能。在短期内(直到2021 年 8 月),可以将目标版本降回 API 29,同时仍针对 Android 11 (API 30 - R) 进行构建,但在此日期之后,Play 商店将不再接受这些构建,并将需要 API 30 作为构建目标。上述警告中已经预料到并指出了这种最终失败。

于 2013-11-14T05:18:56.317 回答
12

如果您使用时间选择器而不是时间选择器对话框,那很好。但实际上有一个解决方案..这是我用来满足相同要求的..我使用了CustomTimePickerDialog。一切都是一样的,只有 TimePickerDialog 会在代码中更改为 CustomTimePickerDialog。

CustomTimePickerDialog timePickerDialog = new CustomTimePickerDialog(myActivity.this, timeSetListener, 
            Calendar.getInstance().get(Calendar.HOUR), 
            CustomTimePickerDialog.getRoundedMinute(Calendar.getInstance().get(Calendar.MINUTE) + CustomTimePickerDialog.TIME_PICKER_INTERVAL), 
            false
);
timePickerDialog.setTitle("2. Select Time");
timePickerDialog.show();

这是我的 CustomTimePickerDialog 类...只需在您的项目中使用这个类并将 TimePickerDialog 更改为 CustomTimePickerDialog..

public class CustomTimePickerDialog extends TimePickerDialog{

    public static final int TIME_PICKER_INTERVAL=10;
    private boolean mIgnoreEvent=false;

    public CustomTimePickerDialog(Context context, OnTimeSetListener callBack, int hourOfDay, int minute,
        boolean is24HourView) {
    super(context, callBack, hourOfDay, minute, is24HourView);
    }
/*
 * (non-Javadoc)
 * @see android.app.TimePickerDialog#onTimeChanged(android.widget.TimePicker, int, int)
 * Implements Time Change Interval
 */
    @Override
    public void onTimeChanged(TimePicker timePicker, int hourOfDay, int minute) {
        super.onTimeChanged(timePicker, hourOfDay, minute);
        this.setTitle("2. Select Time");
        if (!mIgnoreEvent){
            minute = getRoundedMinute(minute);
            mIgnoreEvent=true;
            timePicker.setCurrentMinute(minute);
            mIgnoreEvent=false;
        }
    }

    public static int getRoundedMinute(int minute){
         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;
         }

        return minute;
    }
}

使用此 CustomTimePickerDialog 类后,您需要做的就是在代码中使用 CustomTimePickerDialog 而不是 TimePickerDialog 来访问/覆盖 TimePickerDialog 类的默认函数。简单来说,我的意思是你的 timeSetListener 在这之后将如下所示......

private CustomTimePickerDialog.OnTimeSetListener timeSetListener = new CustomTimePickerDialog.OnTimeSetListener() {
    @Override
    public void onTimeSet(TimePicker view, int hourOfDay, int minute) {

    }
}// using CustomTimePickerDialog
于 2012-04-02T06:44:14.540 回答
1

您可以使用常规 AlertDialog 并使用 setView 来包含自定义 TimePicker 视图。

于 2011-10-10T13:40:56.147 回答
1
/**
 * Set TimePicker interval by adding a custom minutes list
 * TIME_PICKER_INTERVAL = Enter your Minutes;
 * @param timePicker
 */
private void setTimePickerInterval(TimePicker timePicker) {
    try {
        int TIME_PICKER_INTERVAL = 10;
        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);
    }
}
于 2017-10-13T12:01:40.577 回答