java 如何在 Android 中的 TimePickerDialog 中设置自定义分钟间隔

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7713538/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 21:05:53  来源:igfitidea点击:

How to set a custom minutes interval in TimePickerDialog in Android

javaandroidintervalstimepicker

提问by jocherra

I have got a TimePickerDialog working to set time which is set to a TextView in order to display it. Now, I need help to set that TimePicker (inside the TimePickerDialog) minutues interval to 15 minutes. I have seen there is a post with 15 minutes interval issue related to TimePicker, but I don't know how to apply it to the TimePickerDialog because I don't know how to use the TimePicker that it is created inside the TimePickerDialog. I am new to Android and completely lost in this matter. Thanks in advance.

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

回答by David O'Meara

Using a combination of thisfrom @Rizwan and thisother thread, I came up with a combined solution that allows arbitrary minute increments in a TimePickerDialog. The main issue is that most of the functionality is hidden by the android TimePickerDialogand TimePickerclasses and it doesn't appear to be

使用的组合从@Rizwan和这个其他线程,我想出了一个综合的解决方案,允许任意分钟为单位的TimePickerDialog。主要问题是大部分功能都被 androidTimePickerDialogTimePicker类隐藏了,它似乎没有

  1. Extend TimePickerDialogto allow us easier access
  2. Use reflection to reach inside the display and access the required bits (see below)
  3. rewire the minute 'NumberPicker' to display our values
  4. rewire the TimePickerto receive and return values form the NumberPickerhonoring our custom increment.
  5. block onStop()so that it doesn't reset the value on close.
  1. 扩展TimePickerDialog以让我们更轻松地访问
  2. 使用反射到达显示器内部并访​​问所需的位(见下文)
  3. 重新连接分钟“NumberPicker”以显示我们的价值观
  4. 重新连接TimePicker以接收和返回值形成NumberPicker尊重我们的自定义增量。
  5. 阻止onStop()以便它不会在关闭时重置值。

Warning

警告

The main issue with reaching inside the UI is that elements are referenced by ids which are likely to change, and even the name of the id is not guaranteed to be the same forever. Having said that, this is working, stable solution and likely to work for the foreseeable future. In my opinion the empty catch block should warn that the UI has changed and should fall back to the default (increment 1 minute) behaviour.

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

Solution

解决方案

    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();
            }
        }
    }

}

constructoraccepts the increment value and retains some other references. Note that this omits error checking and we'd prefer 60%increment==0

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

onCreateuses the name of the UI fields and reflection to discover the current location. Again this omits error checking and should be 'fail-safe' ie revert to default behaviour if something goes wrong.

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

onClickoverridden to return the correct minute value to the callback listener

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

onStopoverridden to prevent the (incorrect) index value being returned a second time, when the dialog closes. Go on, try it yourself.

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

Most of this comes from digging into the TimePickerDialog source.

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

回答by Rizwan Sohaib

well thats fine if you used time-picker instead of time-picker-dialog. But there is a solution for this actually.. here is what I used to meet the same requirement.. I used CustomTimePickerDialog. Every thing will be same, only TimePickerDialog will change to CustomTimePickerDialog in the code.

如果您使用时间选择器而不是时间选择器对话框,那很好。但实际上有一个解决方案..这是我用来满足相同要求的..我使用了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();

Here is my CustomTimePickerDialog class... Just use this class in your project and change TimePickerDialog to CustomTimePickerDialog..

这是我的 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;
    }
}

After using this CustomTimePickerDialog class, All you will need to do is use CustomTimePickerDialog instead of TimePickerDialog in your code to access/override default functions of TimePickerDialog class. In the simple way, I mean your timeSetListener will be as following after this...

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

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

    }
}// using CustomTimePickerDialog

回答by njzk2

You can use a regular AlertDialog and use setView to include a custom TimePicker view.

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

回答by Tharik ahamed

/**
 * 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);
    }
}