最近想好好看下自定义View,有趣使用,下面是在学习别人代码的基础上写出来的一个View。
package com.example.xxiang1x.teststudio;
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.util.AttributeSet;
import android.view.View;
import java.util.Calendar;
import java.util.GregorianCalendar;
/**
* 手表表盘
*/
public class WatchView extends View {
//create some variables
/**
* 分针画笔
*/
private Paint minPaint;
/**
* 秒针画笔
*/
private Paint secondPaint;
/**
* 时针画笔
*/
private Paint hourPaint;
/**
* 表盘外轮廓画笔
*/
private Paint circlePaint;
/**
* 表盘文字的画笔
*/
private Paint textPaint;
/**
* 表盘内短线画笔
*/
private Paint linePaint;
//width and height
/**
* View的宽
*/
private int mWidth;
/**
* View的高
*/
private int mHeight;
private static final double ROUND = 2d * Math.PI;
private static final double QUARTER = 1d / 4d;
private Handler mHandler = new Handler(Looper.getMainLooper());
private Calendar calendar = new GregorianCalendar();
public WatchView(Context context) {
super(context);
}
public WatchView(Context context, AttributeSet attrs) {
super(context, attrs);
initPaint();
}
/**
* 创建所有的paint
*/
private void initPaint() {
minPaint = getAvailablePaint(Color.BLUE, 0, 15, Paint.Style.FILL_AND_STROKE);
secondPaint = getAvailablePaint(Color.RED, 0, 15, Paint.Style.FILL_AND_STROKE);
hourPaint = getAvailablePaint(Color.GRAY, 0, 15, Paint.Style.FILL_AND_STROKE);
circlePaint = getAvailablePaint(Color.GRAY, 5, 10, Paint.Style.STROKE);
textPaint = getAvailablePaint(Color.GRAY, 45, 3, Paint.Style.FILL);
linePaint = getAvailablePaint(Color.GRAY, 45, 3, Paint.Style.FILL);
}
/**
* get a paint by ur request.
*
* @param color
* @param textSize
* @param strockWidth
* @param style
* @return
*/
private Paint getAvailablePaint(int color, int textSize, int strockWidth, Paint.Style style) {
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FAKE_BOLD_TEXT_FLAG);
paint.setAntiAlias(true);
paint.setTextSize(textSize);
paint.setAlpha(1);
paint.setColor(color);
paint.setStyle(style);
paint.setStrokeWidth(strockWidth);
paint.setStrokeCap(Paint.Cap.ROUND);
paint.setTextAlign(Paint.Align.CENTER);
paint.setStrokeCap(Paint.Cap.ROUND);
paint.setDither(true);//设置图像抖动处理
paint.setStrokeJoin(Paint.Join.ROUND);//画笔线等连接处的轮廓样式
paint.setSubpixelText(true);
return paint;
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public WatchView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//获取圆心坐标
int x = mWidth / 2;
int y = mHeight / 2;
//半径
int radius = Math.min(x, y) - 10;
// 为了让秒针连续转动,所以秒针的角度肯定不是从「秒」这个整数里来
// 刚好秒针走一圈是 1 分钟,那么,就用分乘以「一圈(2π)」就是秒针要走的弧度数了
float millis = calendar.get(Calendar.MILLISECOND) / 1000f;
float second = (calendar.get(Calendar.SECOND) + millis) / 60f;
float minute = (calendar.get(Calendar.MINUTE) + second) / 60f;
float hour = (calendar.get(Calendar.HOUR) + minute) / 12f;
drawHand(canvas, hourPaint, x, y, radius * 0.5f, hour);
drawHand(canvas, minPaint, x, y, radius * 0.6f, minute);
drawHand(canvas, secondPaint, x, y, radius * 0.7f, second);
//draw the hour line .
drawHourNumbers(canvas, textPaint, mWidth, mHeight);
//draw the minutes line .
drawMinuteLine(canvas, linePaint, mWidth, mHeight);
//draw outer circle
circlePaint.setColor(Color.GRAY);
canvas.drawCircle(x, y, radius, circlePaint);
//draw center point
circlePaint.setColor(Color.YELLOW);
canvas.drawCircle(x, y, 3, circlePaint);
}
/**
* 画小时的线
*
* @param canvas
* @param paint
* @param width
* @param height
*/
private void drawHourNumbers(Canvas canvas, Paint paint, int width, int height) {
//12个小时,12条线。
for (int i = 1; i < 13; i++) {
canvas.save(); //save current state of canvas.
canvas.rotate(360 / 12 * i, width / 2, height / 2);
//绘制表盘
canvas.drawLine(width / 2, height / 2 - (width / 2 - 20), width / 2, height / 2 - width / 2 + 40, paint);
//绘制文字
canvas.drawText("" + i, width / 2, height / 2 - width / 2 + 80, paint);
//恢复开始位置
canvas.restore();
}
}
/**
* 画分钟的线
*
* @param canvas
* @param paint
* @param width
* @param height
*/
private void drawMinuteLine(Canvas canvas, Paint paint, int width, int height) {
//一共分出来有60条线
for (int i = 1; i < 61; i++) {
canvas.save(); //save current state of canvas.
canvas.rotate(360 / 12 / 5 * i, width / 2, height / 2);
//绘制表盘
canvas.drawLine(width / 2, height / 2 - (width / 2 - 20), width / 2, height / 2 - width / 2 + 30, paint);
//恢复开始位置
canvas.restore();
}
}
/**
* @param canvas
* @param paint
* @param x
* @param y
* @param length
* @param round
*/
private void drawHand(Canvas canvas, Paint paint, float x, float y, float length, float round) {
// 三角函数的坐标轴是以 3 点方向为 0 的,所以记得要减去四分之一个圆周哦
double radians = (round - QUARTER) * ROUND;
canvas.drawLine(
x,
y,
x + (float) Math.cos(radians) * length,
y + (float) Math.sin(radians) * length,
paint);
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
mHandler.post(r);
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
mHandler.removeCallbacksAndMessages(null);//remove all of the messages.
}
//子线程+handler不断更新View
Runnable r = new Runnable() {
@Override
public void run() {
calendar.setTimeInMillis(System.currentTimeMillis());
invalidate();
mHandler.postDelayed(this, 1000 / 60);
}
};
/**
* 获取宽和高
*
* @param widthMeasureSpec
* @param heightMeasureSpec
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//获取View的宽高。
mWidth = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
mHeight = getDefaultSize(getSuggestedMinimumWidth(), heightMeasureSpec);
}
}
擦,在studio的模拟器上面好多了。在genymotion模拟器上比较模糊。
Screen Shot 2016-04-08 at 4.36.48 PM.png
Screen Shot 2016-04-08 at 3.39.40 PM.png
网友评论