100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > Android 自定义View加属性动画实现动画时钟

Android 自定义View加属性动画实现动画时钟

时间:2019-06-28 07:53:43

相关推荐

Android 自定义View加属性动画实现动画时钟

目录

前言

效果图

项目实现

用到的属性

重写三个构造方法

初始化各个指针的画笔,指针的矩形

重写onMeasure方法

获取系统的时间

重写ondraw方法

最后给时钟添加上属性动画

前言

之前项目有个需求是在桌面上增加一个桌面时钟,当时是参考别人的博客,在其基础上添加了属性动画然后实现的。因此今天特地重新写了一遍这个自定义view 加深印象并分享出来

效果图

用手机拍的视频,然后转为GIF的,因为是试用的,所以就是这个渣渣效果,还有水印,求推荐一个好用的格式转换工具

项目实现

为了编写方便,这里没有用到自定义属性,有需要的话,可以自行添加自定义属性,同时在代码中注释很详细,文章这里只简单介绍一下

用到的属性

private Paint hPaint ,mPaint ,sPaint ,circlePaint ,cPointPaint,paintDegree,txtPaint,titlePaint;private final int maxWidth = 400;int width ,height;int hSound = 0;int mSound = 0;int sSound = 0;private int hcount = 0;//当前小时数private int mcount = 0;//当前分钟数private int scount = 0;//当前秒钟数private final int hScale = 30;//每小时之间30度private static final int mScale = 6;//每分钟之间是6度RectF hRect , mRect ,sRect ;//三个boolean first = true;//执行动画之后再转动指针

重写三个构造方法

public ClockView(Context context) {super(context);init();}public ClockView(Context context, AttributeSet attrs) {super(context, attrs);init();}public ClockView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init();}

初始化各个指针的画笔,指针的矩形

这里各种new操作不要放在Ondraw方法中,避免重复实现

private void init(){//外圆盘画笔circlePaint = new Paint();circlePaint.setAntiAlias(true);circlePaint.setDither(true);circlePaint.setStyle(Paint.Style.STROKE);circlePaint.setColor(Color.BLACK);circlePaint.setStrokeWidth(1);//圆心画笔cPointPaint = new Paint();cPointPaint.setAntiAlias(true);cPointPaint.setDither(true);cPointPaint.setStyle(Paint.Style.FILL_AND_STROKE);cPointPaint.setColor(0xff4CAF50);//绿色cPointPaint.setStrokeWidth(2);//时针画笔hPaint = new Paint();hPaint.setAntiAlias(true);hPaint.setDither(true);hPaint.setStyle(Paint.Style.FILL_AND_STROKE);hPaint.setColor(0xff349CE2);//蓝色hPaint.setStrokeWidth(7);//时针矩形hRect = new RectF(-16,0,89,0);//分针画笔mPaint = new Paint();mPaint.setAntiAlias(true);mPaint.setDither(true);mPaint.setStyle(Paint.Style.FILL_AND_STROKE);mPaint.setColor(0xffDB2540);//红色mPaint.setStrokeWidth(6);//分针矩形mRect = new RectF(-25,0,140,0);//秒针画笔sPaint = new Paint();sPaint.setAntiAlias(true);sPaint.setDither(true);sPaint.setStyle(Paint.Style.FILL_AND_STROKE);sPaint.setColor(0xff4CAF50);//绿色sPaint.setStrokeWidth(5);//秒钟矩形sRect = new RectF(-30,0,180,0);//刻度画笔paintDegree = new Paint();paintDegree.setColor(0xff000000);paintDegree.setStyle(Paint.Style.STROKE);paintDegree.setAntiAlias(true);//文字画笔txtPaint = new Paint();txtPaint.setColor(0xff000000);txtPaint.setTextSize(20);txtPaint.setAntiAlias(true);//标题画笔titlePaint = new Paint();titlePaint.setColor(0xff000000);titlePaint.setTextSize(45);titlePaint.setAntiAlias(true);}

重写onMeasure方法

@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);int width = MeasureSpec.getSize(widthMeasureSpec);int widthMode = MeasureSpec.getMode(widthMeasureSpec);int height = MeasureSpec.getSize(heightMeasureSpec);int heightMode = MeasureSpec.getMode(heightMeasureSpec);if (widthMode == MeasureSpec.AT_MOST && heightMode ==MeasureSpec.AT_MOST){setMeasuredDimension(maxWidth,maxWidth);}else if (widthMode == MeasureSpec.AT_MOST ){setMeasuredDimension(maxWidth,width);}else if (heightMode ==MeasureSpec.AT_MOST ){setMeasuredDimension(height,maxWidth);}}

获取系统的时间

private void getDatas() {SimpleDateFormat format = new SimpleDateFormat("HH,mm,ss");String time = format.format(new Date());try {String s[] = time.split(",");hcount = Integer.parseInt(s[0]);mcount = Integer.parseInt(s[1]);scount = Integer.parseInt(s[2]);} catch (Exception ex) {ex.printStackTrace();}}

重写ondraw方法

首先获取并计算宽高,设置各指针长度以及外圆的半径

