今天我们来一起学习一下怎么通过自定义view画一个时钟出来。

自定义view是一个比较有意思,同时难度也是很高的工作。现在市面上有很多动画效果很棒的页面,无非都是一步一步从最基础的学起的,正所谓万丈高楼平地起。所以,这篇文章很适合新手入门练习哦。

首先先贴上最终的效果图吧,这样到时看代码不会特别抽象。

android自定义View尺子 android 自定义view绘制_自定义view

下面我说一下,实现的步骤是什么吧。

  1. 画一个外圆(确定圆心位置,然后给一个半径)
  2. 画刻度(将圆等分成12部分,先画处0点的位置,最后通过画布的旋转,旋转的角度的360/12,画刻度直线)
  3. 画时针和分针(把手机的坐标原点移动到圆的中心点,再画2条直线,一个时针和分针)

下面贴上代码:

 

package com.example.myapplication.view;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;

public class CustomClockView extends View {

    private Paint circlePaint, keduPaint, hourPaint, minuterPaint;

    public CustomClockView(Context context) {
        this(context, null);
    }

    public CustomClockView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CustomClockView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        //圆
        circlePaint = new Paint();
        circlePaint.setColor(Color.BLACK);
        circlePaint.setStyle(Paint.Style.STROKE);
        circlePaint.setStrokeWidth(10);

        //刻度
        keduPaint = new Paint();
        keduPaint.setColor(Color.BLACK);
        circlePaint.setStrokeWidth(3);
        circlePaint.setStyle(Paint.Style.STROKE);

        //时针和分针
        hourPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        hourPaint.setStrokeWidth(15);
        hourPaint.setStyle(Paint.Style.STROKE);
        hourPaint.setColor(Color.BLACK);

        minuterPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        minuterPaint.setStrokeWidth(8);
        minuterPaint.setStyle(Paint.Style.STROKE);
        minuterPaint.setColor(Color.BLACK);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //防止在xml输入wrap_content导致布局变形
        //设置为始终保持正方形
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);

        setMeasuredDimension(width > height ? height : width, height > width ? width : height);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //画一个圆
        canvas.drawCircle(getWidth() / 2, getHeight() / 2, getWidth() / 4, circlePaint);
        //画刻度
        for (int i = 0; i < 12; i++) {
            if (i == 0 || i == 3 || i == 6 || i == 9) {
                keduPaint.setStrokeWidth(6);
                keduPaint.setTextSize(40);
                //画刻度
                canvas.drawLine(getWidth() / 2, getHeight() / 2 - getWidth() / 4, getWidth() / 2, getHeight() / 2 - getWidth() / 4 + 50, keduPaint);
                //画时间
                String timeText = String.valueOf(i);
                canvas.drawText(timeText, getWidth() / 2 - keduPaint.measureText(timeText) / 2, getHeight() / 2 - getWidth() / 4 + 80, keduPaint);
            } else {
                keduPaint.setStrokeWidth(3);
                keduPaint.setTextSize(20);
                //画刻度
                canvas.drawLine(getWidth() / 2, getHeight() / 2 - getWidth() / 4, getWidth() / 2, getHeight() / 2 - getWidth() / 4 + 25, keduPaint);
                //画时间
                String timeText = String.valueOf(i);
                canvas.drawText(timeText, getWidth() / 2 - keduPaint.measureText(timeText) / 2, getHeight() / 2 - getWidth() / 4 + 80, keduPaint);
            }

            canvas.rotate(30, getWidth() / 2, getHeight() / 2);
        }

        //画布平移到中点
        canvas.translate(getWidth()/2,getHeight()/2);
        //画时针
        canvas.drawLine(0, 0, 100 , 0, hourPaint);
        //画分针
        canvas.drawLine(0, 0, 0, 130, minuterPaint);
    }
}

下面介绍一下其中比较重要的api吧

画一条直线: canvas.drawLine(float startX, float startY, float stopX, float stopY, @NonNull Paint paint)

  1. starX: 开始时XX坐标
  2. startY:开始时的Y坐标
  3. stopX:结束时的X坐标
  4. stopY:结束时的Y坐标
  5. paint :这条直线的画笔(我们可以通过画笔设置一些颜色,字体大小,宽度,等参数)

 画圆:

canvas.drawCircle(float cx, float cy, float radius, @NonNull Paint paint)

  1. cx:原点X坐标位置
  2. cy:原点Y坐标位置
  3. radius:半径
  4. paint:圆的画笔

画文字:

canvas.drawText(@NonNull String text, float x, float y, @NonNull Paint paint)

  1. text:需要画的文字
  2. x:开始画字的x坐标
  3. y:开始画字的y坐标
  4. paint:字的画笔

 

画钟表上的文字的时候,要明白,其实就是在刻度的终点画这个文字,然后我们要使文字稍微居中一点,可以这样:

开始画字的X坐标 - paint.measureText()/2 ;

旋转:

canvas.rotate(float degrees, float px, float py);

  1. degress:旋转的角度
  2. px:旋转的原点X
  3. py:旋转的原点Y

平移: canvas.translate(float dx, float dy);

手机的坐标原点都是在左上角的位置,这个方法是把这个手机的原始坐标点,移动到另一个点,作为手机的左上角,再开始计算位置的。

最后贴上布局文件:

<xxx.CustomClockView
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

结束,下班。哈哈。这是入门的第一个,后面我还会继续出更多的自定义view和大家一起学习,大家一起成长哦。