Android 自定View实现仿QQ运动步数圆弧及动画效果

Android 自定View实现仿QQ运动步数圆弧及动画效果,第1张

概述在之前的Android超精准计步器开发-Dylan计步中的首页用到了一个自定义控件,和QQ运动的界面有点类似,还有动画效果,下面就来讲一下这个View是如何绘制的。

在之前的Android超精准计步器开发-Dylan计步中的首页用到了一个自定义控件,和QQ运动的界面有点类似,还有动画效果,下面就来讲一下这个VIEw是如何绘制的。

1.先看效果图

2.效果图分析

功能说明:黄色的代表用户设置的总计划锻炼步数,红色的代表用户当前所走的步数。

初步分析:完全自定义view重写onDraw()方法,画圆弧

3.画一个圆弧必备知识

在Canvas中有一个画圆弧的方法

drawArc(RectF oval,float startAngle,float sweepAngle,boolean useCenter,Paint paint)//画弧,

参数一是RectF对象,一个矩形区域椭圆形的界限用于定义在形状、大小、电弧,

参数二是起始角(度)在电弧的开始,圆弧起始角度,单位为度。

参数三圆弧扫过的角度,顺时针方向,单位为度,从右中间开始为零度。

参数四是如果是true(真)的话,在绘制圆弧时将圆心包括在内,通常用来绘制扇形;如果是false(假)这将是一个弧线。

参数五是Paint对象;

对于这个方法,大家可以看一下我手绘的草图,比较烂,表达一下这几个参数的意思和绘制过程,画得不好望大家见谅!

4.绘图的准备工作

(1).获取中心点坐标

/**中心点的x坐标*/float centerX = (getWIDth()) / 2;

(2).建立一个圆弧外的参考矩形

/**指定圆弧的外轮廓矩形区域*/RectF rectF = new RectF(0 + borderWIDth,borderWIDth,2 * centerX - borderWIDth,2 * centerX - borderWIDth);

5.绘图的主要步骤

(1).【第一步】绘制整体的黄色圆弧

/*** 1.绘制总步数的黄色圆弧** @param canvas 画笔* @param rectF 参考的矩形*/private voID drawArcYellow(Canvas canvas,RectF rectF) {Paint paint = new Paint();/** 默认画笔颜色,黄色 */paint.setcolor(getResources().getcolor(R.color.yellow));/** 结合处为圆弧*/paint.setstrokeJoin(Paint.Join.ROUND);/** 设置画笔的样式 Paint.Cap.Round,Cap.SQUARE等分别为圆形、方形*/paint.setstrokeCap(Paint.Cap.ROUND);/** 设置画笔的填充样式 Paint.Style.FILL :填充内部;Paint.Style.FILL_AND_stroke :填充内部和描边; Paint.Style.stroke :仅描边*/paint.setStyle(Paint.Style.stroke);/**抗锯齿功能*/paint.setAntiAlias(true);/**设置画笔宽度*/paint.setstrokeWIDth(borderWIDth);/**绘制圆弧的方法* drawArc(RectF oval,Paint paint)//画弧,参数一是RectF对象,一个矩形区域椭圆形的界限用于定义在形状、大小、电弧,参数二是起始角(度)在电弧的开始,圆弧起始角度,单位为度。参数三圆弧扫过的角度,顺时针方向,单位为度,从右中间开始为零度。参数四是如果这是true(真)的话,在绘制圆弧时将圆心包括在内,通常用来绘制扇形;如果它是false(假)这将是一个弧线,参数五是Paint对象;*/canvas.drawArc(rectF,startAngle,angleLength,false,paint);}

(2).【第二步】绘制当前进度的红色圆弧

