Android - TimePicker минут до 15 - PullRequest
       2

Android - TimePicker минут до 15

38 голосов
/ 05 апреля 2010

Можно ли управлять представлением Android TimePicker, чтобы отображать интервал от минут до 15 минут?

То есть, если сейчас 12:28, покажите 12:30, и нажатие кнопок + и - увеличит и уменьшит на 15?

Спасибо,

Ти

Ответы [ 9 ]

19 голосов
/ 20 февраля 2012

Вот моя версия, где вы можете установить интервал:

private static final int TIME_PICKER_INTERVAL=15;
private boolean mIgnoreEvent=false;

private TimePicker.OnTimeChangedListener mTimePickerListener=new TimePicker.OnTimeChangedListener(){
    public void onTimeChanged(TimePicker timePicker, int hourOfDay, int minute){
        if (mIgnoreEvent)
            return;
        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;
            mIgnoreEvent=true;
            timePicker.setCurrentMinute(minute);
            mIgnoreEvent=false;
        }

    }
};
19 голосов
/ 09 апреля 2014

Создайте XML-файл и назовите его activity_time_picker.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

 <TimePicker
        android:id="@+id/timePicker1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/layoutHourMinute"
        android:layout_centerInParent="true"

        />

</RelativeLayout>

теперь создайте класс активности, подобный этому

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

import android.annotation.SuppressLint;

import android.content.pm.ActivityInfo;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.widget.NumberPicker;
import android.widget.TimePicker;

public class TimePickerActivity extends Activity {


    TimePicker timePicker;
    private int TIME_PICKER_INTERVAL = 15;
     NumberPicker minutePicker;
     List<String> displayedValues;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
                 super.onCreate(savedInstanceState);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
        setContentView(R.layout.activity_time_picker);
        super.onCreate(savedInstanceState);
        timePicker = (TimePicker)findViewById(R.id.timePicker1);

        timePicker.setIs24HourView(true);
        timePicker.setCurrentHour(0);
        timePicker.setCurrentMinute(0);

        setTimePickerInterval(timePicker);
    }
@SuppressLint("NewApi")
    private void setTimePickerInterval(TimePicker timePicker) {
         try {
                Class<?> classForid = Class.forName("com.android.internal.R$id");
               // Field timePickerField = classForid.getField("timePicker");  

                Field field = classForid.getField("minute");
                minutePicker = (NumberPicker) timePicker
                        .findViewById(field.getInt(null));

                minutePicker.setMinValue(0);
                minutePicker.setMaxValue(3);
                displayedValues = new ArrayList<String>();
                for (int i = 0; i < 60; i += TIME_PICKER_INTERVAL) {
                    displayedValues.add(String.format("%02d", i));
                }
              //  for (int i = 0; i < 60; i += TIME_PICKER_INTERVAL) {
              //      displayedValues.add(String.format("%02d", i));
              //  }
                minutePicker.setDisplayedValues(displayedValues
                        .toArray(new String[0]));
               minutePicker.setWrapSelectorWheel(true);
            } catch (Exception e) {
                e.printStackTrace();
            }
    }
}
8 голосов
/ 24 июня 2010

У меня сработало следующее.

Сначала в onCreate:

pickStartTime = (TimePicker)findViewById(R.id.StartTime);
pickStartTime.setOnTimeChangedListener(mStartTimeChangedListener);

Установите OnTimeChangedListener:

private TimePicker.OnTimeChangedListener mStartTimeChangedListener =
    new TimePicker.OnTimeChangedListener() {

    public void onTimeChanged(TimePicker view, int hourOfDay, int minute) {
        updateDisplay(view, startDate, hourOfDay, minute);          
    }
};

Null OnTimeChangedListener (объясняется в комментариях в updateDisplayниже):

private TimePicker.OnTimeChangedListener mNullTimeChangedListener =
    new TimePicker.OnTimeChangedListener() {

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

    }
};

