Android TimePickerDialog устанавливает максимальное время - программирование
Подтвердить что ты не робот

Android TimePickerDialog устанавливает максимальное время

Я ищу способ установить максимальный и минимальный тайм-аут на Android TimePickerDialog и изменить минутный интервал по умолчанию от 1 мин до 5 мин,

Я думал, что это было легко, но я не могу найти способ!

4b9b3361

Ответ 1

Это расширение для ответов fiddlers. Как-то onTimeChangedListener не установлен TimePickerDialog в некоторых версиях Android:

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

Метод onTimeChanged никогда не называется! Лучшим решением для этой проблемы в настоящее время является возможность кодирования пользовательского 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);
}
 }

Ответ 2

Вы можете использовать это как отправную точку.

Я расширил TimePickerDialog и добавил 2 метода setMin и setMax.

В методе 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

Для lolipop и более высокой версии Android вы можете использовать этот модифицированный класс RangeTimePickerDialog

(Из lolipop Timepicker использует режим часов (дизайн материала) по умолчанию, чтобы старый пользовательский класс не работал. Мы можем изменить режим на spinner для последней версии и повторно использовать класс)

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, int dialogTheme, OnTimeSetListener callBack, int hourOfDay, int minute, boolean is24HourView) {
        super(context, callBack, hourOfDay, minute, is24HourView);
        currentHour = hourOfDay;
        currentMinute = minute;
        dateFormat = DateFormat.getTimeInstance(DateFormat.SHORT);
        fixSpinner(context, hourOfDay, minute, is24HourView);

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


    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 android:timePickerMode
                //two modes are available clock mode and spinner mode ... selecting spinner mode for latest versions
                final int MODE_SPINNER = 2;
                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 = (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 {

                        spinnerDelegateClass = Class.forName("android.widget.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);
                    }
                }
            } 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;
    }
}

Ответ 4

Не существует встроенных методов для установки максимального/минимального времени, но, возможно, он работает, если вы расширяете onTimeChanged или updateTime, вы можете запретить устанавливать время вне значения за пределами ваших границ.

Ответ 5

После рефакторированного кода скрипача:

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

Ответ 6

Надеюсь, это поможет. Я использовал библиотеку времени 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

Надеюсь на эту работу, она отлично работает со мной...

Установите максимальное время для выбора времени.

        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

Вы можете просто использовать пользовательский 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();
    }

}

Итак, вы можете установить, какие значения вы хотите

Ответ 9

В качестве отправной точки я принял решение @Zarooka. Я думаю, что нашел ошибку. Если у вас было начальное время, которое уже было вне диапазона, то вы больше не могли его перемещать, потому что любой "onChanged" отклонялся. Вот почему я расширил setMax и setMin, чтобы перейти в допустимый диапазон при настройке mins/maxs.

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