/*** 2.绘制当前步数的红色圆弧*/private voID drawArcRed(Canvas canvas,RectF rectF) {Paint paintCurrent = new Paint();paintCurrent.setstrokeJoin(Paint.Join.ROUND);paintCurrent.setstrokeCap(Paint.Cap.ROUND);//圆角弧度paintCurrent.setStyle(Paint.Style.stroke);//设置填充样式paintCurrent.setAntiAlias(true);//抗锯齿功能paintCurrent.setstrokeWIDth(borderWIDth);//设置画笔宽度paintCurrent.setcolor(getResources().getcolor(R.color.red));//设置画笔颜色canvas.drawArc(rectF,currentAngleLength,paintCurrent);}

(3).【第三步】绘制当前进度的红色数字

/*** 3.圆环中心的步数*/private voID drawTextNumber(Canvas canvas,float centerX) {Paint vTextPaint = new Paint();vTextPaint.setTextAlign(Paint.Align.CENTER);vTextPaint.setAntiAlias(true);//抗锯齿功能vTextPaint.setTextSize(numberTextSize);Typeface Font = Typeface.create(Typeface.SANS_serif,Typeface.norMAL);vTextPaint.setTypeface(Font);//字体风格vTextPaint.setcolor(getResources().getcolor(R.color.red));Rect bounds_Number = new Rect();vTextPaint.getTextBounds(stepNumber,stepNumber.length(),bounds_Number);canvas.drawText(stepNumber,centerX,getHeight() / 2 + bounds_Number.height() / 2,vTextPaint);}

(4).【第四步】绘制”步数”的红色数字

/*** 4.圆环中心[步数]的文字*/private voID drawTextStepString(Canvas canvas,float centerX) {Paint vTextPaint = new Paint();vTextPaint.setTextSize(diptopx(16));vTextPaint.setTextAlign(Paint.Align.CENTER);vTextPaint.setAntiAlias(true);//抗锯齿功能vTextPaint.setcolor(getResources().getcolor(R.color.grey));String stepString = "步数";Rect bounds = new Rect();vTextPaint.getTextBounds(stepString,stepString.length(),bounds);canvas.drawText(stepString,getHeight() / 2 + bounds.height() + getFontHeight(numberTextSize),vTextPaint);}

6.动画是如何实现的->ValueAnimator

ValueAnimator是整个属性动画机制当中最核心的一个类,属性动画的运行机制是通过不断地对值进行 *** 作来实现的,而初始值和结束值之间的动画过渡就是由ValueAnimator这个类来负责计算的。它的内部使用一种时间循环的机制来计算值与值之间的动画过渡, 我们只需要将初始值和结束值提供给ValueAnimator,并且告诉它动画所需运行的时长,那么ValueAnimator就会自动帮我们完成从初始值平滑地过渡到结束值这样的效果。

/*为进度设置动画* @param start 初始值* @param current 结束值* @param length 动画时长*/private voID setAnimation(float start,float current,int length) {ValueAnimator progressAnimator = ValueAnimator.offloat(start,current);progressAnimator.setDuration(length);progressAnimator.setTarget(currentAngleLength);progressAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@OverrIDepublic voID onAnimationUpdate(ValueAnimator animation) {/**每次在初始值和结束值之间产生的一个平滑过渡的值,逐步去更新进度*/currentAngleLength = (float) animation.getAnimatedValue();invalIDate();}});progressAnimator.start();}

7.整个自定义StepArcVIEw的源码

import androID.animation.ValueAnimator;import androID.content.Context;import androID.graphics.Canvas;import androID.graphics.Paint;import androID.graphics.Rect;import androID.graphics.RectF;import androID.graphics.Typeface;import androID.util.AttributeSet;import androID.vIEw.VIEw;import cn.bluemobi.dylan.step.R;/*** Created by DylanAndroID on 2016/5/26.* 显示步数的圆弧*/public class StepArcVIEw extends VIEw {/*** 圆弧的宽度*/private float borderWIDth = 38f;/*** 画步数的数值的字体大小*/private float numberTextSize = 0;/*** 步数*/private String stepNumber = "0";/*** 开始绘制圆弧的角度*/private float startAngle = 135;/*** 终点对应的角度和起始点对应的角度的夹角*/private float angleLength = 270;/*** 所要绘制的当前步数的红色圆弧终点到起点的夹角*/private float currentAngleLength = 0;/*** 动画时长*/private int animationLength = 3000;public StepArcVIEw(Context context) {super(context);}public StepArcVIEw(Context context,AttributeSet attrs) {super(context,attrs);}public StepArcVIEw(Context context,AttributeSet attrs,int defStyleAttr) {super(context,attrs,defStyleAttr);}@OverrIDeprotected voID onDraw(Canvas canvas) {super.onDraw(canvas);/**中心点的x坐标*/float centerX = (getWIDth()) / 2;/**指定圆弧的外轮廓矩形区域*/RectF rectF = new RectF(0 + borderWIDth,2 * centerX - borderWIDth);/**【第一步】绘制整体的黄色圆弧*/drawArcYellow(canvas,rectF);/**【第二步】绘制当前进度的红色圆弧*/drawArcRed(canvas,rectF);/**【第三步】绘制当前进度的红色数字*/drawTextNumber(canvas,centerX);/**【第四步】绘制"步数"的红色数字*/drawTextStepString(canvas,centerX);}/*** 1.绘制总步数的黄色圆弧** @param canvas 画笔* @param rectF 参考的矩形*/private voID drawArcYellow(Canvas canvas,paint);}/*** 2.绘制当前步数的红色圆弧*/private voID drawArcRed(Canvas canvas,paintCurrent);}/*** 3.圆环中心的步数*/private voID drawTextNumber(Canvas canvas,vTextPaint);}/*** 4.圆环中心[步数]的文字*/private voID drawTextStepString(Canvas canvas,vTextPaint);}/*** 获取当前步数的数字的高度** @param FontSize 字体大小* @return 字体高度*/public int getFontHeight(float FontSize) {Paint paint = new Paint();paint.setTextSize(FontSize);Rect bounds_Number = new Rect();paint.getTextBounds(stepNumber,bounds_Number);return bounds_Number.height();}/*** dip 转换成px** @param dip* @return*/private int diptopx(float dip) {float density = getContext().getResources().getdisplayMetrics().density;return (int) (dip * density + 0.5f * (dip >= 0 ? 1 : -1));}/*** 所走的步数进度** @param totalStepNum 设置的步数* @param currentCounts 所走步数*/public voID setCurrentCount(int totalStepNum,int currentCounts) {stepNumber = currentCounts + "";setTextSize(currentCounts);/**如果当前走的步数超过总步数则圆弧还是270度,不能成为园*/if (currentCounts > totalStepNum) {currentCounts = totalStepNum;}/**所走步数占用总共步数的百分比*/float scale = (float) currentCounts / totalStepNum;/**换算成弧度最后要到达的角度的长度-->弧长*/float currentAngleLength = scale * angleLength;/**开始执行动画*/setAnimation(0,animationLength);}/*** 为进度设置动画* ValueAnimator是整个属性动画机制当中最核心的一个类,属性动画的运行机制是通过不断地对值进行 *** 作来实现的,* 而初始值和结束值之间的动画过渡就是由ValueAnimator这个类来负责计算的。* 它的内部使用一种时间循环的机制来计算值与值之间的动画过渡,* 我们只需要将初始值和结束值提供给ValueAnimator,并且告诉它动画所需运行的时长,* 那么ValueAnimator就会自动帮我们完成从初始值平滑地过渡到结束值这样的效果。** @param last* @param current*/private voID setAnimation(float last,int length) {ValueAnimator progressAnimator = ValueAnimator.offloat(last,current);progressAnimator.setDuration(length);progressAnimator.setTarget(currentAngleLength);progressAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@OverrIDepublic voID onAnimationUpdate(ValueAnimator animation) {currentAngleLength = (float) animation.getAnimatedValue();invalIDate();}});progressAnimator.start();}/*** 设置文本大小,防止步数特别大之后放不下,将字体大小动态设置** @param num*/public voID setTextSize(int num) {String s = String.valueOf(num);int length = s.length();if (length <= 4) {numberTextSize = diptopx(50);} else if (length > 4 && length <= 6) {numberTextSize = diptopx(40);} else if (length > 6 && length <= 8) {numberTextSize = diptopx(30);} else if (length > 8) {numberTextSize = diptopx(25);}}}

8.用法说明

xml中

<cn.bluemobi.dylan.step.vIEw.StepArcVIEwandroID:ID="@+ID/sv "androID:layout_wIDth="200dp"androID:layout_height="200dp"androID:layout_centerHorizontal="true"androID:layout_margintop="50dp" />

Activity中

StepArcVIEw sv = (StepArcVIEw) findVIEwByID(R.ID.sv);sv.setCurrentCount(7000,1000);

以上所述是小编给大家介绍的AndroID 仿QQ运动步数圆弧及动画效果,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对编程小技巧网站的支持!

总结

以上是内存溢出为你收集整理的Android 自定View实现仿QQ运动步数圆弧及动画效果全部内容,希望文章能够帮你解决Android 自定View实现仿QQ运动步数圆弧及动画效果所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/web/1147897.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-31
下一篇 2022-05-31

发表评论

登录后才能评论

评论列表(0条)

保存