super.onDraw(canvas);width = getMeasuredWidth()-getPaddingStart()-getPaddingEnd();height = getMeasuredHeight()-getPaddingBottom()-getPaddingTop();width = height = Math.min(width,height);//圆心点int cpoints = width/2;hSound = width/8;//时针长度mSound = width/6;//分针长度sSound = width/4;//秒针长度int radius =cpoints*3/4;//外圆半径

借用一下别人的图

这里判断是否是第一次显示时钟,等于true为第一次,然后绘制标题,位置的计算根据上图

if(!first){getDatas();}String titleText = "三原色时钟";//X坐标等于圆心的X坐标减去文字的一半的长度,Y坐标等于圆心的Y坐标减圆的半径再减20canvas.drawText(titleText,cpoints - titlePaint.measureText(titleText) / 2 ,cpoints-radius-20,titlePaint);

然后绘制刻度,圆盘

//画出12个小时的刻度线及文字for (int i = 0; i < 12; i++) {String txtTime = Integer.toString(i);//3,6,9,12比其他的略粗略长if(i%3==0) {if (i==0){txtTime = "12";}paintDegree.setStrokeWidth(5);canvas.drawLine(width / 2, height / 2 - radius, width / 2, height / 2 - radius + 20, paintDegree);}else{paintDegree.setStrokeWidth(4);canvas.drawLine(width / 2, height / 2 - radius, width / 2, height / 2 - radius + 15, paintDegree);}canvas.drawText(txtTime,cpoints - txtPaint.measureText(txtTime) / 2,height / 2 - radius + 40,txtPaint);canvas.rotate(hScale, width / 2, height / 2);}//画出60个分钟的刻度线for (int x = 0; x < 60; x++) {paintDegree.setStrokeWidth(3);if (x % 5 != 0) {//当x % 5 == 0时即是时钟刻度,因此不需要绘制,避免重复绘制canvas.drawLine(width / 2, height / 2 - radius, width / 2, height / 2 - radius + 8, paintDegree);}canvas.rotate(mScale, width / 2, height / 2);}//画外层圆canvas.drawCircle(cpoints,cpoints,radius,circlePaint);//画内层圆canvas.drawCircle(cpoints,cpoints,radius/6,circlePaint);//平移至中心点canvas.translate(cpoints,cpoints);//保存画布canvas.save();

最后是绘制三个指针

//int hRotate = 270 + hScale * hcount;int offset = 30 * mcount / 60;offset -= offset % mScale;//时针相对分针数,有一个偏移量int hRotate = 270 + hScale * hcount + offset;canvas.rotate(hRotate);// canvas.drawLine(0, -10, 0, hSound, hPaint);//画时针canvas.drawRoundRect(hRect,15,15,hPaint);//画时针canvas.restore();canvas.save();int mRotate = 270 + mScale * mcount ;canvas.rotate(mRotate);canvas.drawRoundRect(mRect,25,25,mPaint);//画分针//canvas.drawLine(0, -15, 0, mSound, mPaint);//画分针canvas.restore();canvas.save();//一圈360度,总共60秒,因此时间每多一秒,度数加6int sRotate = 270 + mScale * scount ;canvas.rotate(sRotate);//canvas.drawLine(0, -25, 0, sSound, sPaint);//画秒针canvas.drawRoundRect(sRect,15,15,sPaint);//画秒针

绘制指针上的圆心点

canvas.drawCircle(0,0,6,cPointPaint);//画圆心

第一次出现时不转动指针

if(!first){postInvalidateDelayed(1000);}

最后给时钟添加上属性动画

在View中添加一个公共方法给外部调用

public void startAnim(){getDatas();final ValueAnimator animatorh = ValueAnimator.ofInt(0,hcount>12?hcount-12:hcount);//大于十二点时减去12 避免转两圈final ValueAnimator animatorm=ValueAnimator.ofInt(0,mcount);final ValueAnimator animators=ValueAnimator.ofInt(0,scount);//设置动画时长animatorh.setDuration(1500);animatorm.setDuration(1500);animators.setDuration(1500);animatorh.setInterpolator(new LinearInterpolator());animatorh.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {hcount = (int)animation.getAnimatedValue();}});animatorh.start();animatorm.setInterpolator(new LinearInterpolator());animatorm.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {mcount = (int)animation.getAnimatedValue();}});animatorm.start();animators.setInterpolator(new LinearInterpolator());animators.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {scount = (int)animation.getAnimatedValue();postInvalidate();//添加之后动画才会执行,不然看不到效果}});animators.start();//添加动画完成时的监听,在动画完成之后开始指针的转动animators.addListener(new AnimatorListenerAdapter() {@Overridepublic void onAnimationEnd(Animator animation) {first = false ;postInvalidate();}});}

有时不需要执行动画的话,可以再添加一个公共方法直接设置first 为false

public void SetFirstInit(Boolean ttt) {first =ttt;}

//然后在布局添加自定义view即可

在Activity中使用ClockView并根据需求调用对应的方法

到这里文章就结束了,觉得还算可以的,欢迎点赞啊

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。