Как реализовать средство выбора минут и секунд Android?

Мне нужно реализовать диалог, в котором пользователь может ввести время в минутах и ​​секундах. Например: 6 минут 30 секунд. Там мне также нужен верхний предел количества минут (т. Е. Минуты будут варьироваться от 0 до 10, секунды от 0 до 60).

Но, как уже говорилось здесь, Android TimePicker представляет только часы и минуты. Я видел несколько сообщений о добавлении к нему секунд, но ничего об удалении часов и добавлении секунд. Вероятно, также нет возможности наложить ограничение на минуты.

Я видел несколько сообщений, в которых рекомендовалось создать собственное средство выбора времени с помощью NumberPicker, но я также видел предупреждения о том, что NumberPicker предназначен для внутренних целей и не должен использоваться. Похоже, это Уловка-22.

Я мог бы попытаться изменить исходный код для TimePicker или NumberPicker, но я не в восторге от того, сколько времени потребуется, чтобы понять, как они работают, и поддерживать собственную версию в будущем.

Я предполагаю, что это оставляет меня с реализацией пользовательского средства выбора минут-секунд. Использование кнопок вверх-вниз для перемещения числа не выглядит слишком сложным, но я не знаю, как разрешить пользователю прокручивать числа в каждом «колесе».

Какие-либо предложения?


person user2704782    schedule 22.10.2013    source источник


Ответы (2)


После использования этого ответа SO, чтобы добавить минутный интервал в TimePickerDialog, я создал аналогичный подкласс, который расширяет диапазон часов spinner на 0-60 и обрабатывает счетчики часов:минуты как минуты:секунды:

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

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

public class DurationPicker extends TimePickerDialog {

    private TimePicker timePicker;
    private final OnTimeSetListener callback;

    private int initialMinutes;

    public DurationPicker(Context context, OnTimeSetListener callBack, int minutes, int seconds) {
        super(context, callBack, minutes, seconds, true); // the last argument removes the am/pm spinner
        this.callback = callBack;
        this.initialMinutes = minutes; // we'll have to set this again after modifying the "hours" spinner
        this.setTitle("Set duration");
    }

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

    @Override
    public void onAttachedToWindow() {
        super.onAttachedToWindow();
        try {
            Class<?> classForid = Class.forName("com.android.internal.R$id");
            Field timePickerField = classForid.getField("timePicker");
            this.timePicker = (TimePicker) findViewById(timePickerField.getInt(null));
            Field field = classForid.getField("hour");

            // modify the hours spinner to cover the maximum number of minutes we want to support
            int maxMinutes = 60;
            NumberPicker mHourSpinner = (NumberPicker)timePicker.findViewById(field.getInt(null));
            mHourSpinner.setMinValue(0);
            mHourSpinner.setMaxValue(maxMinutes);
            List<String> displayedValues = new ArrayList<String>();
            for (int i = 0; i <= maxMinutes; i++) {
                displayedValues.add(String.format("%d", i));
            }
            mHourSpinner.setDisplayedValues(displayedValues.toArray(new String[0]));
            mHourSpinner.setValue(initialMinutes); // we can set this again now that we've modified the hours spinner
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

}

В обратном вызове просто обработайте значение второго аргумента как минуты, а значение третьего аргумента — как секунды.

Вполне возможно, что будущая версия Android может возвращать неверные результаты, когда счетчик «минут» установлен на число выше 24, но я прочитал текущий код TimePicker и не увидел никаких проблем с этим. Кроме того, можно было бы изменить или заменить счетчик am/pm счетчиком секунд, и тогда средство выбора могло бы поддерживать часы:минуты:секунды, а также минуты:секунды.

person arlomedia    schedule 27.07.2014
comment
Средство выбора времени в диалоговом окне отображается как часы, а не как счетчик... как можно изменить режим? - person Yonatan Nir; 02.03.2017
comment
@YonatanNir см. этот ответ stackoverflow.com/a/48163947/6019601 - person Zezi Reeds; 10.02.2021

К сожалению, код от @arlomedia у меня не сработал, так как не нашел поле hour. Я изменил класс с помощью этого ответа (версия Kotlin):


import android.app.TimePickerDialog
import android.content.Context
import android.content.DialogInterface
import android.content.res.Resources
import android.view.View
import android.widget.NumberPicker
import android.widget.TimePicker
import java.util.*


class DurationPickerDialog(context: Context?, private val callback: OnTimeSetListener?, private val initialMinutes: Int, seconds: Int) :
    TimePickerDialog(context, callback, initialMinutes, seconds, true) {

    init {
        this.setTitle("Set duration")
    }

    private var timePicker: TimePicker? = null

    override fun onClick(dialog: DialogInterface, which: Int) {
        if (callback != null && timePicker != null) {
            timePicker!!.clearFocus()
            callback.onTimeSet(timePicker, timePicker!!.currentHour, timePicker!!.currentMinute)
        }
    }

    override fun onAttachedToWindow() {
        super.onAttachedToWindow()
        try {

          
            timePicker = findViewById<View>(
                Resources.getSystem().getIdentifier("timePicker", "id", "android")
            ) as TimePicker


            val hoursPicker = timePicker!!.findViewById(
                Resources.getSystem().getIdentifier("hour", "id", "android")
            ) as NumberPicker

            // Modify the hours spinner to cover the maximum number of minutes we want to support

            val maxMinutes = 60
            hoursPicker.minValue = 0
            hoursPicker.maxValue = maxMinutes

            val displayedValues: MutableList<String> = ArrayList()

            for (i in 0..maxMinutes) displayedValues.add(String.format("%d", i))

            hoursPicker.displayedValues = displayedValues.toTypedArray()
            hoursPicker.value = initialMinutes

        } catch (e: Exception) {
            e.printStackTrace()
        }
    }
}
person Zezi Reeds    schedule 10.02.2021