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

时间:2022-06-30 02:52:04

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内)的minutues间隔设置为15分钟。我已经看到有一个与TimePicker相关的15分钟间隔问题的帖子,但我不知道如何将它应用于TimePickerDialog,因为我不知道如何使用它在TimePickerDialog中创建的TimePicker。我是Android新手,完全迷失在这件事上。提前致谢。

4 个解决方案

#1


13  

Using a combination of this from @Rizwan and this other 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 TimePickerDialog and TimePicker classes and it doesn't appear to be

使用@Rizwan和其他线程的组合,我提出了一个组合解决方案,允许在TimePickerDialog中任意分钟增量。主要问题是大多数功能都是由android TimePickerDialog和TimePicker类隐藏的,它似乎不是

  1. Extend TimePickerDialog to allow us easier access
  2. 扩展TimePickerDialog以便于我们访问
  3. Use reflection to reach inside the display and access the required bits (see below)
  4. 使用反射到达显示器内部并访​​问所需的位(见下文)
  5. rewire the minute 'NumberPicker' to display our values
  6. 重新连接分钟'NumberPicker'以显示我们的值
  7. rewire the TimePicker to receive and return values form the NumberPicker honoring our custom increment.
  8. 重新连接TimePicker以接收和返回NumberPicker中的值,以表达我们的自定义增量。
  9. block onStop() so that it doesn't reset the value on close.
  10. 阻止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的名称也不能保证永远相同。话虽如此,这是一个有效,稳定的解决方案,并且可能在可预见的未来发挥作用。在我看来,空的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();
            }
        }
    }

}

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

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

onCreate uses 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字段和反射的名称来发现当前位置。这又省略了错误检查,应该是“故障安全”,即如果出现问题则恢复默认行为。

onClick overridden to return the correct minute value to the callback listener

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

onStop overridden 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源代码。

#2


8  

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

#3


1  

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

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

#4


0  

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

#1


13  

Using a combination of this from @Rizwan and this other 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 TimePickerDialog and TimePicker classes and it doesn't appear to be

使用@Rizwan和其他线程的组合,我提出了一个组合解决方案,允许在TimePickerDialog中任意分钟增量。主要问题是大多数功能都是由android TimePickerDialog和TimePicker类隐藏的,它似乎不是

  1. Extend TimePickerDialog to allow us easier access
  2. 扩展TimePickerDialog以便于我们访问
  3. Use reflection to reach inside the display and access the required bits (see below)
  4. 使用反射到达显示器内部并访​​问所需的位(见下文)
  5. rewire the minute 'NumberPicker' to display our values
  6. 重新连接分钟'NumberPicker'以显示我们的值
  7. rewire the TimePicker to receive and return values form the NumberPicker honoring our custom increment.
  8. 重新连接TimePicker以接收和返回NumberPicker中的值,以表达我们的自定义增量。
  9. block onStop() so that it doesn't reset the value on close.
  10. 阻止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的名称也不能保证永远相同。话虽如此,这是一个有效,稳定的解决方案,并且可能在可预见的未来发挥作用。在我看来,空的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();
            }
        }
    }

}

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

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

onCreate uses 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字段和反射的名称来发现当前位置。这又省略了错误检查,应该是“故障安全”,即如果出现问题则恢复默认行为。

onClick overridden to return the correct minute value to the callback listener

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

onStop overridden 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源代码。

#2


8  

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

#3


1  

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

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

#4


0  

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