private void updateDisplay(TimePicker timePicker, Date date, int hourOfDay, int minute) { 

    // do calculation of next time 
    int nextMinute = 0;     
    if (minute >= 45 && minute <= 59)
        nextMinute = 45;
    else if(minute >= 30)
        nextMinute = 30;
    else if(minute >= 15)
        nextMinute = 15;
    else if(minute > 0)
        nextMinute = 0;
    else {          
        nextMinute = 45;
    }

    // remove ontimechangedlistener to prevent stackoverflow/infinite loop
    timePicker.setOnTimeChangedListener(mNullTimeChangedListener);

    // set minute
    timePicker.setCurrentMinute(nextMinute);

    // hook up ontimechangedlistener again
    timePicker.setOnTimeChangedListener(mStartTimeChangedListener);

    // update the date variable for use elsewhere in code
    date.setMinutes(nextMinute);  
}
3 голосов
/ 16 апреля 2011
private void updateDisplay(TimePicker timePicker, int hourOfDay, int minute) {
    int nextMinute = 0;

    timePicker.setOnTimeChangedListener(mNullTimeChangedListener);

    if (minute >= 45 && minute <= 59) 
        nextMinute = 45;  
    else if (minute  >= 30) 
        nextMinute = 30;
    else if (minute >= 15) 
        nextMinute = 15;
    else if (minute > 0) 
        nextMinute = 0; 
    else { 
        nextMinute = 45; 
    }

    if (minute - nextMinute == 1) {
        if (minute >= 45 && minute <= 59) 
            nextMinute = 00; 
        else if(minute  >= 30) 
            nextMinute = 45;
        else if(minute >= 15) 
            nextMinute = 30;
        else if(minute > 0) 
            nextMinute = 15; 
        else { 
            nextMinute = 15; 
        }
    }

    timePicker.setCurrentMinute(nextMinute);

    timePicker.setOnTimeChangedListener(timePickerChangedListener);

}

Обновлен метод отображения, измененный для кнопок + и -. Остальной код такой же, как и у Эндрю Дайера.

3 голосов
/ 05 апреля 2010

Думаю, я понял это. Может быть, гетто, но ...

Вот что я сделал.

start_time.setOnTimeChangedListener(new TimePicker.OnTimeChangedListener() {

            public void onTimeChanged(TimePicker view, int hourOfDay, int minute) {
                updateDisplay(hourOfDay, minute);
            }
        });

private void updateDisplay(int hourOfDay, int minute) {
                // do calculation of next time
                // nextTime = calculation of next time;

                // the processed boolean is to prevent infinite loop
        if (!processed) {
            start_time.setCurrentMinute(nextTime);  
                        processed = true;
        } else {
                        processed = false;
                }
    }
3 голосов
/ 05 апреля 2010

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

2 голосов
/ 05 мая 2015

Я нашел решение, основанное на некоторых предыдущих ответах на этот вопрос и некоторых моих собственных дополнениях. Это решение, в частности, переопределяет getCurrentMinute и setCurrentMinute, которые по умолчанию возвращают вам минутный индекс, а не минутное значение (т. Е. Если ваш минутный интервал равен 15, а в сборщике отображается минута 30, он вернет 2 без этого кода). 1001 *

Это решение также будет переносить минуты, превышающие максимальное значение интервала (опять же, если ваш интервал равен 15, любые минуты> 45 установят значение минуты в 0 и увеличат значение часа).

ПРИМЕЧАНИЕ: это проверено и работает на Android 4.4 и 5.0.

public class CustomIntervalTimePicker extends TimePicker {

    private static final int TIME_PICKER_MINUTE_INTERVAL = 15;
    private OnTimeChangedListener timeChangedListener;

