自定義view實現時鐘

這裏時間是根據本地時間來的,如果需要精確,可以與百度時間對比,獲取偏移量並計算

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();
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章