Android TimePickerDialog设置最长时间

时间:2012-11-22 16:02:08

标签: android timepicker

我正在寻找一种方法来设置Android TimePickerDialog上的maximun和minimun时间选择,并将默认的分钟间隔从1分钟更改为5分钟,

我觉得这很简单,但我找不到办法!

9 个答案:

答案 0 :(得分:35)

这个答案已经过时

它不适用于Android 5或更高版本。


这是小提琴手答案的延伸。 不知何故,onTimeChangedListener在某些Android版本中没有被TimePickerDialog设置:

离。 http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.2.1_r1.2/android/app/TimePickerDialog.java

永远不会调用onTimeChanged方法! 目前这个问题的最佳解决方案是使用来自fiddler的min / max逻辑编写自定义TimePickerDialog。

更难看的是这个。 (使用反射添加侦听器) 我还会更新标题以显示当前选定的时间。

package com.mysuger.android.dialogs;

import java.lang.reflect.Field;
import java.text.DateFormat;
import java.util.Calendar;

import android.app.TimePickerDialog;
import android.content.Context;
import android.widget.TimePicker;

/**
 * A time dialog that allows setting a min and max time.
 * 
 */
public class RangeTimePickerDialog extends TimePickerDialog {

private int minHour = -1;
private int minMinute = -1;

private int maxHour = 25;
private int maxMinute = 25;

private int currentHour = 0;
private int currentMinute = 0;

private Calendar calendar = Calendar.getInstance();
private DateFormat dateFormat;


public RangeTimePickerDialog(Context context, OnTimeSetListener callBack, int hourOfDay, int minute, boolean is24HourView) {
    super(context, callBack, hourOfDay, minute, is24HourView);
    currentHour = hourOfDay;
    currentMinute = minute;
    dateFormat = DateFormat.getTimeInstance(DateFormat.SHORT);

    try {
        Class<?> superclass = getClass().getSuperclass();
        Field mTimePickerField = superclass.getDeclaredField("mTimePicker");
        mTimePickerField.setAccessible(true);
        TimePicker mTimePicker = (TimePicker) mTimePickerField.get(this);
        mTimePicker.setOnTimeChangedListener(this);
    } catch (NoSuchFieldException e) {
    } catch (IllegalArgumentException e) {
    } catch (IllegalAccessException e) {
    }
}

public void setMin(int hour, int minute) {
    minHour = hour;
    minMinute = minute;
}

public void setMax(int hour, int minute) {
    maxHour = hour;
    maxMinute = minute;
}

@Override
public void onTimeChanged(TimePicker view, int hourOfDay, int minute) {

    boolean validTime = true;
    if (hourOfDay < minHour || (hourOfDay == minHour && minute < minMinute)){
        validTime = false;
    }

    if (hourOfDay  > maxHour || (hourOfDay == maxHour && minute > maxMinute)){
        validTime = false;
    }

    if (validTime) {
        currentHour = hourOfDay;
        currentMinute = minute;
    }

    updateTime(currentHour, currentMinute);
    updateDialogTitle(view, currentHour, currentMinute);
}

private void updateDialogTitle(TimePicker timePicker, int hourOfDay, int minute) {
    calendar.set(Calendar.HOUR_OF_DAY, hourOfDay);
    calendar.set(Calendar.MINUTE, minute);
    String title = dateFormat.format(calendar.getTime());
    setTitle(title);
}
 }

答案 1 :(得分:8)

对于lolipop及更高版本的android,你可以使用这个修改过的RangeTimePickerDialog类

(从lolipop,Timepicker默认使用时钟模式(材料设计),以便旧的自定义类不起作用。我们可以将模式更改为spinner以获取最新版本并可以重用该类)

['1', [('2', '100')]]
['3', [('4', '300')], [('5', '400')], [('6', '500')]]
['7', [('8', '700')], [('9', '800')]]

答案 2 :(得分:5)

您可以将此作为起点。

我扩展了TimePickerDialog并添加了2个方法setMinsetMax

onTimeChanged方法中,我检查新时间相对于最小/最大时间是否有效。

它仍然需要一些抛光......

public class BoundTimePickerDialog extends TimePickerDialog {

    private int minHour = -1, minMinute = -1, maxHour = 100, maxMinute = 100;

    private int currentHour, currentMinute;

