Last active
February 12, 2016 09:16
-
-
Save vadymhimself/e52071bec889128bc989 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.clockwidget; | |
import android.content.Context; | |
import android.graphics.Canvas; | |
import android.graphics.Color; | |
import android.graphics.Paint; | |
import android.util.AttributeSet; | |
import android.view.View; | |
import java.util.Calendar; | |
/** | |
* Simple animated clock widget. Uses system time | |
* | |
* Created by bolein on 12.02.2016. | |
*/ | |
public class ClockView extends View { | |
private static final String TAG = ClockView.class.getSimpleName(); | |
private static final long REDRAW_RATE = 20; // 20ms | |
private static final int BACKGROUND_COLOR = 0xFF098852; | |
private Paint mBackgroundPaint; | |
private Paint mHandPaint; | |
public ClockView(Context context) { | |
super(context); | |
init(context, null); | |
} | |
public ClockView(Context context, AttributeSet attrs) { | |
super(context, attrs); | |
init(context, attrs); | |
} | |
private void init(Context context, AttributeSet attrs) { | |
mBackgroundPaint = new Paint(); | |
mBackgroundPaint.setColor(BACKGROUND_COLOR); | |
mBackgroundPaint.setAntiAlias(true); | |
mHandPaint = new Paint(); | |
mHandPaint.setColor(Color.WHITE); | |
mHandPaint.setAntiAlias(true); | |
} | |
@Override | |
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { | |
// always keep square size 1:1 | |
int width = MeasureSpec.getSize(widthMeasureSpec); | |
int height = MeasureSpec.getSize(heightMeasureSpec); | |
int measuredSize = Math.min(width, height); | |
setMeasuredDimension(measuredSize, measuredSize); | |
} | |
/** | |
* Runnable instantiated only once | |
*/ | |
private Runnable invalidator = new Runnable() { | |
@Override | |
public void run() { | |
invalidate(); | |
} | |
}; | |
@Override | |
protected void onDraw(Canvas canvas) { | |
drawBackground(canvas); | |
drawHourHand(canvas); | |
drawMinuteHand(canvas); | |
drawSecondHand(canvas); | |
drawNail(canvas); | |
// redraw itself in REDRAW_RATE millis | |
postDelayed(invalidator, REDRAW_RATE); | |
} | |
private void drawBackground(Canvas canvas) { | |
float bgrCircleRadius = getHeight() / 2f; | |
canvas.drawCircle(bgrCircleRadius, bgrCircleRadius, bgrCircleRadius, mBackgroundPaint); | |
} | |
private void drawHourHand(Canvas canvas) { | |
float viewRadius = getWidth() / 2f; | |
float handRadius = getWidth() * 0.2f; | |
float thickness = getWidth() * 0.01f; // 1% of view's width | |
mHandPaint.setStrokeWidth(thickness); | |
// coordinates of hand's end | |
double angle = getHoursAngle(); | |
float x = getStopX(viewRadius, handRadius, angle); | |
float y = getStopY(viewRadius, handRadius, angle); | |
canvas.drawLine(viewRadius, viewRadius, x, y, mHandPaint); | |
} | |
private void drawMinuteHand(Canvas canvas) { | |
float viewRadius = getWidth() / 2f; | |
float handRadius = getWidth() * 0.3f; | |
float thickness = getWidth() * 0.01f; // 1% of view's width | |
mHandPaint.setStrokeWidth(thickness); | |
// coordinates of hand's end | |
double angle = getMinutesAngle(); | |
float x = getStopX(viewRadius, handRadius, angle); | |
float y = getStopY(viewRadius, handRadius, angle); | |
canvas.drawLine(viewRadius, viewRadius, x, y, mHandPaint); | |
} | |
private void drawSecondHand(Canvas canvas) { | |
float viewRadius = getWidth() / 2f; | |
float handRadius = getWidth() * 0.4f; | |
float thickness = getWidth() * 0.005f; // 0.5% of view's width | |
mHandPaint.setStrokeWidth(thickness); | |
// coordinates of hand's end | |
double angle = getSecondsAngle(); | |
float x = getStopX(viewRadius, handRadius, angle); | |
float y = getStopY(viewRadius, handRadius, angle); | |
canvas.drawLine(viewRadius, viewRadius, x, y, mHandPaint); | |
} | |
/** | |
* Evaluates hand's end X coordinate based on the given angle. | |
* x = R + r * sin(a); | |
*/ | |
private float getStopX(float viewRadius, float handRadius, double angle) { | |
return (float) (viewRadius + handRadius * Math.sin(angle)); | |
} | |
/** | |
* Evaluates hand's end Y coordinate based on the given angle | |
* y = R - r * cos(a); | |
*/ | |
private float getStopY(float viewRadius, float handRadius, double angle) { | |
return (float) (viewRadius - handRadius * Math.cos(angle)); | |
} | |
private void drawNail(Canvas canvas) { | |
float viewRadius = getHeight() / 2f; | |
float nailRadius = getHeight() * 0.02f; | |
canvas.drawCircle(viewRadius, viewRadius, nailRadius, mHandPaint); | |
} | |
/** | |
* Gets angle of hour hand(minute-accurate) | |
* @return angle in radians | |
*/ | |
private double getHoursAngle() { | |
Calendar c = Calendar.getInstance(); | |
int hours = c.get(Calendar.HOUR); | |
int minutes = c.get(Calendar.MINUTE); | |
int minutesFromStart = hours * 60 | |
+ minutes; | |
return (2 * Math.PI * minutesFromStart) / 720; // divided by number of minutes in 12 hours; | |
} | |
/** | |
* Gets angle of minute hand (second-accurate) | |
* @return angle in radians | |
*/ | |
private double getMinutesAngle() { | |
Calendar c = Calendar.getInstance(); | |
int secondsFromStart = c.get(Calendar.MINUTE) * 60 | |
+ c.get(Calendar.SECOND); | |
return (2 * Math.PI * secondsFromStart) / 3600; // divided by number of seconds in 1 hour | |
} | |
/** | |
* Gets angle of second hand (millisecond-accurate) | |
* @return angle in radians | |
*/ | |
private double getSecondsAngle() { | |
Calendar c = Calendar.getInstance(); | |
int millisFromStart = c.get(Calendar.SECOND) * 1000 + c.get(Calendar.MILLISECOND); | |
return (2 * Math.PI * millisFromStart) / 60000; // divided by number of milliseconds in 1 minute | |
} | |
} |
Author
vadymhimself
commented
Feb 11, 2016
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment