通过Canvas的平移与旋转简化绘图逻辑是一个非常有用的技巧,下面的时钟view就是利用这个方法完成的,省去了使用三角函数计算坐标的麻烦。
package com.example.swt369.simpleclock;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.Toast;
import java.util.Calendar;
/**
* Created by swt369 on 2017/8/20.
*/
public class ClockView extends View {
//时钟各个部件的长度
private float mScaleLengthLong;
private float mScaleLengthShort;
private float mTickLengthHour;
private float mTickLengthMinute;
private float mTickLengthSecond;
//view的宽和高
private float mWidth;
private float mHeight;
//时钟半径
private float mRadius;
//绘制各部件时用的Paint
private Paint mPaintScaleLong;
private Paint mPaintScaleShort;
private Paint mPaintOutline;
private Paint mPaintNum;
private Paint mPaintTickHour;
private Paint mPaintTickMinute;
private Paint mPaintTickSecond;
private ViewTreeObserver.OnPreDrawListener onPreDrawListener;
public ClockView(final Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
onPreDrawListener = new ViewTreeObserver.OnPreDrawListener() {
//获取view宽高并计算各个部件的长度
@Override
public boolean onPreDraw() {
mWidth = getMeasuredWidth();
mHeight = getMeasuredHeight();
mRadius = Math.min(mWidth,mHeight) / 2 * 0.95f;
mScaleLengthLong = mRadius * 0.1f;
mScaleLengthShort = mRadius * 0.05f;
mTickLengthHour = mRadius * 0.3f;
mTickLengthMinute = mRadius * 0.45f;
mTickLengthSecond = mRadius * 0.6f;
return true;
}
};
getViewTreeObserver().addOnPreDrawListener(onPreDrawListener);
//点击显示具体时间
setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Calendar calendar = Calendar.getInstance();
String time = String.format("当前时间:%02d:%02d:%02d",
calendar.get(Calendar.HOUR_OF_DAY),calendar.get(Calendar.MINUTE),calendar.get(Calendar.SECOND));
Toast.makeText(context,time, Toast.LENGTH_SHORT).show();
}
});
//初始化所有Paint对象
initializePaints();
}
@Override
protected void onDraw(Canvas canvas) {
if(mWidth == 0 || mHeight == 0){
return;
}
if(onPreDrawListener != null){
getViewTreeObserver().removeOnPreDrawListener(onPreDrawListener);
onPreDrawListener = null;
}
//绘制时钟
drawClock(canvas);
//一秒后重绘
postInvalidateDelayed(1000);
}
private void drawClock(Canvas canvas) {
//保存原始状态
canvas.save();
//将坐标系原点移到中心,并逆时针旋转90度。完成后x轴朝上。
canvas.translate(mWidth / 2,mHeight / 2);
canvas.rotate(-90);
//画外围轮廓
canvas.drawCircle(0,0,mRadius, mPaintOutline);
//画刻度
for(int i = 0 ; i < 12 ; i++){
String num = String.valueOf(i == 0 ? 12 : i);
if(i % 3 == 0){
canvas.drawLine(mRadius,0,mRadius - mScaleLengthLong,0, mPaintScaleLong);
}else {
canvas.drawLine(mRadius,0,mRadius - mScaleLengthShort,0, mPaintScaleShort);
}
canvas.drawText(num,mRadius - mScaleLengthLong - mPaintNum.measureText(num) * 2,0, mPaintNum);
//顺时针旋转30度
canvas.rotate(30);
}
Calendar calendar = Calendar.getInstance();
//画时针
int hour = calendar.get(Calendar.HOUR);
canvas.save();
canvas.rotate(hour * 30);
canvas.drawLine(0,0,mTickLengthHour,0,mPaintTickHour);
canvas.restore();
//画分针
int minute = calendar.get(Calendar.MINUTE);
canvas.save();
canvas.rotate(minute * 6);
canvas.drawLine(0,0,mTickLengthMinute,0,mPaintTickMinute);
canvas.restore();
//画秒针
int second = calendar.get(Calendar.SECOND);
canvas.save();
canvas.rotate(second * 6);
canvas.drawLine(0,0,mTickLengthSecond,0,mPaintTickSecond);
canvas.restore();
//恢复原始状态
canvas.restore();
}
private void initializePaints(){
mPaintScaleLong = new Paint();
mPaintScaleLong.setAntiAlias(true);
mPaintScaleLong.setStrokeWidth(5);
mPaintScaleShort = new Paint();
mPaintScaleShort.setAntiAlias(true);
mPaintScaleShort.setStrokeWidth(3);
mPaintOutline = new Paint();
mPaintOutline.setStyle(Paint.Style.STROKE);
mPaintOutline.setAntiAlias(true);
mPaintOutline.setStrokeWidth(5);
mPaintNum = new Paint();
mPaintNum.setTextSize(30);
mPaintTickHour = new Paint();
mPaintTickHour.setAntiAlias(true);
mPaintTickHour.setStrokeWidth(6);
mPaintTickMinute = new Paint();
mPaintTickMinute.setAntiAlias(true);
mPaintTickMinute.setStrokeWidth(4);
mPaintTickSecond = new Paint();
mPaintTickSecond.setAntiAlias(true);
mPaintTickSecond.setStrokeWidth(2);
}
}
代码注释已经比较详细了,下面把比较重要的部分再说明一下:
//保存原始状态 canvas.save(); //省略中间部分... //恢复原始状态 canvas.restore();
在绘图开始时调用canvas.save(),可以保存下未经任何平移、旋转操作的原始画布状态。在所有绘图工作完成后调用canvas.restore(),可以恢复到上一次保存的状态(类似进出栈的感觉)。
//将坐标系原点移到中心,并逆时针旋转90度。完成后x轴朝上。 canvas.translate(mWidth / 2,mHeight / 2); canvas.rotate(-90);
画布的平移与旋转可能比较抽象,可以想象成坐标系的平移与旋转。调用canvas.translate(dx,dy)相当于将坐标原点向x,y方向移动了dx,dy的距离,调用canvas.rotate(degree)相当于坐标系顺时针旋转了degree°。
//画刻度
for(int i = 0 ; i < 12 ; i++){
String num = String.valueOf(i == 0 ? 12 : i);
if(i % 3 == 0){
canvas.drawLine(mRadius,0,mRadius - mScaleLengthLong,0, mPaintScaleLong);
}else {
canvas.drawLine(mRadius,0,mRadius - mScaleLengthShort,0, mPaintScaleShort);
}
canvas.drawText(num,mRadius - mScaleLengthLong - mPaintNum.measureText(num) * 2,0, mPaintNum);
//顺时针旋转30度
canvas.rotate(30);
}
根据i值决定是画大刻度(90°的倍数)还是小刻度。每次画完一条之后将坐标系顺时针旋转30°,这样保证每次画的刻度线的坐标不变。
//一秒后重绘 postInvalidateDelayed(1000);
作用是在1000ms(1s)后再次执行View的draw流程,产生指针运动的效果。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
# Android
# 时钟
# View
# Android获取设备CPU核数、时钟频率以及内存大小的方法
# Android多功能时钟开发案例(实战篇)
# android实现widget时钟示例分享
# Android 仿日历翻页、仿htc时钟翻页、数字翻页切换效果
# Android多功能时钟开发案例(基础篇)
# android高仿小米时钟(使用Camera和Matrix实现3D效果)
# Android自定义动态壁纸开发(时钟)
# Android编程基于自定义控件实现时钟功能的方法
# Android仿小米时钟效果
# Android自定义View实现时钟功能
# 顺时针
# 完成后
# 移到
# 朝上
# 是在
# 后将
# 是一个非常
# 时用
# 大家多多
# mHeight
# mRadius
# mTickLengthSecond
# mWidth
# mPaintScaleShort
# mPaintOutline
# Canvas
# mPaintScaleLong
# private
# float
# ClockView
相关文章:
ppt制作免费网站有哪些,ppt模板免费下载网站?
C++如何将C风格字符串(char*)转换为std::string?(代码示例)
建站主机解析:虚拟主机配置与服务器选择指南
,柠檬视频怎样兑换vip?
设计网站制作公司有哪些,制作网页教程?
如何使用Golang table-driven基准测试_多组数据测量函数效率
如何在建站宝盒中设置产品搜索功能?
极客网站有哪些,DoNews、36氪、爱范儿、虎嗅、雷锋网、极客公园这些互联网媒体网站有什么差异?
网站制作专业公司有哪些,如何制作一个企业网站,建设网站的基本步骤有哪些?
如何做静态网页,sublimetext3.0制作静态网页?
如何用VPS主机快速搭建个人网站?
交易网站制作流程,我想开通一个网站,注册一个交易网址,需要那些手续?
山东网站制作公司有哪些,山东大源集团官网?
制作网站怎么制作,*游戏网站怎么搭建?
外贸公司网站制作,外贸网站建设一般有哪些步骤?
如何高效生成建站之星成品网站源码?
高防服务器如何保障网站安全无虞?
如何用腾讯建站主机快速创建免费网站?
北京营销型网站制作公司,可以用python做一个营销推广网站吗?
在线教育网站制作平台,山西立德教育官网?
企业网站制作费用多少,企业网站空间一般需要多大,费用是多少?
建站主机无法访问?如何排查域名与服务器问题
相册网站制作软件,图片上的网址怎么复制?
c# 在高并发场景下,委托和接口调用的性能对比
外贸公司网站制作哪家好,maersk船公司官网?
h5在线制作网站电脑版下载,h5网页制作软件?
建站之星安全性能如何?防护体系能否抵御黑客入侵?
,网页ppt怎么弄成自己的ppt?
网页制作模板网站推荐,网页设计海报之类的素材哪里好?
利用JavaScript实现拖拽改变元素大小
定制建站价位费用解析与套餐推荐全攻略
建站之星后台密码遗忘?如何快速找回?
股票网站制作软件,网上股票怎么开户?
移民网站制作流程,怎么看加拿大移民官网?
企业在线网站设计制作流程,想建设一个属于自己的企业网站,该如何去做?
如何用花生壳三步快速搭建专属网站?
已有域名如何快速搭建专属网站?
建站之星如何助力企业快速打造五合一网站?
公司网站设计制作厂家,怎么创建自己的一个网站?
清除minerd进程的简单方法
如何在Golang中使用encoding/gob序列化对象_存储和传输数据
如何零基础在云服务器搭建WordPress站点?
如何通过商城自助建站源码实现零基础高效建站?
宝塔新建站点报错如何解决?
如何用AWS免费套餐快速搭建高效网站?
JS中使用new Date(str)创建时间对象不兼容firefox和ie的解决方法(两种)
如何通过山东自助建站平台快速注册域名?
名字制作网站免费,所有小说网站的名字?
合肥做个网站多少钱,合肥本地有没有比较靠谱的交友平台?
制作证书网站有哪些,全国城建培训中心证书查询官网?
*请认真填写需求信息,我们会在24小时内与您取得联系。