這裏時間是根據本地時間來的,如果需要精確,可以與百度時間對比,獲取偏移量並計算
package com.packg.demo;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PointF;
import android.graphics.RectF;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.View;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import io.reactivex.Observable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
import io.reactivex.schedulers.Schedulers;
/**
* created by wy on 2020-03-26
* description : 自定義時鐘view
*/
public class LockView extends View {
public LockView(Context context) {
this(context, null);
}
public LockView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public LockView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
private int radius = 0;//半徑
private Paint mPaint = null;
private Paint StokPaint = null;
private int width, height;
private int padding;
private PointF center = new PointF();
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
mPaint = new Paint();
mPaint.setAntiAlias(true);
StokPaint = new Paint();
StokPaint.setAntiAlias(true);
width = right - left;
height = bottom - top;
padding = Math.min(width, height) / 20;
radius = Math.min(width, height) / 2 - padding;
center.x = (left + right) / 2;
center.y = (bottom - top) / 2;
//rx
Disposable subscribe = Observable.intervalRange(0, Integer.MAX_VALUE, 0, 20, TimeUnit.MILLISECONDS)
.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<Long>() {
@Override
public void accept(final Long aLong) throws Exception {
LockView.this.invalidate();
}
});
}
private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mPaint.setColor(0xff303F9F);
canvas.drawCircle(center.x, center.y, radius, mPaint);//背景
Matrix matrix = new Matrix();
mPaint.setColor(Color.LTGRAY);
mPaint.setStrokeWidth(3);
for (int i = 0; i < 60; i++) {
matrix.setRotate(i * 6, center.x, center.y);//以繪製區域中心爲遠點旋轉,並將旋轉角度遞增,達到轉圈的效果
canvas.setMatrix(matrix);
if (i % 15 == 0) {
//最大的刻度,3 6 9 12
canvas.drawRect(center.x - 2, padding, center.x + 2, padding + 40, mPaint);
} else if (i % 5 == 0) {
//小一點的刻度 對應1、2、4、5...
canvas.drawRect(center.x - 1.8f, padding, center.x + 1.8f, padding + 24, mPaint);
} else {
//分針對應的刻度
canvas.drawRect(center.x - 1f, padding, center.x + 1f, padding + 12, mPaint);
}
}
matrix.setRotate(0, center.x, center.y);//以繪製區域中心爲遠點旋轉,並將旋轉角度遞增,達到轉圈的效果
canvas.setMatrix(matrix);
mPaint.setTextAlign(Paint.Align.CENTER);
for (int i = 0; i < 4; i++) {//畫4個數字 3 6 9 12
//此處注意drawtex的y座標,對應的是descent,不是top,也不是bottom
String txt = String.valueOf(i == 0 ? 12 : i * 3);
mPaint.setTextSize(40);
float w = mPaint.measureText(txt);
Paint.FontMetrics fm = mPaint.getFontMetrics();
float des = fm.descent - fm.top;
float x = 0;
float y = 0;
switch (i) {
case 0:
x = center.x;
y = padding + 45 + des;
break;
case 1:
x = center.x + radius - 45 - w;
y = center.y + (fm.bottom - fm.top) / 4;
break;
case 2:
x = center.x;
y = center.y + radius - 45 - (fm.bottom - fm.top) / 2;
break;
default:
x = center.x - radius + 45 + w;
y = center.y + (fm.bottom - fm.top) / 4;
break;
}
canvas.drawText(txt, x, y, mPaint);//畫時刻數字
}
Path path = new Path();
path.addArc(new RectF(center.x - 200, padding + 150, center.x + 200, center.y - 150),
180, 180);//設置扇形區域邊框,以及旋轉的角度
Paint citePaint = new Paint(mPaint);
citePaint.setTextSize(40);
citePaint.setStrokeWidth(3);
// canvas.drawPath(path, citePaint);可放開查看扇形區域
canvas.drawTextOnPath("lock view from canvas", path, 0, 0, citePaint);//畫頂部扇形區域外邊框文字
canvas.drawText(dateFormat.format(new Date()), center.x, center.y + radius - 150, mPaint);//當前時間 也可以加上星期
mPaint.setColor(Color.BLACK);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(3);
canvas.drawCircle(center.x, center.y, radius, mPaint); //畫最外層圓圈,可以優化
mPaint.setStyle(Paint.Style.FILL);
//此處計算每根針的角度,-90是因爲0度對應的是3點,減90恰好對應12點
long mTime = 60 * 1000;//一分鐘的時間
long hTime = mTime * 60;//一小時的時間
long halfDay = 12 * hTime;//12小時的時間
long time = getNowTime() % halfDay;//因爲手錶是12小時制,需要餘掉
float hRotate = time * 360.0f / halfDay - 90;//時針的角度
float mRotate = (time % hTime) * 360.0f / hTime - 90;//分針的角度
float sRotate = (time % mTime) * 360.0f / mTime - 90;//秒針的角度
mPaint.setColor(0xffFF4081);
matrix.setRotate(hRotate, center.x, center.y);//以繪製區域中心爲遠點旋轉,並將旋轉角度遞增,達到轉圈的效果
canvas.setMatrix(matrix);
mPaint.setStrokeWidth(12);
canvas.drawLine(center.x - 30, center.y, center.x + radius / 2, center.y, mPaint);//時針
mPaint.setColor(0xff3F51B5);
matrix.setRotate(mRotate, center.x, center.y);//以繪製區域中心爲遠點旋轉,並將旋轉角度遞增,達到轉圈的效果
canvas.setMatrix(matrix);
mPaint.setStrokeWidth(10);
canvas.drawLine(center.x - 30, center.y, center.x + radius * 2 / 3, center.y, mPaint);//分針
mPaint.setColor(0xFFFFBB33);
matrix.setRotate(sRotate, center.x, center.y);//以繪製區域中心爲遠點旋轉,並將旋轉角度遞增,達到轉圈的效果
canvas.setMatrix(matrix);
mPaint.setStrokeWidth(7);
canvas.drawLine(center.x - 30, center.y, center.x + radius * 3 / 4, center.y, mPaint);//秒針
mPaint.setColor(Color.WHITE);
canvas.drawCircle(center.x, center.y, 15, mPaint);//這個圓是爲了美觀
}
/**
* 獲取今天的開始時間
*
* @return 時間戳long
*/
public static long getNowTime() {
Calendar c = Calendar.getInstance();
c.set(Calendar.HOUR_OF_DAY, 0);
c.set(Calendar.MINUTE, 0);
c.set(Calendar.SECOND, 0);
c.set(Calendar.MILLISECOND, 0);
return System.currentTimeMillis() - c.getTimeInMillis();
}
}