CircleTimerView.java revision 113e1daddd8cb0e890084aa4b6ea3194d8ad4826
1package com.android.deskclock; 2 3import android.content.Context; 4import android.content.SharedPreferences; 5import android.content.res.Configuration; 6import android.content.res.Resources; 7import android.graphics.Canvas; 8import android.graphics.Color; 9import android.graphics.Paint; 10import android.graphics.RectF; 11import android.graphics.Typeface; 12import android.os.Parcel; 13import android.os.Parcelable; 14import android.util.AttributeSet; 15import android.view.View; 16 17import com.android.deskclock.stopwatch.Stopwatches; 18 19/** 20 * TODO: Insert description here. (generated by isaackatz) 21 */ 22public class CircleTimerView extends View { 23 24 25 private int mRedColor; 26 private int mWhiteColor; 27 private long mIntervalTime = 0; 28 private long mIntervalStartTime = -1; 29 private long mMarkerTime = -1; 30 private long mCurrentIntervalTime = 0; 31 private long mAccumulatedTime = 0; 32 private boolean mPaused = false; 33 private static float mStrokeSize = 4; 34 private static float mDiamondStrokeSize = 12; 35 private static float mMarkerStrokeSize = 2; 36 private final Paint mPaint = new Paint(); 37 private final RectF mArcRect = new RectF(); 38 private Resources mResources; 39 private float mRadiusOffset; // amount to remove from radius to account for markers on circle 40 41 // Class has 2 modes: 42 // Timer mode - counting down. in this mode the animation is counter-clockwise and stops at 0 43 // Stop watch mode - counting up - in this mode the animation is clockwise and will keep the 44 // animation until stopped. 45 private boolean mTimerMode = false; // default is stop watch view 46 47 Runnable mAnimationThread = new Runnable() { 48 49 @Override 50 public void run() { 51 mCurrentIntervalTime = 52 Utils.getTimeNow() - mIntervalStartTime + mAccumulatedTime; 53 invalidate(); 54 postDelayed(mAnimationThread, 20); 55 } 56 57 }; 58 59 public CircleTimerView(Context context) { 60 this(context, null); 61 } 62 63 public CircleTimerView(Context context, AttributeSet attrs) { 64 super(context, attrs); 65 init(context); 66 } 67 68 public void setIntervalTime(long t) { 69 mIntervalTime = t; 70 postInvalidate(); 71 } 72 73 public void setMarkerTime(long t) { 74 mMarkerTime = t; 75 postInvalidate(); 76 } 77 78 public void reset() { 79 mIntervalStartTime = -1; 80 mMarkerTime = -1; 81 postInvalidate(); 82 } 83 public void startIntervalAnimation() { 84 mIntervalStartTime = Utils.getTimeNow(); 85 this.post(mAnimationThread); 86 mPaused = false; 87 } 88 public void stopIntervalAnimation() { 89 this.removeCallbacks(mAnimationThread); 90 mIntervalStartTime = -1; 91 mAccumulatedTime = 0; 92 } 93 94 public boolean isAnimating() { 95 return (mIntervalStartTime != -1); 96 } 97 98 public void pauseIntervalAnimation() { 99 this.removeCallbacks(mAnimationThread); 100 mAccumulatedTime += Utils.getTimeNow() - mIntervalStartTime; 101 mPaused = true; 102 } 103 104 public void setPassedTime(long time) { 105 mAccumulatedTime = time; 106 postInvalidate(); 107 } 108 109 110 111 private void init(Context c) { 112 113 mResources = c.getResources(); 114 mStrokeSize = mResources.getDimension(R.dimen.circletimer_circle_size); 115 mDiamondStrokeSize = mResources.getDimension(R.dimen.circletimer_diamond_size); 116 mMarkerStrokeSize = 117 mResources.getDimension(R.dimen.circletimer_marker_size) * 2 + mStrokeSize; 118 mPaint.setAntiAlias(true); 119 mPaint.setStyle(Paint.Style.STROKE); 120 mWhiteColor = mResources.getColor(R.color.clock_white); 121 mRedColor = mResources.getColor(R.color.clock_red); 122 123 mRadiusOffset = Math.max(mStrokeSize, Math.max(mDiamondStrokeSize, mMarkerStrokeSize)); 124 } 125 126 public void setTimerMode(boolean mode) { 127 mTimerMode = mode; 128 } 129 130 @Override 131 public void onDraw(Canvas canvas) { 132 int xCenter = getWidth() / 2 + 1; 133 int yCenter = getHeight() / 2; 134 135 mPaint.setStrokeWidth(mStrokeSize); 136 float radius = Math.min(xCenter, yCenter) - mRadiusOffset; 137 138 if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { 139 xCenter = (int) (radius + mRadiusOffset); 140 } 141 142 if (mIntervalStartTime == -1) { 143 // just draw a complete white circle, no red arc needed 144 mPaint.setColor(mWhiteColor); 145 canvas.drawCircle (xCenter, yCenter, radius, mPaint); 146 } else { 147 //draw a combination of red and white arcs to create a circle 148 mArcRect.top = yCenter - radius; 149 mArcRect.bottom = yCenter + radius; 150 mArcRect.left = xCenter - radius; 151 mArcRect.right = xCenter + radius; 152 float redPercent = (float)mCurrentIntervalTime / (float)mIntervalTime; 153 // prevent timer from doing more than one full circle 154 redPercent = (redPercent > 1 && mTimerMode) ? 1 : redPercent; 155 156 float whitePercent = 1 - (redPercent > 1 ? 1 : redPercent); 157 // draw red arc here 158 mPaint.setColor(mRedColor); 159 if (mTimerMode){ 160 canvas.drawArc (mArcRect, 270, - redPercent * 360 , false, mPaint); 161 } else { 162 canvas.drawArc (mArcRect, 270, + redPercent * 360 , false, mPaint); 163 } 164 165 // draw white arc here 166 mPaint.setStrokeWidth(mStrokeSize); 167 mPaint.setColor(mWhiteColor); 168 if (mTimerMode) { 169 canvas.drawArc(mArcRect, 270, + whitePercent * 360, false, mPaint); 170 } else { 171 canvas.drawArc(mArcRect, 270 + (1 - whitePercent) * 360, 172 whitePercent * 360, false, mPaint); 173 } 174 175 // draw red diamond here 176 mPaint.setColor(mRedColor); 177 mPaint.setStrokeWidth(mDiamondStrokeSize); 178 if (mTimerMode){ 179 canvas.drawArc (mArcRect, 265 - redPercent * 360, 10 , false, mPaint); 180 } else { 181 canvas.drawArc (mArcRect, 265 + redPercent * 360, 10 , false, mPaint); 182 } 183 184 185 } 186 if (mMarkerTime != -1) { 187 mPaint.setStrokeWidth(mMarkerStrokeSize); 188 mPaint.setColor(mWhiteColor); 189 float angle = (float)(mMarkerTime % mIntervalTime) / (float)mIntervalTime * 360; 190 canvas.drawArc (mArcRect, 270 + angle, 1 , false, mPaint); 191 } 192 } 193 194 public static final String PREF_CTV_PAUSED = "_ctv_paused"; 195 public static final String PREF_CTV_INTERVAL = "_ctv_interval"; 196 public static final String PREF_CTV_INTERVAL_START = "_ctv_interval_start"; 197 public static final String PREF_CTV_CURRENT_INTERVAL = "_ctv_current_interval"; 198 public static final String PREF_CTV_ACCUM_TIME = "_ctv_accum_time"; 199 public static final String PREF_CTV_TIMER_MODE = "_ctv_timer_mode"; 200 public static final String PREF_CTV_MARKER_TIME = "_ctv_marker_time"; 201 202 // Since this view is used in multiple places, use the key to save different instances 203 public void writeToSharedPref(SharedPreferences prefs, String key) { 204 SharedPreferences.Editor editor = prefs.edit(); 205 editor.putBoolean (key + PREF_CTV_PAUSED, mPaused); 206 editor.putLong (key + PREF_CTV_INTERVAL, mIntervalTime); 207 editor.putLong (key + PREF_CTV_INTERVAL_START, mIntervalStartTime); 208 editor.putLong (key + PREF_CTV_CURRENT_INTERVAL, mCurrentIntervalTime); 209 editor.putLong (key + PREF_CTV_ACCUM_TIME, mAccumulatedTime); 210 editor.putLong (key + PREF_CTV_MARKER_TIME, mMarkerTime); 211 editor.putBoolean (key + PREF_CTV_TIMER_MODE, mTimerMode); 212 editor.apply(); 213 } 214 215 public void readFromSharedPref(SharedPreferences prefs, String key) { 216 mPaused = prefs.getBoolean(key + PREF_CTV_PAUSED, false); 217 mIntervalTime = prefs.getLong(key + PREF_CTV_INTERVAL, 0); 218 mIntervalStartTime = prefs.getLong(key + PREF_CTV_INTERVAL_START, -1); 219 mCurrentIntervalTime = prefs.getLong(key + PREF_CTV_CURRENT_INTERVAL, 0); 220 mAccumulatedTime = prefs.getLong(key + PREF_CTV_ACCUM_TIME, 0); 221 mMarkerTime = prefs.getLong(key + PREF_CTV_MARKER_TIME, -1); 222 mTimerMode = prefs.getBoolean(key + PREF_CTV_TIMER_MODE, false); 223 if (mIntervalStartTime != -1 && !mPaused) { 224 this.post(mAnimationThread); 225 } 226 } 227 228 public void clearSharedPref(SharedPreferences prefs, String key) { 229 SharedPreferences.Editor editor = prefs.edit(); 230 editor.remove (Stopwatches.PREF_START_TIME); 231 editor.remove (Stopwatches.PREF_ACCUM_TIME); 232 editor.remove (Stopwatches.PREF_STATE); 233 editor.remove (key + PREF_CTV_PAUSED); 234 editor.remove (key + PREF_CTV_INTERVAL); 235 editor.remove (key + PREF_CTV_INTERVAL_START); 236 editor.remove (key + PREF_CTV_CURRENT_INTERVAL); 237 editor.remove (key + PREF_CTV_ACCUM_TIME); 238 editor.remove (key + PREF_CTV_MARKER_TIME); 239 editor.remove (key + PREF_CTV_TIMER_MODE); 240 editor.apply(); 241 } 242} 243