Animated progress bar
This commit is contained in:
parent
07de78e8e7
commit
74ec0fd883
@ -18,6 +18,16 @@ public abstract class Timer extends ObjectWithId implements Parcelable {
|
|||||||
|
|
||||||
private long endTime;
|
private long endTime;
|
||||||
private long pauseTime;
|
private long pauseTime;
|
||||||
|
private long duration;
|
||||||
|
|
||||||
|
// Using this crashes the app when we create a Timer and start it...
|
||||||
|
// timeRemaining() is returning a negative value... but it doesn't even
|
||||||
|
// consider duration()....?
|
||||||
|
// My guess is the hour, minute, and second getters are returning 0
|
||||||
|
// at this point...?
|
||||||
|
// private final long normalDuration = TimeUnit.HOURS.toMillis(hour())
|
||||||
|
// + TimeUnit.MINUTES.toMillis(minute())
|
||||||
|
// + TimeUnit.SECONDS.toMillis(second());
|
||||||
|
|
||||||
public abstract int hour();
|
public abstract int hour();
|
||||||
public abstract int minute();
|
public abstract int minute();
|
||||||
@ -61,9 +71,12 @@ public abstract class Timer extends ObjectWithId implements Parcelable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public long duration() {
|
public long duration() {
|
||||||
return TimeUnit.HOURS.toMillis(hour())
|
if (duration == 0) {
|
||||||
+ TimeUnit.MINUTES.toMillis(minute())
|
duration = TimeUnit.HOURS.toMillis(hour())
|
||||||
+ TimeUnit.SECONDS.toMillis(second());
|
+ TimeUnit.MINUTES.toMillis(minute())
|
||||||
|
+ TimeUnit.SECONDS.toMillis(second());
|
||||||
|
}
|
||||||
|
return duration;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void start() {
|
public void start() {
|
||||||
@ -89,6 +102,7 @@ public abstract class Timer extends ObjectWithId implements Parcelable {
|
|||||||
public void stop() {
|
public void stop() {
|
||||||
endTime = 0;
|
endTime = 0;
|
||||||
pauseTime = 0;
|
pauseTime = 0;
|
||||||
|
duration = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addOneMinute() {
|
public void addOneMinute() {
|
||||||
@ -97,8 +111,17 @@ public abstract class Timer extends ObjectWithId implements Parcelable {
|
|||||||
// throw new IllegalStateException("Cannot extend a timer that is not running");
|
// throw new IllegalStateException("Cannot extend a timer that is not running");
|
||||||
if (expired()) {
|
if (expired()) {
|
||||||
endTime = SystemClock.elapsedRealtime() + MINUTE;
|
endTime = SystemClock.elapsedRealtime() + MINUTE;
|
||||||
|
// If the timer's normal duration is >= MINUTE, then an extra run time of one minute
|
||||||
|
// will still be within the normal duration. Thus, the progress calculation does not
|
||||||
|
// need to change. For example, if the timer's normal duration is 2 minutes, an extra
|
||||||
|
// 1 minute run time is fully encapsulated within the 2 minute upper bound.
|
||||||
|
if (duration < MINUTE) {
|
||||||
|
// This scales the progress bar to a full minute.
|
||||||
|
duration = MINUTE;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
endTime += MINUTE;
|
endTime += MINUTE;
|
||||||
|
duration += MINUTE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,6 +154,13 @@ public abstract class Timer extends ObjectWithId implements Parcelable {
|
|||||||
return pauseTime;
|
return pauseTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TO ONLY BE CALLED BY TIMERDATABASEHELPER.
|
||||||
|
*/
|
||||||
|
public void setDuration(long duration) {
|
||||||
|
this.duration = duration;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int describeContents() {
|
public int describeContents() {
|
||||||
return 0;
|
return 0;
|
||||||
@ -146,6 +176,7 @@ public abstract class Timer extends ObjectWithId implements Parcelable {
|
|||||||
dest.writeLong(getId());
|
dest.writeLong(getId());
|
||||||
dest.writeLong(endTime);
|
dest.writeLong(endTime);
|
||||||
dest.writeLong(pauseTime);
|
dest.writeLong(pauseTime);
|
||||||
|
dest.writeLong(duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final Creator<Timer> CREATOR = new Creator<Timer>() {
|
public static final Creator<Timer> CREATOR = new Creator<Timer>() {
|
||||||
@ -166,6 +197,7 @@ public abstract class Timer extends ObjectWithId implements Parcelable {
|
|||||||
t.setId(source.readLong());
|
t.setId(source.readLong());
|
||||||
t.endTime = source.readLong();
|
t.endTime = source.readLong();
|
||||||
t.pauseTime = source.readLong();
|
t.pauseTime = source.readLong();
|
||||||
|
t.duration = source.readLong();
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,6 +26,7 @@ public class TimerCursor extends BaseItemCursor<Timer> {
|
|||||||
t.setId(getLong(getColumnIndexOrThrow(TimersTable.COLUMN_ID)));
|
t.setId(getLong(getColumnIndexOrThrow(TimersTable.COLUMN_ID)));
|
||||||
t.setEndTime(getLong(getColumnIndexOrThrow(TimersTable.COLUMN_END_TIME)));
|
t.setEndTime(getLong(getColumnIndexOrThrow(TimersTable.COLUMN_END_TIME)));
|
||||||
t.setPauseTime(getLong(getColumnIndexOrThrow(TimersTable.COLUMN_PAUSE_TIME)));
|
t.setPauseTime(getLong(getColumnIndexOrThrow(TimersTable.COLUMN_PAUSE_TIME)));
|
||||||
|
t.setDuration(getLong(getColumnIndexOrThrow(TimersTable.COLUMN_DURATION)));
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -27,9 +27,9 @@ public final class TimersTable {
|
|||||||
|
|
||||||
public static final String COLUMN_END_TIME = "end_time";
|
public static final String COLUMN_END_TIME = "end_time";
|
||||||
public static final String COLUMN_PAUSE_TIME = "pause_time";
|
public static final String COLUMN_PAUSE_TIME = "pause_time";
|
||||||
|
public static final String COLUMN_DURATION = "duration";
|
||||||
|
|
||||||
public static final String SORT_ORDER =
|
public static final String SORT_ORDER = COLUMN_HOUR + " ASC, "
|
||||||
COLUMN_HOUR + " ASC, "
|
|
||||||
+ COLUMN_MINUTE + " ASC, "
|
+ COLUMN_MINUTE + " ASC, "
|
||||||
+ COLUMN_SECOND + " ASC, "
|
+ COLUMN_SECOND + " ASC, "
|
||||||
// All else equal, newer timers first
|
// All else equal, newer timers first
|
||||||
@ -44,7 +44,8 @@ public final class TimersTable {
|
|||||||
+ COLUMN_LABEL + " TEXT NOT NULL, "
|
+ COLUMN_LABEL + " TEXT NOT NULL, "
|
||||||
// + COLUMN_GROUP + " TEXT NOT NULL, "
|
// + COLUMN_GROUP + " TEXT NOT NULL, "
|
||||||
+ COLUMN_END_TIME + " INTEGER NOT NULL, "
|
+ COLUMN_END_TIME + " INTEGER NOT NULL, "
|
||||||
+ COLUMN_PAUSE_TIME + " INTEGER NOT NULL);");
|
+ COLUMN_PAUSE_TIME + " INTEGER NOT NULL, "
|
||||||
|
+ COLUMN_DURATION + " INTEGER NOT NULL);");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
public static void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||||
|
|||||||
@ -53,6 +53,7 @@ public class TimersTableManager extends DatabaseTableManager<Timer> {
|
|||||||
Log.d(TAG, "endTime = " + timer.endTime() + ", pauseTime = " + timer.pauseTime());
|
Log.d(TAG, "endTime = " + timer.endTime() + ", pauseTime = " + timer.pauseTime());
|
||||||
cv.put(TimersTable.COLUMN_END_TIME, timer.endTime());
|
cv.put(TimersTable.COLUMN_END_TIME, timer.endTime());
|
||||||
cv.put(TimersTable.COLUMN_PAUSE_TIME, timer.pauseTime());
|
cv.put(TimersTable.COLUMN_PAUSE_TIME, timer.pauseTime());
|
||||||
|
cv.put(TimersTable.COLUMN_DURATION, timer.duration());
|
||||||
return cv;
|
return cv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
package com.philliphsu.clock2.timers;
|
package com.philliphsu.clock2.timers;
|
||||||
|
|
||||||
|
import android.animation.ObjectAnimator;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.ImageButton;
|
import android.widget.ImageButton;
|
||||||
@ -20,9 +22,11 @@ import butterknife.OnClick;
|
|||||||
*/
|
*/
|
||||||
public class TimerViewHolder extends BaseViewHolder<Timer> {
|
public class TimerViewHolder extends BaseViewHolder<Timer> {
|
||||||
private static final String TAG = "TimerViewHolder";
|
private static final String TAG = "TimerViewHolder";
|
||||||
|
private static final int MAX_PROGRESS = 10000;
|
||||||
|
|
||||||
private final AsyncTimersTableUpdateHandler mAsyncTimersTableUpdateHandler;
|
private final AsyncTimersTableUpdateHandler mAsyncTimersTableUpdateHandler;
|
||||||
private TimerController mController;
|
private TimerController mController;
|
||||||
|
private ObjectAnimator mProgressAnimator;
|
||||||
|
|
||||||
@Bind(R.id.label) TextView mLabel;
|
@Bind(R.id.label) TextView mLabel;
|
||||||
@Bind(R.id.duration) CountdownChronometer mChronometer;
|
@Bind(R.id.duration) CountdownChronometer mChronometer;
|
||||||
@ -34,17 +38,20 @@ public class TimerViewHolder extends BaseViewHolder<Timer> {
|
|||||||
public TimerViewHolder(ViewGroup parent, OnListItemInteractionListener<Timer> listener,
|
public TimerViewHolder(ViewGroup parent, OnListItemInteractionListener<Timer> listener,
|
||||||
AsyncTimersTableUpdateHandler asyncTimersTableUpdateHandler) {
|
AsyncTimersTableUpdateHandler asyncTimersTableUpdateHandler) {
|
||||||
super(parent, R.layout.item_timer, listener);
|
super(parent, R.layout.item_timer, listener);
|
||||||
|
Log.d(TAG, "New TimerViewHolder");
|
||||||
mAsyncTimersTableUpdateHandler = asyncTimersTableUpdateHandler;
|
mAsyncTimersTableUpdateHandler = asyncTimersTableUpdateHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBind(Timer timer) {
|
public void onBind(final Timer timer) {
|
||||||
super.onBind(timer);
|
super.onBind(timer);
|
||||||
|
Log.d(TAG, "Binding TimerViewHolder");
|
||||||
// TOneverDO: create before super
|
// TOneverDO: create before super
|
||||||
mController = new TimerController(timer, mAsyncTimersTableUpdateHandler);
|
mController = new TimerController(timer, mAsyncTimersTableUpdateHandler);
|
||||||
bindLabel(timer.label());
|
bindLabel(timer.label());
|
||||||
bindChronometer(timer);
|
bindChronometer(timer);
|
||||||
bindButtonControls(timer);
|
bindButtonControls(timer);
|
||||||
|
bindProgressBar(timer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnClick(R.id.start_pause)
|
@OnClick(R.id.start_pause)
|
||||||
@ -106,4 +113,42 @@ public class TimerViewHolder extends BaseViewHolder<Timer> {
|
|||||||
mAddOneMinute.setVisibility(visibility);
|
mAddOneMinute.setVisibility(visibility);
|
||||||
mStop.setVisibility(visibility);
|
mStop.setVisibility(visibility);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void bindProgressBar(Timer timer) {
|
||||||
|
mProgressBar.setMax(MAX_PROGRESS);
|
||||||
|
final long timeRemaining = timer.timeRemaining();
|
||||||
|
final int progress = (int) (MAX_PROGRESS * (double) timeRemaining / timer.duration());
|
||||||
|
|
||||||
|
// In case we're reusing an animator instance that could be running
|
||||||
|
if (mProgressAnimator != null && mProgressAnimator.isRunning()) {
|
||||||
|
mProgressAnimator.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!timer.isRunning()) {
|
||||||
|
mProgressBar.setProgress(progress);
|
||||||
|
} else {
|
||||||
|
mProgressAnimator = ObjectAnimator.ofInt(
|
||||||
|
// The object that has the property we wish to animate
|
||||||
|
mProgressBar,
|
||||||
|
// The name of the property of the object that identifies which setter method
|
||||||
|
// the animation will call to update its values. Here, a property name of
|
||||||
|
// "progress" will result in a call to the function setProgress() in ProgressBar.
|
||||||
|
// The docs for ObjectAnimator#setPropertyName() says that for best performance,
|
||||||
|
// the setter method should take a float or int parameter, and its return type
|
||||||
|
// should be void (both of which setProgress() satisfies).
|
||||||
|
"progress",
|
||||||
|
// The set of values to animate between. A single value implies that that value
|
||||||
|
// is the one being animated to. Two values imply starting and ending values.
|
||||||
|
// More than two values imply a starting value, values to animate through along
|
||||||
|
// the way, and an ending value (these values will be distributed evenly across
|
||||||
|
// the duration of the animation).
|
||||||
|
progress, 0);
|
||||||
|
mProgressAnimator.setDuration(timeRemaining);
|
||||||
|
// The algorithm that calculates intermediate values between keyframes. We use linear
|
||||||
|
// interpolation so that the animation runs at constant speed.
|
||||||
|
mProgressAnimator.setInterpolator(null/*results in linear interpolation*/);
|
||||||
|
// This MUST be run on the UI thread.
|
||||||
|
mProgressAnimator.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -34,7 +34,6 @@
|
|||||||
android:id="@+id/progress_bar"
|
android:id="@+id/progress_bar"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:progress="90"
|
|
||||||
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
|
style="@style/Widget.AppCompat.ProgressBar.Horizontal"
|
||||||
android:layout_below="@id/duration"/>
|
android:layout_below="@id/duration"/>
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user