s时钟画布 android,Android自定义控件实现时钟效果

在学习安卓群英传自定义控件章节的时候,有一个例子是绘制时钟,在实现了书上的例子后就想看这个时钟能不能动起来。

这里选择延迟一秒发送消息重绘view来实现的动画,对外提供了开启时钟,关闭时钟的方法,当activity执行onResume方法的时候,执行startClock()方法,当移除view或activity执行onStop方法的时候可以执行stopClock()方法。

首先根据view的宽高来确定圆心的位置,并画出一个圆。再通过view高度的一半减去圆的半径,确定刻度的起始位置,选择刻度的长度并绘制出来。然后再刻度下方绘制出数字。最终将画布进行旋转,时钟总共有60个刻度,循环旋转,每次旋转6度即可。

最后是绘制指针,通过计算算出指针对应每个刻度的X,Y坐标并绘制直线。

9f305b2bd49757e2336b1dc54fd068d7.gif

代码实现

自定义控件的代码:

public class ClockView extends View{

private Paint circlePaint,dialPaint,numberPaint;

//view 的宽高

private float mWidth,mHeight;

//圆的半径

private float circleRadius;

//圆心X,Y坐标

private float circleX,circleY;

private int second,minute;

private double hour;

private Handler handler = new Handler(Looper.getMainLooper()){

@Override

public void handleMessage(Message msg) {

super.handleMessage(msg);

if(msg.what==0){

invalidate();

}

}

};

public ClockView(Context context, AttributeSet attrs) {

super(context, attrs);

initPaint();

}

private void initPaint(){

//刻盘圆,小时刻度,时针和分针的画笔

circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);

circlePaint.setColor(Color.BLACK);

circlePaint.setStyle(Paint.Style.STROKE);

circlePaint.setStrokeWidth(10);

//分钟刻度的画笔

dialPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

dialPaint.setColor(Color.BLACK);

dialPaint.setStrokeWidth(5);

//数字的画笔

numberPaint = new Paint(Paint.ANTI_ALIAS_FLAG);

numberPaint.setColor(Color.BLACK);

numberPaint.setStrokeWidth(5);

numberPaint.setTextSize(30);

}

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

mWidth = getMeasuredWidth();

mHeight = getMeasuredHeight();

if(mWidth

//圆的半径为view的宽度的一半再减9,防止贴边

circleRadius = mWidth/2-9;

circleX = mWidth/2;

circleY = mHeight/2;

} else{

circleRadius = mHeight/2-9;

circleX = mWidth/2;

circleY = mHeight/2;

}

}

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

setTimes();

drawCirclePoint(canvas);

drawCircle(canvas);

drawDial(canvas);

drawPointer(canvas);

}

/**圆心

* @param canvas

*/

private void drawCirclePoint(Canvas canvas){

canvas.drawCircle(circleX,circleY,5,circlePaint);

}

private void drawCircle(Canvas canvas){

canvas.drawCircle(circleX,circleY,circleRadius,circlePaint);

}

/**画刻度及时间

* @param canvas

*/

private void drawDial(Canvas canvas){

//时钟用长一点的刻度,画笔用画圆的画笔

Point hourStartPoint = new Point(circleX,circleY-circleRadius);

Point hourEndPoint = new Point(circleX,circleY-circleRadius+40);

//分钟的刻度要稍微短一些,画笔用画圆的画笔

Point startPoint2 = new Point(circleX,circleY-circleRadius);

Point endPoint2 = new Point(circleX,circleY-circleRadius+10);

//开始画刻度和数字,总共60个刻度,12个时钟刻度,被5整除画一个时钟刻度,被其余的为分针刻度

String clockNumber;

for(int i=0;i<60;i++){

if(i%5==0){

if(i==0){

clockNumber = "12";

} else{

clockNumber = String.valueOf(i/5);

}

//时针刻度

canvas.drawLine(hourStartPoint.getX(),hourStartPoint.getY(),hourEndPoint.getX(),hourEndPoint.getY(),circlePaint);

//画数字,需在时针刻度末端加30

canvas.drawText(clockNumber,circleX-numberPaint.measureText(clockNumber)/2,hourEndPoint.getY()+30,numberPaint);

} else{

//画分针刻度

canvas.drawLine(startPoint2.getX(),startPoint2.getY(),endPoint2.getX(),endPoint2.getY(),circlePaint);

}

//画布旋转6度

canvas.rotate(360/60,circleX,circleY);

}

}

/**画指针

* X点坐标 cos(弧度)*r

* Y点坐标 sin(弧度)*r

* toRadians将角度转成弧度

* 安卓坐标系与数学坐标系不同的地方是X轴是相反的,所以为了调整方向,需要将角度+270度

* @param canvas

*/

private void drawPointer(Canvas canvas){

canvas.translate(circleX,circleY);

float hourX = (float) Math.cos(Math.toRadians(hour*30+270))*circleRadius*0.5f;

float hourY = (float) Math.sin(Math.toRadians(hour*30+270))*circleRadius*0.5f;

float minuteX = (float) Math.cos(Math.toRadians(minute*6+270))*circleRadius*0.8f;

float minuteY = (float) Math.sin(Math.toRadians(minute*6+270))*circleRadius*0.8f;

float secondX = (float) Math.cos(Math.toRadians(second*6+270))*circleRadius*0.8f;

float secondY = (float) Math.sin(Math.toRadians(second*6+270))*circleRadius*0.8f;

canvas.drawLine(0,0,hourX,hourY,circlePaint);

canvas.drawLine(0,0,minuteX,minuteY,circlePaint);

canvas.drawLine(0,0,secondX,secondY,dialPaint);

//一秒重绘一次

handler.sendEmptyMessageDelayed(0,1000);

}

public void startClock(){

setTimes();

invalidate();

}

private void setTimes(){

Date date = new Date();

Calendar calendar = Calendar.getInstance();

calendar.setTime(date);

second = getTimes(date,Calendar.SECOND);

minute = getTimes(date,Calendar.MINUTE);

hour = getTimes(date,Calendar.HOUR)+minute/12*0.2;

}

private int getTimes(Date date,int calendarField){

Calendar calendar = Calendar.getInstance();

calendar.setTime(date);

return calendar.get(calendarField);

}

public void stopClock(){

handler.removeMessages(0);

}

}

public class Point {

private float x;

private float y;

public Point(float x, float y) {

this.x = x;

this.y = y;

}

public float getX() {

return x;

}

public void setX(float x) {

this.x = x;

}

public float getY() {

return y;

}

public void setY(float y) {

this.y = y;

}

Acitivity:

public class ClockActivity extends Activity{

private ClockView clockView;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.clock_layout);

clockView = (ClockView) findViewById(R.id.clock);

}

@Override

protected void onResume() {

super.onResume();

clockView.startClock();

}

@Override

protected void onStop() {

super.onStop();

clockView.stopClock();

}

}

xml布局:

android:orientation="vertical" android:layout_width="match_parent"

android:gravity="center"

android:layout_height="match_parent">

android:layout_width="match_parent"

android:id="@+id/clock"

android:layout_height="match_parent" />

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持云海天教程。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值