    public BoundTimePickerDialog(Context context, OnTimeSetListener callBack, int hourOfDay, int minute, boolean is24HourView) {
        super(context, callBack, hourOfDay, minute, is24HourView);
    }

    public void setMin(int hour, int minute) {
        minHour = hour;
        minMinute = minute;
    }

    public void setMax(int hour, int minute) {
        maxHour = hour;
        maxMinute = minute;
    }

    @Override
    public void onTimeChanged(TimePicker view, int hourOfDay, int minute) {
        super.onTimeChanged(view, hourOfDay, minute);

        boolean validTime;
        if(hourOfDay < minHour) {
            validTime = false;
        }
        else if(hourOfDay == minHour) {
            validTime = minute >= minMinute;
        }
        else if(hourOfDay == maxHour) {
            validTime = minute <= maxMinute;
        }
        else {
            validTime = true;
        }

        if(validTime) {
            currentHour = hourOfDay;
            currentMinute = minute;
        }
        else {
            updateTime(currentHour, currentMinute);
        }
    }
}

答案 3 :(得分:2)

重新考虑了fiddler的代码:

public class RangeTimePickerDialog extends TimePickerDialog {

    private int mMinHour = -1;
    private int mMinMinute = -1;
    private int mMaxHour = 100;
    private int mMaxMinute = 100;
    private int mCurrentHour;
    private int mCurrentMinute;

    public RangeTimePickerDialog(Context context, OnTimeSetListener callBack, int hourOfDay, 
        int minute, boolean is24HourView) {
        super(context, callBack, hourOfDay, minute, is24HourView);
        mCurrentHour = hourOfDay;
        mCurrentMinute = minute;
        // Somehow the onTimeChangedListener is not set by TimePickerDialog
        // in some Android Versions, so, Adding the listener using
        // reflections
        try {
            Class<?> superclass = getClass().getSuperclass();
            Field mTimePickerField = superclass.getDeclaredField("mTimePicker");
            mTimePickerField.setAccessible(true);
            TimePicker mTimePicker = (TimePicker) mTimePickerField.get(this);
            mTimePicker.setOnTimeChangedListener(this);
        } catch (NoSuchFieldException e) {
        } catch (IllegalArgumentException e) {
        } catch (IllegalAccessException e) {
        }
    }

    public void setMin(int hour, int minute) {
        mMinHour = hour;
        mMinMinute = minute;
    }

    public void setMax(int hour, int minute) {
        mMaxHour = hour;
        mMaxMinute = minute;
    }

    @Override
    public void onTimeChanged(TimePicker view, int hourOfDay, int minute) {
        super.onTimeChanged(view, hourOfDay, minute);
        boolean validTime;
        if (((hourOfDay < mMinHour ) || (hourOfDay == mMinHour && minute < mMinMinute)) 
                || ((hourOfDay > mMaxHour) || (hourOfDay == mMaxHour && minute > mMaxMinute))) {
            validTime = false;
        } else {
            validTime = true;
        }
        if (validTime) {
            mCurrentHour = hourOfDay;
            mCurrentMinute = minute;
        } else {
            updateTime(mCurrentHour, mCurrentMinute);
        }
    }
}

答案 4 :(得分:1)

没有本地方法来设置最大/最小时间,但是如果扩展onTimeChangedupdateTime,它可能会起作用,可以防止将时间设置为超出边界的值。

答案 5 :(得分:1)

您可以使用带反射的自定义TimePicker来设置值。

 @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(5);
        mMinuteSpinner.setMaxValue((60 / timeInterval) - 1);

        List<String> displayedValues = new ArrayList<>();
        for (int i = 0; i < 60; i += timeInterval)
            displayedValues.add(String.format("%02d", i));
        mMinuteSpinner.setDisplayedValues(displayedValues.toArray(new String[0]));

        mMinuteSpinner.setWrapSelectorWheel(true);

    } catch (Exception e) {
        e.printStackTrace();
    }

}

所以你可以设置你想要的值

答案 6 :(得分:0)

希望这可能会有所帮助。我使用了Joda时间库。

