可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I am writing an application where the user needs to specify a given point in time, but i can't seem to figure out how to set the minute values that the user can choose from, to only use increments of 5 instead of increments of 1.
Simply put, when the user scrolls through the available amounts, he/she must only see 0,5,10,15 etc.
Thank you in advance.
回答1:
To ensure you're compatible with API 21+, make sure your TimePicker has the following attribute:
android:timePickerMode="spinner"
Then here's how you can set an interval programmatically. This method falls back on the standard TimePicker if the minute field cannot be found:
private static final int INTERVAL = 5;
private static final DecimalFormat FORMATTER = new DecimalFormat("00");
private TimePicker picker; // set in onCreate
private NumberPicker minutePicker;
public void setMinutePicker() {
int numValues = 60 / INTERVAL;
String[] displayedValues = new String[numValues];
for (int i = 0; i < numValues; i++) {
displayedValues[i] = FORMATTER.format(i * INTERVAL);
}
View minute = picker.findViewById(Resources.getSystem().getIdentifier("minute", "id", "android"));
if ((minute != null) && (minute instanceof NumberPicker)) {
minutePicker = (NumberPicker) minute;
minutePicker.setMinValue(0);
minutePicker.setMaxValue(numValues - 1);
minutePicker.setDisplayedValues(displayedValues);
}
}
public int getMinute() {
if (minutePicker != null) {
return (minutePicker.getValue() * INTERVAL);
} else {
return picker.getCurrentMinute();
}
}
回答2:
all relative answer need you to set an OnTimeChangedListener.
My resolution is that you extends android TimePicker,and modify the constructor of it:
// minute
mMinuteSpinner = (NumberPicker) findViewById(R.id.minute);
mMinuteSpinner.setMinValue(0);
mMinuteSpinner.setMaxValue(3);
mMinuteSpinner.setDisplayedValues(new String[]{"0", "15", "30", "45"});
mMinuteSpinner.setOnLongPressUpdateInterval(100);
mMinuteSpinner.setFormatter(NumberPicker.getTwoDigitFormatter());
so you can have the interval you want.
回答3:
Thanks @Quadddd, this is the code in Kotlin
private val INTERVAL = 5
private val FORMATTER = DecimalFormat("00")
private var picker: TimePicker? = null // set in onCreate
private var minutePicker: NumberPicker? = null
fun setMinutePicker() {
val numValues = 60 / INTERVAL
val displayedValues = arrayOfNulls<String>(numValues)
for (i in 0 until numValues) {
displayedValues[i] = FORMATTER.format(i * INTERVAL)
}
val minute = picker?.findViewById<NumberPicker>(Resources.getSystem().getIdentifier("minute", "id", "android"))
if (minute != null) {
minutePicker = minute
minutePicker!!.minValue = 0
minutePicker!!.maxValue = numValues - 1
minutePicker!!.displayedValues = displayedValues
}
}
fun getMinute(): Int {
return if (minutePicker != null) {
minutePicker!!.getValue() * INTERVAL
} else {
picker!!.currentMinute
}
}
回答4:
After searching the net, I didn't find the simplest solution.
So I decided to share:
You can use reflections!
The following code use intervals of 10 minutes, but you can choose the minutes you want to use in the DISPLAYED_MINS array.
private final static String[] DISPLAYED_MINS = { "0", "10", "20", "30", "40", "50" };
private NumberPicker getMinuteSpinner(TimePicker t)
{
try
{
Field f = t.getClass().getDeclaredField("mMinuteSpinner"); // NoSuchFieldException
f.setAccessible(true);
return (NumberPicker) f.get(t); // IllegalAccessException
}
catch (Exception e)
{
Log.e("timepicker","field name has been changed, check grepcode");
return null;
}
}
when you create your timepicker:
final TimePicker dpStartDate = (TimePicker) view.findViewById(R.id.dpStartDate);
NumberPicker startMinSpiner = getMinuteSpinner(dpStartDate);
if (null != startMinSpiner)
{
startMinSpiner.setMinValue(0);
startMinSpiner.setMaxValue(DISPLAYED_MINS.length - 1);
startMinSpiner.setDisplayedValues(DISPLAYED_MINS);
}
Just don't forget that getCurrentMinute() return the selected minute in the DISPLAY_MINS array.
in order to get the minute:
int theTime = 0;
for (String number: DISPLAYED_MINS) {
int theNumber = Integer.parseInt(number);
if (theNumber % 5 != 0) {
theNumber = ((int)(theNumber / 5)) * 5;
}
if (theNumber == dpStartDate.getCurrentMinute()) {
theTime = theNumber;
break;
}
}
回答5:
You can do this programmatically.
pickStartTime = (TimePicker)findViewById(R.id.StartTime);
pickStartTime.setOnTimeChangedListener(mStartTimeChangedListener);
int nextMinute = 0;
Next, Set the OnTimeChangedListener
as shown below
private TimePicker.OnTimeChangedListener mStartTimeChangedListener =
new TimePicker.OnTimeChangedListener() {
public void onTimeChanged(TimePicker view, int hourOfDay, int minute) {
updateDisplay(view, startDate, hourOfDay, minute);
}
};
private TimePicker.OnTimeChangedListener mNullTimeChangedListener =
new TimePicker.OnTimeChangedListener() {
public void onTimeChanged(TimePicker view, int hourOfDay, int minute) {}
};
And,
private void updateDisplay(TimePicker timePicker, Date date, int hourOfDay, int minute)
{
nextMinute = nextMinute+5;
// remove ontimechangedlistener to prevent stackoverflow/infinite loop
timePicker.setOnTimeChangedListener(mNullTimeChangedListener);
// set minute
timePicker.setCurrentMinute(nextMinute);
// look up ontimechangedlistener again
timePicker.setOnTimeChangedListener(mStartTimeChangedListener);
// update the date variable for use elsewhere in code
date.setMinutes(nextMinute);
}