88import android .os .CountDownTimer ;
99import android .os .Parcel ;
1010import android .os .Parcelable ;
11+ import android .support .annotation .DrawableRes ;
12+ import android .support .annotation .IdRes ;
13+ import android .support .annotation .NonNull ;
14+ import android .support .annotation .Nullable ;
1115import android .util .AttributeSet ;
1216import android .util .TypedValue ;
1317import android .view .View ;
2024import java .util .concurrent .TimeUnit ;
2125
2226
27+ /**
28+ * A button that has a countdown timer running over it.
29+ */
2330public class TimerButton extends RelativeLayout implements Animation .AnimationListener , View .OnClickListener {
2431
2532 private static final long INTERVAL = 500L ;
@@ -32,6 +39,7 @@ public class TimerButton extends RelativeLayout implements Animation.AnimationLi
3239 private ScaleAnimation mScaleAnimation ;
3340 private ButtonCountDownTimer mTimer ;
3441 private ColorStateList mTextColor ;
42+ private ButtonAnimationListener mAnimationListener ;
3543
3644 private long mDuration = 10000L ;
3745 private long mDurationLeft ;
@@ -106,9 +114,9 @@ protected void onLayout(boolean changed, int l, int t, int r, int b) {
106114 private void init () {
107115 inflate (getContext (), R .layout .layout_timer_button , this );
108116
109- mBaseButton = ( Button ) findViewById (R .id .timer_base_button );
117+ mBaseButton = findViewById (R .id .timer_base_button );
110118 mOverView = findViewById (R .id .over_view );
111- mTransparentButton = ( Button ) findViewById (R .id .text_button );
119+ mTransparentButton = findViewById (R .id .text_button );
112120
113121 setBeforeAnimationText (mBeforeAnimationText );
114122 setButtonBackground (mButtonBackgroundId );
@@ -153,40 +161,76 @@ private void setupAnimation() {
153161 mScaleAnimation .setAnimationListener (this );
154162 }
155163
164+ /**
165+ * Set the duration for which the animation will run and the button will be disabled
166+ *
167+ * @param duration duration of animation
168+ */
156169 public void setDuration (long duration ) {
157170 mDurationLeft = mDuration = duration ;
158171 }
159172
160- public void setBeforeAnimationText (String beforeAnimationText ) {
161- if (beforeAnimationText != null ) {
162- mBeforeAnimationText = beforeAnimationText ;
163- mBaseButton .setText (mBeforeAnimationText );
164- mTransparentButton .setText (mBeforeAnimationText );
165- }
173+ /**
174+ * Set the text to display before the animations will run
175+ *
176+ * @param beforeAnimationText text to display before animation
177+ */
178+ public void setBeforeAnimationText (@ NonNull String beforeAnimationText ) {
179+ mBeforeAnimationText = beforeAnimationText ;
180+ mBaseButton .setText (mBeforeAnimationText );
181+ mTransparentButton .setText (mBeforeAnimationText );
166182 }
167183
168- public void setOnAnimationCompleteText (String onAnimationCompleteText ) {
184+ /**
185+ * Set the text to display after the animation is finished. Set as null if
186+ * it is supposed to be same as set in {@link #setBeforeAnimationText(String)}
187+ *
188+ * @param onAnimationCompleteText text to display after animation is finished
189+ */
190+ public void setOnAnimationCompleteText (@ Nullable String onAnimationCompleteText ) {
191+ if (mOnAnimationCompleteText == null || mOnAnimationCompleteText .isEmpty ()) {
192+ mOnAnimationCompleteText = mBeforeAnimationText ;
193+ }
169194 mOnAnimationCompleteText = onAnimationCompleteText ;
170195 }
171196
172- public void setDynamicText (int id ) {
197+ /**
198+ * Set the string resource id to be displayed during the animation.
199+ * The string resource should be a formatted string that accepts one integer
200+ *
201+ * @param id string resource id
202+ */
203+ public void setDynamicText (@ IdRes int id ) {
173204 mDynamicStringId = id ;
174205 }
175206
176- public void setButtonBackground (int id ) {
207+ /**
208+ * Set the background of the button
209+ *
210+ * @param id background resource id
211+ */
212+ public void setButtonBackground (@ DrawableRes int id ) {
177213 if (id != 0 ) {
178214 mButtonBackgroundId = id ;
179215 mBaseButton .setBackgroundResource (id );
180216 }
181217 }
182218
183- public void setAnimationBackground (int id ) {
219+ /**
220+ * Set the background for the overlaying animation
221+ *
222+ * @param id animation resource id
223+ */
224+ public void setAnimationBackground (@ DrawableRes int id ) {
184225 if (id != 0 ) {
185226 mAnimationBackgroundId = id ;
186227 mOverView .setBackgroundResource (id );
187228 }
188229 }
189230
231+ /**
232+ * Start the button animation
233+ */
190234 public void startAnimation () {
191235 mIsAnimating = true ;
192236 setupTimer ();
@@ -199,11 +243,18 @@ private void setupTimer() {
199243 mTimer = new ButtonCountDownTimer (mDurationLeft == 0 ? mDuration : mDurationLeft , INTERVAL );
200244 }
201245
246+ /**
247+ * Reset button animation
248+ */
202249 public void reset () {
203- end ();
204250 mIsReset = true ;
251+ end ();
205252 }
206253
254+ /**
255+ * Forcefully end the animation. Note that this is different from
256+ * {@link #reset()} which resets the animation to the start state
257+ */
207258 public void end () {
208259 if (!mScaleAnimation .hasEnded ()) {
209260 mOverView .clearAnimation ();
@@ -213,11 +264,31 @@ public void end() {
213264 mDurationLeft = mDuration ;
214265 }
215266
267+ /**
268+ * Set the {@link ButtonAnimationListener} object to receive callbacks
269+ * @param listener {@link ButtonAnimationListener} object
270+ */
271+ public void setButtonAnimationListener (@ Nullable ButtonAnimationListener listener ) {
272+ mAnimationListener = listener ;
273+ }
274+
216275 @ Override
217276 public void onAnimationStart (Animation animation ) {
218277 mOverView .setVisibility (View .VISIBLE );
219278 mTransparentButton .setVisibility (View .VISIBLE );
220279 mBaseButton .setEnabled (false );
280+ if (mAnimationListener != null ) {
281+ mAnimationListener .onAnimationStart ();
282+ }
283+ }
284+
285+ @ Override
286+ protected void onDetachedFromWindow () {
287+ super .onDetachedFromWindow ();
288+ mAnimationListener = null ;
289+ if (mTimer != null ) {
290+ mTimer .onFinish ();
291+ }
221292 }
222293
223294 @ Override
@@ -268,7 +339,13 @@ public void onTick(long millisUntilFinished) {
268339
269340 @ Override
270341 public void onFinish () {
271-
342+ if (mAnimationListener != null ) {
343+ if (mIsReset ) {
344+ mAnimationListener .onAnimationReset ();
345+ } else {
346+ mAnimationListener .onAnimationEnd ();
347+ }
348+ }
272349 }
273350 }
274351
@@ -306,7 +383,7 @@ protected Parcelable onSaveInstanceState() {
306383 return ss ;
307384 }
308385
309- public class SavedState extends BaseSavedState {
386+ class SavedState extends BaseSavedState {
310387
311388 long timeInFuture ;
312389 int width ;
0 commit comments