    public CustomIntervalTimePicker(Context context, AttributeSet attrs) {
        super(context, attrs);

        try {
            Class<?> classForId = Class.forName("com.android.internal.R$id");
            Field field = classForId.getField("minute");

            NumberPicker minuteSpinner = (NumberPicker) this.findViewById(field.getInt(null));
            minuteSpinner.setMaxValue((60 / TIME_PICKER_MINUTE_INTERVAL) - 1);
            List<String> displayedValues = new ArrayList<>();
            for (int i = 0; i < 60; i += TIME_PICKER_MINUTE_INTERVAL)
                displayedValues.add(String.format("%02d", i));
            minuteSpinner.setDisplayedValues(displayedValues.toArray(new String[displayedValues.size()]));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private int maxMinuteIndex() {
        return (60 / TIME_PICKER_MINUTE_INTERVAL) - 1;
    }

    @Override
    public void setOnTimeChangedListener(OnTimeChangedListener onTimeChangedListener) {
        super.setOnTimeChangedListener(internalTimeChangedListener);
        this.timeChangedListener = onTimeChangedListener;
    }

    @Override
    public Integer getCurrentMinute() {
        return super.getCurrentMinute() * TIME_PICKER_MINUTE_INTERVAL;
    }

    @Override
    public void setCurrentMinute(Integer currentMinute) {
        int cleanMinute = currentMinute / TIME_PICKER_MINUTE_INTERVAL;
        if(currentMinute % TIME_PICKER_MINUTE_INTERVAL > 0) {
            if(cleanMinute == maxMinuteIndex()) {
                cleanMinute = 0;
                setCurrentHour(getCurrentHour()+1);
            } else {
                cleanMinute++;
            }
        }
        super.setCurrentMinute(cleanMinute);
    }

    // We want to proxy all the calls to our member variable OnTimeChangedListener with our own
    // internal listener in order to make sure our overridden getCurrentMinute is called. Without
    // this some versions of android return the underlying minute index.
    private OnTimeChangedListener internalTimeChangedListener = new OnTimeChangedListener() {
        @Override
        public void onTimeChanged(TimePicker view, int hourOfDay, int minute) {
            timeChangedListener.onTimeChanged(view, getCurrentHour(), getCurrentMinute());
        }
    };
}
1 голос
/ 19 марта 2011

Прежде всего, я хотел бы поблагодарить Эндрю за преодоление ошибки переполнения стека (бесконечный цикл). Моя логика для увеличения времени на 15 минут выглядит примерно так. 1001 *

// remove ontimechangedlistener to prevent stackoverflow/infinite loop timePicker.setOnTimeChangedListener(mNullTimeChangedListener);</p> <pre><code> if((minute - previousMinuteSet == 1) || (minute - previousMinuteSet == 15) || (minute - previousMinuteSet == -45)) { // set hour timePicker.setCurrentHour((hourOfDay + minute / 45) % 12); // set minute timePicker.setCurrentMinute((minute + 14) % 60); } else { // set hour timePicker.setCurrentHour(hourOfDay); // set minute timePicker.setCurrentMinute(minute); } previousMinuteSet = minute; // hook up ontimechangedlistener again timePicker.setOnTimeChangedListener(timePickerChangedListener);

Надеюсь, это могло бы быть полезным для других. Код, который я заменил в методе updateDisplay Эндрю, кроме того, что все было одинаково.

0 голосов
/ 17 февраля 2016

Вот версия, которую я написал. Это код на C #, потому что я использую Xamarin, но я надеюсь, что никому не будет сложнее перевести его на Java, чем мне, а выполнять перевод наоборот, когда мне нужно скопировать кусок кода Java.

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

Я мог бы лучше справиться с задачей упростить настройку пользовательского интервала минут и не сделать жестким кодирование значений интервалов в реализации, но я считаю, что вы можете отшлифовать это решение, если хотите очень быстро!

HourPickerMapper.cs

public class HourPickerMapper
{
    public HourPickerMapper() { }

    public int MapValue(int hour)
    {
        return hour;
    }

    public int MapNumber(int number)
    {
        return number;
    }

    public void InitNumberPicker(NumberPicker numberPicker)
    {
        int[] numbers = new int[24];
        for (var i = 0; i < numbers.Length; i++)
        {
            numbers[i] = i;
        }
        var displayed = numbers.Select(_ => $"{_:00}").ToArray();

        numberPicker.SetDisplayedValues(displayed);
        numberPicker.MinValue = 0;
        numberPicker.MaxValue = displayed.Length - 1;
    }
}

MinutePickerMapper.cs

public class MinutePickerMapper
{
    public MinutePickerMapper() { }

    public int MapValue(int value)
    {
        return (int)Math.Floor(value / 10.0);
    }

    public int MapNumber(int number)
    {
        return number * 10;
    }

    public void InitNumberPicker(NumberPicker numberPicker)
    {
        int[] numbers = new int[6];
        for (var i = 0; i < numbers.Length; i++)
        {
            numbers[i] = i * 10;
        }
        var displayed = numbers.Select(_ => _.ToString()).ToArray();

        numberPicker.SetDisplayedValues(displayed);
        numberPicker.MinValue = 0;
        numberPicker.MaxValue = displayed.Length - 1;
    }
}

А вот пример использования: DialogFragment

public class CustomDateTimePickerDialogFragment : Android.Support.V4.App.DialogFragment
{
    private DateTime _dt;
    private NumberPicker _datePicker, _hourPicker, _minutePicker;
    private DatePickerMapper _datePickerMapper;
    private HourPickerMapper _hourPickerMapper;
    private MinutePickerMapper _minutePickerMapper;

    public event EventHandler<DateTimeSetEventArgs> DateTimeSetEvent;
    public CustomDateTimePickerDialogFragment()
    {
        _dt = DateTime.Now + new TimeSpan(24, 0, 0); // now + 1 day
    }

    public CustomDateTimePickerDialogFragment(DateTime dt)
    {
        _dt = dt;
        if (dt == null)
        {
            _dt = DateTime.Now + new TimeSpan(24, 0, 0); // now + 1 day
        }
    }

    public override Dialog OnCreateDialog(Bundle savedInstanceState)
    {
        AlertDialog.Builder builder = new AlertDialog.Builder(Context);
        builder.SetNeutralButton(Resource.String.dialog_datetime_now, (sender, e) => 
        {
            var eventArgs = new DateTimeSetEventArgs();
            DateTimeSetEvent.Invoke(this, eventArgs);
        });
        builder.SetPositiveButton(Resource.String.dialog_ok, (sender, e) =>
        {
            var hour = _hourPickerMapper.MapNumber(_hourPicker.Value);
            var minute = _minutePickerMapper.MapNumber(_minutePicker.Value);
            var date = _datePickerMapper.MapNumber(_datePicker.Value);
            var eventArgs = new DateTimeSetEventArgs(new DateTime(date.Year, date.Month, date.Day, hour, minute, 0));
            DateTimeSetEvent.Invoke(this, eventArgs);
            Dismiss();
        });
        var dialog = builder.Create();
        dialog.SetView(createDateTimeView(dialog.LayoutInflater));

        _datePicker.Value = _datePickerMapper.MapValue(_dt);
        _hourPicker.Value = _hourPickerMapper.MapValue(_dt.Hour);
        _minutePicker.Value = _minutePickerMapper.MapValue(_dt.Minute);

        return dialog;
    }

    private View createDateTimeView(LayoutInflater inflater)
    {
        View view = inflater.Inflate(Resource.Layout.dialog_custom_datetime_picker, null);

        _datePicker = view.FindViewById<NumberPicker>(Resource.Id.datePicker);
        _datePickerMapper = new DatePickerMapper(DateTime.Now, 10);
        _datePickerMapper.InitNumberPicker(_datePicker);

        var now = DateTime.Now;
        _datePicker.Value = _datePickerMapper.MapValue(now);

        _minutePicker = view.FindViewById<NumberPicker>(Resource.Id.minutePicker);
        _minutePickerMapper = new MinutePickerMapper();
        _minutePickerMapper.InitNumberPicker(_minutePicker);
        _minutePicker.Value = _minutePickerMapper.MapValue(now.Minute);

        _hourPicker = view.FindViewById<NumberPicker>(Resource.Id.hourPicker);
        _hourPickerMapper = new HourPickerMapper();
        _hourPickerMapper.InitNumberPicker(_hourPicker);
        _hourPicker.Value = _hourPickerMapper.MapValue(now.Hour);

        return view;
    }

    public class DateTimeSetEventArgs : EventArgs
    {
        public DateTimeSetEventArgs(DateTime dt)
        {
            IsNow = false;
            DT = dt;
        }

        public DateTimeSetEventArgs()
        {
            IsNow = true;
        }

        public DateTime DT { get; }
        public bool IsNow { get; }
    }
}

dialog_custom_datetime_picker.xml

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:padding="@dimen/dialog_padding"
    >
  <!-- Layout for the DatePicker -->
  <LinearLayout
    android:orientation="vertical"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center_horizontal"
  >
     <LinearLayout
      android:orientation="horizontal"
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:gravity="center_vertical"
      >
      <NumberPicker
        android:id="@+id/datePicker"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:descendantFocusability="blocksDescendants"
        />
      <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text=" "
        />
      <NumberPicker
        android:id="@+id/hourPicker"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:descendantFocusability="blocksDescendants"
        />
         <TextView
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:text=":"
          />
      <NumberPicker
        android:id="@+id/minutePicker"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:descendantFocusability="blocksDescendants"
        />       
    </LinearLayout>  
  </LinearLayout>
</LinearLayout>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...