先上图:
控件非常简单,主要是为了练习自定义控件,巧用 canvas.rotate等方法能大大简化自定义控件中一些复杂计算。上代码
public class ClockView extends View {
private int widthAndHeight;//控件的宽高
private int radius;//半径
private Point center;//圆心
private Paint mPaint;
private Paint mTextPaint;
private double minsRadian;//分钟弧度
private double hoursRadian;//小时弧度
public ClockView(Context context) {
super(context);
init();
}
public ClockView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public ClockView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(Color.BLACK);
mPaint.setStrokeWidth(3);
mTextPaint = new Paint();
mTextPaint.setAntiAlias(true);
mTextPaint.setStyle(Paint.Style.FILL);
mTextPaint.setColor(Color.BLACK);
mTextPaint.setTextSize(50);
mTextPaint.setTextAlign(Paint.Align.CENTER);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heughtSize = MeasureSpec.getSize(heightMeasureSpec);
//保证是个正方形
widthAndHeight = Math.min(widthSize, heughtSize);
radius = widthAndHeight / 2 - 5;
center = new Point(widthAndHeight/2,widthAndHeight/2);
setMeasuredDimension(widthAndHeight, widthAndHeight);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//1.画外圆
canvas.drawCircle(widthAndHeight / 2, widthAndHeight / 2, radius, mPaint);
//2.画刻度
int lineLength;
for (int i = 0; i < 60; i++) {
if (i % 5 == 0) {
lineLength = 40;
mPaint.setStrokeWidth(3);
String hour = String.valueOf(i / 5);
if (i == 0)
hour = "12";
canvas.drawText(hour, widthAndHeight / 2, 100, mTextPaint);
} else {
lineLength = 25;
mPaint.setStrokeWidth(2);
}
canvas.drawLine(widthAndHeight / 2, 5, widthAndHeight / 2, 5 + lineLength, mPaint);
canvas.rotate(6, widthAndHeight / 2, widthAndHeight / 2);
}
//3.画时分针
mPaint.setStrokeWidth(4);
//圆心
canvas.drawRect(widthAndHeight / 2 - 5, widthAndHeight / 2 - 5, widthAndHeight / 2 + 5, widthAndHeight / 2 + 5, mPaint);
Point stopPoint = pointInCircle(center, radius-150, minsRadian);
canvas.drawLine(center.x, center.y, stopPoint.x, stopPoint.y, mPaint);//分钟线
Point stopPoint2 = pointInCircle(center, radius-200, hoursRadian);
mPaint.setStrokeWidth(8);
canvas.drawLine(center.x, center.y, stopPoint2.x, stopPoint2.y, mPaint);//分钟线
}
/**
* 计算对应弧度圆上某个点的位置
* @param mCenter 园心
* @param mRadius 半径
* @param mRadian 旋转的弧度
* @return 对应的圆上的点
*/
private Point pointInCircle(Point mCenter,int mRadius,double mRadian){
Point point = new Point();
if (mRadian<Math.PI/2){
point.x = (int)(mCenter.x + Math.sin(mRadian)*mRadius);
point.y = (int)(mCenter.y - Math.cos(mRadian)*mRadius);
}else if(mRadian<Math.PI){
point.x = (int)(mCenter.x + Math.sin(Math.PI - mRadian)*mRadius);
point.y = (int)(mCenter.y + Math.cos(Math.PI - mRadian)*mRadius);
}else if (mRadian < Math.PI *3 /2){
point.x = (int)(mCenter.x - Math.sin(mRadian - Math.PI)*mRadius);
point.y = (int)(mCenter.y + Math.cos(mRadian - Math.PI)*mRadius);
}else if (mRadian < Math.PI *2){
point.x = (int)(mCenter.x - Math.sin(Math.PI*2 - mRadian)*mRadius);
point.y = (int)(mCenter.y - Math.cos(Math.PI*2 - mRadian)*mRadius);
}
return point;
}
public void setTime(Date date){
hoursRadian = date.getHours()%12*2*Math.PI/12;
minsRadian = date.getMinutes()*2*Math.PI/60;
postInvalidate();
}