Android – TimePicker分钟到15
我可以控制Android TimePicker视图只显示15分钟的时间间隔?
意思是如果现在是12点28分,表演12点30分,点击+和 – button会递增和递减15?
谢谢,
T恤
这里是我可以设置时间间隔的版本:
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; } } };
创build一个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>
现在就像这样创build活动课
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(); } } }
以下为我工作。
首先在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); } };
无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); }
你必须编写你自己的TimePicker。 不确定是否可以扩展现有的TimePicker并自行处理button事件。
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); }
更新修改为+和 – button的显示方法。 其余的代码和Andrew Dyer的代码一样。
我想我明白了。 可能是贫民窟的方式,但…
这是我做的。
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; } }
我已经提出了一个解决scheme,基于一些以前对这个问题的答案,以及我自己的一些补充。 这个解决scheme明显地覆盖了getCurrentMinute和setCurrentMinute,默认情况下,它会返回分钟索引,而不是分钟值(例如,如果您的分钟间隔为15,并且select器显示的分钟数为30,则不使用此代码返回2)。
此解决scheme也会翻转大于最大间隔值的分钟数(如果间隔为15,则任何分钟> 45将把分钟值设置为0并递增小时值)。
注意:这是testing和工作在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()); } }; }
首先,我要感谢安德鲁克服stackoverflow错误(无限循环)。我的逻辑增加时间15分钟是这样的.Declare int previousMinuteSet = 0作为成员variables在给定的类。
// remove ontimechangedlistener to prevent stackoverflow/infinite loop timePicker.setOnTimeChangedListener(mNullTimeChangedListener);
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方法,除了一切都是一样的。
这是我写的版本。 这是C#代码,因为我使用的是Xamarin,但是我希望任何人都可以把它翻译成Java而不是更难,当我需要复制一段Java代码的时候,执行vica的翻译。
它与标准的TimePicker有一点不同,它的顶部和底部的边界不是连续的,但它是一些人会觉得微不足道的缺陷。
我可以做更好的工作,使自定义分钟间隔设置更容易,而不是让你在实现中硬编码间隔值,但我相信你可以抛光这个解决scheme,如果你想非常快!
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
的用法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>