今天我们来一起学习一下怎么通过自定义view画一个时钟出来。
自定义view是一个比较有意思,同时难度也是很高的工作。现在市面上有很多动画效果很棒的页面,无非都是一步一步从最基础的学起的,正所谓万丈高楼平地起。所以,这篇文章很适合新手入门练习哦。
首先先贴上最终的效果图吧,这样到时看代码不会特别抽象。
下面我说一下,实现的步骤是什么吧。
- 画一个外圆(确定圆心位置,然后给一个半径)
- 画刻度(将圆等分成12部分,先画处0点的位置,最后通过画布的旋转,旋转的角度的360/12,画刻度直线)
- 画时针和分针(把手机的坐标原点移动到圆的中心点,再画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)
- starX: 开始时XX坐标
- startY:开始时的Y坐标
- stopX:结束时的X坐标
- stopY:结束时的Y坐标
- paint :这条直线的画笔(我们可以通过画笔设置一些颜色,字体大小,宽度,等参数)
画圆:
canvas.drawCircle(float cx, float cy, float radius, @NonNull Paint paint)
- cx:原点X坐标位置
- cy:原点Y坐标位置
- radius:半径
- paint:圆的画笔
画文字:
canvas.drawText(@NonNull String text, float x, float y, @NonNull Paint paint)
- text:需要画的文字
- x:开始画字的x坐标
- y:开始画字的y坐标
- paint:字的画笔
画钟表上的文字的时候,要明白,其实就是在刻度的终点画这个文字,然后我们要使文字稍微居中一点,可以这样:
开始画字的X坐标 - paint.measureText()/2 ;
旋转:
canvas.rotate(float degrees, float px, float py);
- degress:旋转的角度
- px:旋转的原点X
- py:旋转的原点Y
平移: canvas.translate(float dx, float dy);
手机的坐标原点都是在左上角的位置,这个方法是把这个手机的原始坐标点,移动到另一个点,作为手机的左上角,再开始计算位置的。
最后贴上布局文件:
<xxx.CustomClockView
android:layout_width="match_parent"
android:layout_height="match_parent" />
结束,下班。哈哈。这是入门的第一个,后面我还会继续出更多的自定义view和大家一起学习,大家一起成长哦。