Android Timepickerdialog is changing hours illogically when I'm scrolling minutes. I have set the minute interval to 30 minutes in my timepickerdialog so the values for minutes are 00 and 30. For example when I set the hours to 00 and change minutes to from 00 to 30 the hours are decreased one hour so the time is now 23:30 and what I'm suppose to have is 00:30. I realized that this doesn't happen on Samsung devices but happens on every other manufacturers devices. Is there any way to disable hours change when scrolling the minutes?
Here is my code
public class CustomTimePickerDialog extends TimePickerDialog {
private int TIME_PICKER_INTERVAL = 30;
private TimePicker mTimePicker;
private final OnTimeSetListener mTimeSetListener;
public int interval1 = 1;
public CustomTimePickerDialog(Context context, OnTimeSetListener listener,
int hourOfDay, int minute, boolean is24HourView, int interval) {
super(context, TimePickerDialog.THEME_HOLO_LIGHT, null, hourOfDay,
minute / interval, is24HourView);
TIME_PICKER_INTERVAL = interval;
mTimeSetListener = listener;
}
#Override
public void updateTime(int hourOfDay, int minuteOfHour) {
mTimePicker.setCurrentHour(hourOfDay);
mTimePicker.setCurrentMinute(minuteOfHour / TIME_PICKER_INTERVAL);
}
#Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case BUTTON_POSITIVE:
if (mTimeSetListener != null) {
mTimeSetListener.onTimeSet(mTimePicker, mTimePicker.getCurrentHour(),
mTimePicker.getCurrentMinute() * TIME_PICKER_INTERVAL);
}
break;
case BUTTON_NEGATIVE:
cancel();
break;
}
}
#Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
try {
Class<?> classForid = Class.forName("com.android.internal.R$id");
Field timePickerField = classForid.getField("timePicker");
mTimePicker = (TimePicker) findViewById(timePickerField.getInt(null));
Field field = classForid.getField("minute");
NumberPicker minuteSpinner = (NumberPicker) mTimePicker
.findViewById(field.getInt(null));
minuteSpinner.setMinValue(0);
minuteSpinner.setMaxValue((60 / TIME_PICKER_INTERVAL) - 1);
List<String> displayedValues = new ArrayList<String>();
for (int i = 0; i < 60; i += TIME_PICKER_INTERVAL) {
displayedValues.add(String.format("%02d", i));
}
minuteSpinner.setDisplayedValues(displayedValues
.toArray(new String[displayedValues.size()]));
} catch (Exception e) {
e.printStackTrace();
}
}
}
I know there is at least one similar question but it doesn't have problem solving answer.
Android time picker auto change hours when minutes get scrolled
EDIT: I also noticed that when I changed the minute interval to 15 it's working great. For example when I'm increasing the minutes from 45 to 00 the hours are increased by one. Same thing backwards when I'm decreasing minutes from 00 to 45 the hours are decreased by one. Same thing when the minute interval is 6. So the problem is only with the 30 minute interval and it is necessary for me to have that 30 minute interval in my software.
I solved it like below. Just call minute changed listener after minuteSpinner.setDisplayedValues()
minuteSpinner.setOnValueChangedListener { picker, oldVal, newVal ->
// Declare this listener to prevent hour change
}
I've been looking for the same problem as you and couldn't find a way. So I tried this and that by myself and found the simplest solution!
Related
I have a TimePicker with an interval of 30 minutes. When I open up a custom dialog with this picker it works well and it shows me 2 choices correctly (0, 30) in the minutes spinner. But, when I confirm and I come back to the activity it shows me a wrong result like: 10:01 instead 10:30. That's the method I use to set the interval
public static void setTimePickerInterval(TimePicker timePicker) {
try {
NumberPicker minutePicker = (NumberPicker) timePicker.findViewById(Resources.getSystem().getIdentifier("minute", "id", "android"));
minutePicker.setMinValue(0);
minutePicker.setMaxValue((60 / TIME_PICKER_INTERVAL) - 1);
List<String> displayedValues = new ArrayList<>();
for (int i = 0; i < 60; i += TIME_PICKER_INTERVAL) {
displayedValues.add(String.format("%02d", i));
}
minutePicker.setDisplayedValues(displayedValues.toArray(new String[0]));
} catch (Exception e) {
Log.e(TAG, "Exception: " + e);
}
}
TIME_PICKER_INTERVAL is set as 30. And that's what i wrote in the activity inside the method that open a custom dialog with the picker
// Get time picker object.
TimePicker timePicker = customView.findViewById(R.id.timePickerExample);
Utils.setTimePickerInterval(timePicker);
timePicker.setIs24HourView(true);
timePicker.setHour(hour);
timePicker.setMinute(minute);
dpStartDate.init(year, month, day, new DatePicker.OnDateChangedListener() {
#Override
public void onDateChanged(DatePicker datePicker, int year, int month, int day) {
MainActivity.this.year = year;
MainActivity.this.month = month;
MainActivity.this.day = day;
}
});
timePicker.setOnTimeChangedListener(new TimePicker.OnTimeChangedListener() {
#Override
public void onTimeChanged(TimePicker timePicker, int hour, int minute) {
Log.i(TAG, "onTimeChanged: " + minute +" "+ hour);
MainActivity.this.hour = hour;
MainActivity.this.minute = minute;
}
});
Log.i(TAG, "onTimeChanged: " + minute +" "+ hour); shows what I'm setting. The hours are corrected, minutes not. It seems that instead shows "0, 30" it shows and select "0, 1". Any idea?
I have a custom timer that I'm keeping synced to the system clock. It's working fine for one minute intervals, but I also need it to sync to 36 second intervals (for updating fields when the user wants times displayed in decimal hours). Inside the Runnable I recalculate the adjustment (accurate enough for my needs) for the next minute, but can't find a way to conveniently deal with the different offsets needed for 36 seconds.
EDIT
private static class DecimalTimer extends TimerClass {
final int[] seconds = new int[101];
private boolean keepRunning = true;
private Runnable mRunnable;
#Override
void kill() {
keepRunning = false;
}
#Override
Runnable getRunnable() {
return mRunnable;
}
DecimalTimer() {
final int[] counter = new int[1];
for (int i = 0, j = 0; i < 3600; i += 36, j++) {
seconds[j] = i;
}
mRunnable = new Runnable() {
#Override
public void run() {
if (!keepRunning)
return;
final Calendar c = Calendar.getInstance();
int hourSeconds = c.get(Calendar.MINUTE) * 60 + c.get(Calendar.SECOND);
for (counter[0] = 0; counter[0] < 100; counter[0]++) {
if (seconds[counter[0]] > hourSeconds) {
c.add(Calendar.SECOND, seconds[counter[0]]);
break;
}
}
long adjustedDelay = (c.getTimeInMillis() - System.currentTimeMillis()) % 36000;
for (IntervalTimer listener : sListeners) {
listener.updateTime();
}
sHandler.postDelayed(this, adjustedDelay);
}
};
}
}
This edit fires every 36 seconds, but I need to get it to sync to 36 seconds on the clock (ie: 12:00:00, then 12:00:36 .. 12:01:12 .. 12:01:48)
Overthinking things as usual, this is what I came up with. It's accurate enough for what I need, but if anyone has an improvement for accuracy (It's a little off when it executes with 900ms or more) it'd be appreciated.
DecimalTimer() {
mRunnable = new Runnable() {
#Override
public void run() {
if (!keepRunning)
return;
final Calendar c = Calendar.getInstance();
c.set(Calendar.MINUTE, 0);
c.set(Calendar.SECOND, 0);
do {
c.add(Calendar.SECOND, 36);
} while (c.getTimeInMillis() < System.currentTimeMillis());
long adjustedDelay = (c.getTimeInMillis() - System.currentTimeMillis()) % 36000;
for (IntervalTimer listener : sListeners) {
listener.updateTime();
}
sHandler.postDelayed(this, adjustedDelay);
}
};
}
Hello i am creating a timer in my app but i stuck in getting seconds left in day end from now (12.00 AM) my timer basically need to show time left for today 11-59 PM. I successfully created a timer function which takes inputs in seconds and then start countdown but i am unable to calculate remaining time of today in seconds
Below is my timer function
time = 30;
// Here i need time left for today end for example current time is 11.55 then remaining time is 5 minutes in seconds (300)
public void startTimer() {
new CountDownTimer(30000, 1000) {
public void onTick(long millisUntilFinished) {
textTimer.setText("0:"+checkDigit(time));
time--;
}
public void onFinish() {
textTimer.setText("try again");
}
}.start();
}
public String checkDigit(int number) {
return number <= 9 ? "0" + number : String.valueOf(number);
}
remaining time of today in seconds:
Calendar tomorrow = Calendar.getInstance();// creating a calendar for tomorrow at 12am
tomorrow.add(Calendar.DAY_OF_YEAR, 1);
tomorrow.set(Calendar.HOUR_OF_DAY, 0);
tomorrow.set(Calendar.MINUTE, 0);
tomorrow.set(Calendar.SECOND, 0);
tomorrow.set(Calendar.MILLISECOND, 0);
remainingSeconds = ( tomorrow.getTimeInMillis() - System.currentTimeMillis() ) / 1000
Sorry for my english. I need to set time between 00:00:00 and 06:00:00, but my code doesn't work. I'm using joda library. My below method doesn't work, i can set time 14:00 or another, not not beetwen 00:00 and 6:00. What i'm doing wrong?
public void setTime(final TextView setText) {
String dateStart = "00:00:00";
String dateStop = "06:00:00";
SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss");
Date d1 = null;
Date d2 = null;
try {
d1 = format.parse(dateStart);
d2 = format.parse(dateStop);
DateTime dt1 = new DateTime(d1);
DateTime dt2 = new DateTime(d2);
int mHour = Hours.hoursBetween(dt1, dt2).getHours() % 24;
int mMinute = Minutes.minutesBetween(dt1, dt2).getMinutes() % 60;
TimePickerDialog tpd = new TimePickerDialog(context,
new TimePickerDialog.OnTimeSetListener() {
#Override
public void onTimeSet(TimePicker view, int hourOfDay,
int minute) {
setText.setText(String.valueOf(hourOfDay) + ":" + String.valueOf(minute));
}
}, mHour, mMinute, true);
tpd.show();
}catch(Exception e) {
Toast.makeText(getApplicationContext(), "Cant open time, sorry", Toast.LENGTH_SHORT).show();
Log.e("Time error", e.toString());
}
}
Have a look here, with mHour and mMinute, you are removing from the DatePicker the hours before 6:00:00; copying from the link here is the problem:
public TimePickerDialog (Context context, int themeResId,
TimePickerDialog.OnTimeSetListener listener, int hourOfDay, int
minute, boolean is24HourView)
Added in API level 1 Creates a new time picker dialog with the
specified theme.
Parameters:
context the parent context
themeResId the resource ID of the theme to apply to this dialog
listener the listener to call when the time is set
hourOfDay the initial hour
minute the initial minute
is24HourView Whether this is a 24 hour view, or AM/PM.
here it is, leave them t 0 and 0 if you want all hours and minutes in your picker
EDIT:
if you want to set time only between 0 and 6, look at this post
In this code a while loop is supposed to check the time, and if the time is equal to 7 PM, then display a message box.
public void actionPerformed(ActionEvent arg0) {
Enable.setEnabled(false);
Date d = new Date();
int hrs = d.getHours();
int mins = d.getMinutes();
while((1 + 1) == 2) {
if(hrs == 19 && mins == 21) {
JOptionPane.showMessageDialog(frame,
"It's 7:21 PM!",
"Alerts",
JOptionPane.WARNING_MESSAGE);
System.exit(0);
break;
}
}
}
Pushing a button will do that code. If you push the button before it is 7 PM, the GUI will freeze (I don't care about that), and when it turns to 7 PM, it won't display the message box. If you click the button when it is 7 PM, then it will display the message box...
Instead of doing while((1 + 1) == 2) to get an infinite loop, you can just do: while(true) or for(;;)
And this question is unanswerable without any further information or code about your hrs and mins variables
You need to update hrs and mins in your loop otherwise the initialization of them, I assume at the time of pushing the button will always hold the time when the button was pushed.
This is why it works when pushed at 7pm but otherwise will not.
So do something like this
while(true) //Equivalent to what you had
{
if(hrs == 19 && mins == 00) {
JOptionPane.showMessageDialog(frame,
"It's 7:00 PM!",
"Time Alert",
JOptionPane.WARNING_MESSAGE);
System.exit(0);
break;
}
//Refresh your hrs and mins here
Calendar calendar = GregorianCalendar.getInstance(); // Probably dont really want to actually get an instance every time
hrs = calendar.get(Calendar.HOUR_OF_DAY);
mins = calendar.get(Calendar.MINUTE);
}
I'm thinking you're using 1+1=2 to have a continuous loop. you could use while(true){...} instead.
Also, the while loop wouldn't be practical for this case. There is an example on this page that does something similar (Alarm Clock): http://www.ibm.com/developerworks/java/library/j-schedule/index.html
this was their example. I updated it to suite your task.
public class AlarmClock {
private final Scheduler scheduler = new Scheduler();
private final SimpleDateFormat dateFormat =
new SimpleDateFormat("dd MMM yyyy HH:mm:ss.SSS");
private final int hourOfDay, minute, second;
public AlarmClock() {
this.hourOfDay = 19;
this.minute = 0;
this.second = 0;
}
public void start() {
scheduler.schedule(new SchedulerTask() {
public void run() {
soundAlarm();
}
private void soundAlarm() {
JOptionPane.showMessageDialog(frame,
"It's 7:00 PM!",
"Time Alert",
JOptionPane.WARNING_MESSAGE);
System.exit(0);
// Start a new thread to sound an alarm...
}
}, new DailyIterator(hourOfDay, minute, second));
}
public static void main(String[] args) {
AlarmClock alarmClock = new AlarmClock();
alarmClock.start();
}
}
Hope it helps.