public class RangeTimePicker extends TimePicker implements
        TimePicker.OnTimeChangedListener {

    private int mMinHour = -1;

    private int mMinMinute = -1;

    private int mMaxHour = 25;

    private int mMaxMinute = 61;

    private int mCurrentHour;

    private int mCurrentMinute;


    public RangeTimePicker(Context context) {
        super(context);
        setOnTimeChangedListener(this);
    }

    public RangeTimePicker(Context context, AttributeSet attrs) {
        super(context, attrs);
        setOnTimeChangedListener(this);
    }

    public RangeTimePicker(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        setOnTimeChangedListener(this);
    }

    public void setMaxTime(int hourIn24, int minute) {
        mMaxHour = hourIn24;
        mMaxMinute = minute;

        LocalTime currentTime = LocalTime.now();
        LocalTime maxTime = new LocalTime(mMaxHour, mMaxMinute);

        if (currentTime.isAfter(maxTime)) {
            this.setCurrentHour(mCurrentHour = currentTime.getHourOfDay());
            this.setCurrentMinute(
                    mCurrentMinute = currentTime.getMinuteOfHour());
        }

    }

    public void setMinTime(int hourIn24, int minute) {
        mMinHour = hourIn24;
        mMinMinute = minute;

        LocalTime currentTime = LocalTime.now();
        LocalTime minTime = new LocalTime(mMinHour, mMinMinute);

        if (currentTime.isBefore(minTime)) {
            this.setCurrentHour(mCurrentHour = minTime.getHourOfDay());
            this.setCurrentMinute(mCurrentMinute = minTime.getMinuteOfHour());
        }
    }


    @Override
    public void onTimeChanged(TimePicker view, int hourOfDay, int minute) {
        boolean validTime = true;
        if (hourOfDay < mMinHour || (hourOfDay == mMinHour
                && minute < mMinMinute)) {
            validTime = false;
        }

        if (hourOfDay > mMaxHour || (hourOfDay == mMaxHour
                && minute > mMaxMinute)) {
            validTime = false;
        }

        if (validTime) {
            mCurrentHour = hourOfDay;
            mCurrentMinute = minute;
        }

        setCurrentHour(mCurrentHour);
        setCurrentMinute(mCurrentMinute);

    }
}

答案 7 :(得分:0)

希望这项工作能与我完美配合......

设置时间选择器的最长时间。

        timePicker.setOnTimeChangedListener(new TimePicker.OnTimeChangedListener() {
        @Override
        public void onTimeChanged(TimePicker view, int hourOfDay, int minute) {

            if (!mIsOnTimeChanged) {
                mIsOnTimeChanged = true;

                Calendar c = Calendar.getInstance();

                //get the selected day if it is before today allow AM and PM trick
                //else apply rules


                int selected_year = datePicker.getYear();
                int selected_month = datePicker.getMonth();
                int selected_day = datePicker.getDayOfMonth();


                int today = c.get(Calendar.DAY_OF_MONTH);
                int year = c.get(Calendar.YEAR);
                int month = c.get(Calendar.MONTH);


                int hour = c.get(Calendar.HOUR);
                hour += 12;
                int min = c.get(Calendar.MINUTE);

                //Check if user enter hh | mm | more than current reset the timePicker with the current time

                //http://stackoverflow.com/questions/2659954/timepickerdialog-and-am-or-pm

                if ((hourOfDay == hour | hour < hourOfDay | hourOfDay > hour | hour > hourOfDay | minute > min) && (selected_month == month && selected_day == today && selected_year == year)) {

                    int AM_PM_Value = hourOfDay;

                    Calendar datetime = Calendar.getInstance();

                    int hour_without_24 = (hour - 12);
                    if ((datetime.get(Calendar.AM_PM) == Calendar.AM) && (hourOfDay > hour_without_24)) {
                        //set AM
                        timePicker.setCurrentHour(hour - 12);
                    }

                    if (hourOfDay == (hour - 12) && minute > min) {
                        timePicker.setCurrentMinute(min);

                    }

                    if (hourOfDay > hour && datetime.get(Calendar.AM_PM) != Calendar.AM) {
                        timePicker.setCurrentHour(hour);

                        if (minute > min) {
                            timePicker.setCurrentMinute(min);

                        }
                    }


                } else if (selected_month != month | selected_day != today | selected_year != year) {

                } else if (hourOfDay == hour && minute > min) {
                    timePicker.setCurrentMinute(min);
                } else if (hourOfDay > hour) {
                    timePicker.setCurrentHour(hour);

                    if (minute > min) {
                        timePicker.setCurrentMinute(min);

                    }
                }
                //
                isTimePickerChanged = true;
                String AM_PM;
                if (hourOfDay < 12) {
                    AM_PM = "AM";
                } else {
                    AM_PM = "PM";
                }

                //to set as 12 hour
                time_format = (hourOfDay + ":" + minute + ":" + "00");

                if (hourOfDay > 12) {
                    hourOfDay = (hourOfDay - 12);
                }

                st_time = (hourOfDay + ":" + pad(minute) + " " + AM_PM);

                mIsOnTimeChanged = false;

            }


        }
    });

