The timer always starts from the top, and I want it to start from some initialized position with some part already drawn. I took reference from this tutorial.
This is my MainActivity:
public class MainActivity extends AppCompatActivity {
private static final int TIMER_LENGTH1= 3600*24;
private static final int TIMER_LENGTH2= 3600;
private static final int TIMER_LENGTH3= 60;
private static int i=0;
private TextView tvDay, tvHour, tvMinute, tvSecond, tvEvent;
private LinearLayout linearLayout1, linearLayout2;
private Handler handler;
private Runnable runnable;
private TimerView mTimerView1,mTimerView2,mTimerView3;
private static long h=0,m=0,s=0,d=0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity);
initUI();
countDownStart();
mTimerView1 = (TimerView) findViewById(R.id.timer2);
mTimerView2 = (TimerView) findViewById(R.id.timer3);
mTimerView3 = (TimerView) findViewById(R.id.timer4);
}
@SuppressLint("SimpleDateFormat")
private void initUI() {
//linearLayout1 = (LinearLayout) findViewById(R.id.ll1);
linearLayout2 = (LinearLayout) findViewById(R.id.ll2);
tvDay = (TextView) findViewById(R.id.txtTimerDay);
tvHour = (TextView) findViewById(R.id.txtTimerHour);
tvMinute = (TextView) findViewById(R.id.txtTimerMinute);
tvSecond = (TextView) findViewById(R.id.txtTimerSecond);
//tvEvent = (TextView) findViewById(R.id.tvevent);
}
// //////////////COUNT DOWN START/////////////////////////
public void countDownStart() {
handler = new Handler();
runnable = new Runnable() {
@Override
public void run() {
handler.postDelayed(this, 1000);
try {
SimpleDateFormat dateFormat = new SimpleDateFormat(
"yyyy-MM-dd");
// Here Set your Event Date
Date eventDate = dateFormat.parse("2016-12-29");
Date currentDate = new Date();
if (!currentDate.after(eventDate)) {
long diff = eventDate.getTime()
- currentDate.getTime();
long days = diff / (24 * 60 * 60 * 1000);
diff -= days * (24 * 60 * 60 * 1000);
long hours = diff / (60 * 60 * 1000);
diff -= hours * (60 * 60 * 1000);
long minutes = diff / (60 * 1000);
diff -= minutes * (60 * 1000);
long seconds = diff / 1000;
if(i==0)
{
mTimerView1.start(TIMER_LENGTH1);
mTimerView2.start(TIMER_LENGTH2);
mTimerView3.start(TIMER_LENGTH3);
i++;
d=days;
h=hours;
m=minutes;
s=seconds;
}
if(minutes!=m)
{
mTimerView3.start(TIMER_LENGTH3);
m=minutes;
}
if(hours!=h)
{
mTimerView2.start(TIMER_LENGTH2);
h=hours;
}
if(days!=d)
{
mTimerView1.start(TIMER_LENGTH1);
d=days;
}
tvDay.setText("" + String.format("%02d", days));
tvHour.setText("" + String.format("%02d", hours));
tvMinute.setText("" + String.format("%02d", minutes));
tvSecond.setText("" + String.format("%02d", seconds));
} else {
//linearLayout1.setVisibility(View.VISIBLE);
linearLayout2.setVisibility(View.GONE);
tvEvent.setText("CULFEST IS ON");
handler.removeCallbacks(runnable);
// handler.removeMessages(0);
}
} catch (Exception e) {
e.printStackTrace();
}
}
};
handler.postDelayed(runnable, 0);
}
@Override
protected void onPause() {
mTimerView1.stop();
mTimerView2.stop();
mTimerView3.stop();
super.onPause();
}
}
This is my TimerView:
public class TimerView extends View {
private static final int ARC_START_ANGLE = 270; // 12 o'clock
private static final float THICKNESS_SCALE = 0.03f;
private Bitmap mBitmap;
private Canvas mCanvas;
private RectF mCircleOuterBounds;
private RectF mCircleInnerBounds;
private Paint mCirclePaint;
private Paint mEraserPaint;
private float mCircleSweepAngle;
private ValueAnimator mTimerAnimator;
public TimerView(Context context) {
this(context, null);
}
public TimerView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public TimerView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
int circleColor = Color.RED;
if (attrs != null) {
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.TimerView);
if (ta != null) {
circleColor = ta.getColor(R.styleable.TimerView_circleColor, circleColor);
ta.recycle();
}
}
mCirclePaint = new Paint();
mCirclePaint.setAntiAlias(true);
mCirclePaint.setColor(circleColor);
mEraserPaint = new Paint();
mEraserPaint.setAntiAlias(true);
mEraserPaint.setColor(Color.TRANSPARENT);
mEraserPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
}
@SuppressWarnings("SuspiciousNameCombination")
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, widthMeasureSpec); // Trick to make the view square
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
if (w != oldw || h != oldh) {
mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mBitmap.eraseColor(Color.TRANSPARENT);
mCanvas = new Canvas(mBitmap);
}
super.onSizeChanged(w, h, oldw, oldh);
updateBounds();
}
@Override
protected void onDraw(Canvas canvas) {
mCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
if (mCircleSweepAngle > 0f) {
mCanvas.drawArc(mCircleOuterBounds, ARC_START_ANGLE, mCircleSweepAngle, true, mCirclePaint);
mCanvas.drawOval(mCircleInnerBounds, mEraserPaint);
}
canvas.drawBitmap(mBitmap, 0, 0, null);
}
public void start(int secs) {
stop();
mTimerAnimator = ValueAnimator.ofFloat(0f, 1f);
mTimerAnimator.setDuration(TimeUnit.SECONDS.toMillis(secs));
mTimerAnimator.setInterpolator(new LinearInterpolator());
mTimerAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
drawProgress((float) animation.getAnimatedValue());
}
});
mTimerAnimator.start();
}
public void stop() {
if (mTimerAnimator != null && mTimerAnimator.isRunning()) {
mTimerAnimator.cancel();
mTimerAnimator = null;
drawProgress(0f);
}
}
private void drawProgress(float progress) {
mCircleSweepAngle = 360 * progress;
invalidate();
}
private void updateBounds() {
final float thickness = getWidth() * THICKNESS_SCALE;
mCircleOuterBounds = new RectF(0, 0, getWidth(), getHeight());
mCircleInnerBounds = new RectF(
mCircleOuterBounds.left + thickness,
mCircleOuterBounds.top + thickness,
mCircleOuterBounds.right - thickness,
mCircleOuterBounds.bottom - thickness);
invalidate();
}
}
The Timer looks like this:
Please help.
From glancing over the source code, it looks as though you should be able to set an initial start value in the following way:
1) Create an instance variable to store the initial value with a setter:
//Value between 0f and 360f
private float mStartValue = 0f;
//...
public void setStartValue(float startValueInDegrees) {
mStartValue = startValueInDegrees;
}
2) Update the drawProgress()
method to account for this new start value:
private void drawProgress(float progress) {
mCircleSweepAngle = ((360 - mStartValue) * progress) + mStartValue;
invalidate();
}