Android 自定义 View--> 绘制时钟(表)效果
Posted Kevin-Dev
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 自定义 View--> 绘制时钟(表)效果相关的知识,希望对你有一定的参考价值。
前言
本篇文章主要介绍使用自定义 View
来实现时钟效果,灵活地使用 android 的 Canvas
,Paint
, Path
的 API 以及理清 Canvas
的 save
和 restore
的意义。
代码实现
1. 新建一个类继承 View
public class ClockView extends View
//原点
private Point mCoo = new Point(500, 800);
private Path mMainPath;
private Paint mMainPaint;
public ClockView(Context context)
this(context,null);
public ClockView(Context context, @Nullable AttributeSet attrs)
super(context, attrs);
init();
private void init()
//初始化画笔
mMainPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mMainPaint.setStyle(Paint.Style.STROKE);
mMainPaint.setStrokeCap(Paint.Cap.ROUND);
mMainPath = new Path();
@Override
protected void onDraw(Canvas canvas)
super.onDraw(canvas);
//绘制
canvas.save();//新建图层1
canvas.translate(mCoo.x, mCoo.y);
drawBreakCircle(canvas);
drawDot(canvas);
drawText(canvas);
Calendar calendar = Calendar.getInstance();
int hour = calendar.get(Calendar.HOUR_OF_DAY);
int min = calendar.get(Calendar.MINUTE);
int sec = calendar.get(Calendar.SECOND);
drawH(canvas, hour / 12.f * 360 - 90 + min / 60.f * 30 + sec / 3600.f * 30);
drawM(canvas, min / 60.f * 360 - 90 + sec / 60.f);
drawS(canvas, sec / 60.f * 360 - 90);
canvas.restore();
2. 绘制逻辑
2.1 绘制破碎的圆
/**
* 绘制破碎的圆
*
* @param canvas
*/
private void drawBreakCircle(Canvas canvas)
mMainPaint.setStrokeWidth(8);
mMainPaint.setColor(Color.parseColor("#D5D5D5"));
for (int i = 0; i < 4; i++)
canvas.save();
canvas.rotate(90 * i);
canvas.drawArc(
-350, -350, 350, 350,
10, 70, false, mMainPaint);
canvas.restore();
2.2 绘制小点
画 60 个点(小线),每逢 5 变长,也就是画直线,每次将画布旋转 360 / 60 = 6°
/**
* 绘制小点
*
* @param canvas
*/
private void drawDot(Canvas canvas)
for (int i = 0; i < 60; i++)
if (i % 5 == 0)
canvas.save();
canvas.rotate(30 * i);
mMainPaint.setStrokeWidth(8);
mMainPaint.setColor(randomRGB());
canvas.drawLine(250, 0, 300, 0, mMainPaint);
mMainPaint.setStrokeWidth(10);
mMainPaint.setColor(Color.BLACK);
canvas.drawPoint(250, 0, mMainPaint);
canvas.restore();
else
canvas.save();
canvas.rotate(6 * i);
mMainPaint.setStrokeWidth(4);
mMainPaint.setColor(Color.BLUE);
canvas.drawLine(280, 0, 300, 0, mMainPaint);
canvas.restore();
/**
* 返回随机颜色
*
* @return 随机颜色
*/
public static int randomRGB()
Random random = new Random();
int r = 30 + random.nextInt(200);
int g = 30 + random.nextInt(200);
int b = 30 + random.nextInt(200);
return Color.rgb( r, g, b);
2.3 绘制文字
/**
* 添加文字
*
* @param canvas
*/
private void drawText(Canvas canvas)
mMainPaint.setTextSize(60);
mMainPaint.setStrokeWidth(5);
mMainPaint.setStyle(Paint.Style.FILL);
mMainPaint.setTextAlign(Paint.Align.CENTER);
mMainPaint.setColor(Color.BLUE);
canvas.drawText("Ⅲ", 350, 30, mMainPaint);
canvas.drawText("Ⅵ", 0, 350 + 30, mMainPaint);
canvas.drawText("Ⅸ", -350, 30, mMainPaint);
canvas.drawText("Ⅻ", 0, -350 + 30, mMainPaint);
//使用外置字体放在assets目录下
Typeface myFont = Typeface.createFromAsset(getContext().getAssets(), "CHOPS.TTF");
mMainPaint.setTypeface(myFont);
mMainPaint.setTextSize(70);
canvas.drawText("Kevin", 0, -150, mMainPaint);
tips:
.ttf 字体文件下载地址:https://www.fonts.net.cn/
2.4 绘制时针
/**
* 绘制时针
*
* @param canvas
* @param deg
*/
private void drawH(Canvas canvas, float deg)
canvas.save();
canvas.rotate(deg);
mMainPaint.setColor(Color.BLACK);
mMainPaint.setStrokeCap(Paint.Cap.ROUND);
mMainPaint.setStrokeWidth(8);
canvas.drawLine(0, 0, 150, 0, mMainPaint);
canvas.restore();
2.5 绘制分针
/**
* 绘制分针
*
* @param canvas
* @param deg
*/
private void drawM(Canvas canvas, float deg)
canvas.save();
canvas.rotate(deg);
mMainPaint.setColor(Color.BLACK);
mMainPaint.setStrokeWidth(8);
canvas.drawLine(0, 0, 200, 0, mMainPaint);
mMainPaint.setColor(Color.GRAY);
mMainPaint.setStrokeWidth(30);
canvas.drawPoint(0, 0, mMainPaint);
canvas.restore();
2.6 绘制秒针
/**
* 绘制秒针
*
* @param canvas
* @param deg
*/
private void drawS(Canvas canvas, float deg)
mMainPaint.setStyle(Paint.Style.STROKE);
mMainPaint.setColor(Color.RED);
mMainPaint.setStrokeWidth(8);
mMainPaint.setStrokeCap(Paint.Cap.SQUARE);
canvas.save();
canvas.rotate(deg);
canvas.save();
canvas.rotate(45);
//使用path绘制:在init里初始化一下就行了
mMainPath.addArc(-25, -25, 25, 25, 0, 240);
canvas.drawPath(mMainPath, mMainPaint);
canvas.restore();
mMainPaint.setStrokeCap(Paint.Cap.ROUND);
canvas.drawLine(-25, 0, -50, 0, mMainPaint);
mMainPaint.setStrokeWidth(2);
mMainPaint.setColor(Color.RED);
canvas.drawLine(0, 0, 320, 0, mMainPaint);
mMainPaint.setStrokeWidth(15);
mMainPaint.setColor(Color.RED);
canvas.drawPoint(0, 0, mMainPaint);
canvas.restore();
让时钟动起来
1. 布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white"
android:orientation="vertical"
tools:context=".ParcticeOneActivity">
<com.kjd.gesturedemo.widget.ClockView
android:id="@+id/clockView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
2. 更新时间
public class ParcticeOneActivity extends AppCompatActivity
/**
* 新建Handler
*/
Handler mHandler = new Handler()
@Override
public void handleMessage(Message msg)
mView.invalidate();//处理:刷新视图
;
private View mView;
private final Timer timer = new Timer();
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_parctice_one);
mView = findViewById(R.id.clockView);
TimerTask timerTask = new TimerTask()
@Override
public void run()
mHandler.sendEmptyMessage(0);//发送消息
;
//定时任务
timer.schedule(timerTask, 0, 1000);
public void clicked(View view)
new HighLightView(this).showTipForView(view, "", new View.OnClickListener()
@Override
public void onClick(View v)
);
以上是关于Android 自定义 View--> 绘制时钟(表)效果的主要内容,如果未能解决你的问题,请参考以下文章