答案 8 :(得分:-1)

我把@Zarooka的解决方案作为起点。 我想我发现了一个bug。如果你的开始时间已经超出范围,那么你就不能再移动了,因为任何“onChanged”都被拒绝了。 这就是我在设置分钟/最大值时扩展setMax和setMin以便进入有效范围的原因。

package de.appdream.garooda.view;

import java.util.Calendar;
import java.util.Date;

import android.app.TimePickerDialog;
import android.content.Context;
import android.text.format.DateFormat;
import android.widget.TimePicker;

import java.lang.reflect.Field; 


public class GaroodaTimePickerDialog extends TimePickerDialog {

private int minHour = -1;
private int minMinute = -1;

private int maxHour = 25;
private int maxMinute = 61;

private int currentHour = 0;
private int currentMinute = 0;

    private Calendar calendar = Calendar.getInstance();
    //private DateFormat dateFormat;

public GaroodaTimePickerDialog(Context context, OnTimeSetListener callBack, int hour, int minute,
        boolean is24HourView) {
    super(context, callBack, hour, minute, is24HourView);

    currentHour = hour;
    currentMinute = minute;
    //dateFormat = DateFormat.getTimeInstance(DateFormat.SHORT);

    try {
        Class<?> superclass = getClass().getSuperclass();
        Field mTimePickerField = superclass.getDeclaredField("mTimePicker");
        mTimePickerField.setAccessible(true);
        TimePicker mTimePicker = (TimePicker) mTimePickerField.get(this);
        mTimePicker.setOnTimeChangedListener(this);
    } catch (NoSuchFieldException e) {
    } catch (IllegalArgumentException e) {
    } catch (IllegalAccessException e) {
    }
}







public void setMin(int hour, int minute) {
    minHour = hour;
    minMinute = minute;

    Calendar min = Calendar.getInstance();
    Calendar existing = Calendar.getInstance();

    min.set(Calendar.HOUR_OF_DAY, minHour);
    min.set(Calendar.MINUTE, minMinute);

    existing.set(Calendar.HOUR_OF_DAY, currentHour);
    existing.set(Calendar.MINUTE, currentMinute);

    if (existing.before(min)) {
        currentHour = minHour;
        currentMinute = minMinute;
        updateTime(currentHour, currentMinute);
    }
}

public void setMax(int hour, int minute) {
    maxHour = hour;
    maxMinute = minute;

    Calendar max = Calendar.getInstance();
    Calendar existing = Calendar.getInstance();

    max.set(Calendar.HOUR_OF_DAY, maxHour);
    max.set(Calendar.MINUTE, maxMinute);

    existing.set(Calendar.HOUR_OF_DAY, currentHour);
    existing.set(Calendar.MINUTE, currentMinute);

    if (existing.after(max)) {
        currentHour = maxHour;
        currentMinute = maxMinute;
        updateTime(currentHour, currentMinute);
    }

}

@Override
public void onTimeChanged(TimePicker view, int hourOfDay, int minute) {

    boolean validTime = true;
    if (hourOfDay < minHour || (hourOfDay == minHour && minute < minMinute)){
        validTime = false;
    }

    if (hourOfDay  > maxHour || (hourOfDay == maxHour && minute > maxMinute)){
        validTime = false;
    }

    if (validTime) {
        currentHour = hourOfDay;
        currentMinute = minute;
    }

    updateTime(currentHour, currentMinute);
    updateDialogTitle(view, currentHour, currentMinute);
}

private void updateDialogTitle(TimePicker timePicker, int hourOfDay, int minute) {
    calendar.set(Calendar.HOUR_OF_DAY, hourOfDay);
    calendar.set(Calendar.MINUTE, minute);
    //String title = dateFormat.format(calendar.getTime());
    //setTitle(title);
}
}