Android Canvas绘制图形 拾音器之动画篇
标签 Android Canvas
View Animation
ValueAnimator
View动画
属性动画
前几天我写过一篇文章,叫Android Canvas 绘制图形 – 拾音器,那篇文章旨在讲解如何使用Canvas来绘制图形,并没有实现指针的偏转动画实现,那么,今天我们就来看看指针的偏转动画如何实现。
知识准备
安卓上实现动画的方式分为两种,一种是View动画,包名:android.view.animation
,另一种是属性动画,包名:android.animation
。
View动画从字面上理解就是作用对象只能是View的派生类,其他的就只能心有余而力不足了。
属性动画的作用对象就不只是针对View的派生类了,他能操作很多属性,比如改变一个控件的宽高值;一个数值平滑过渡到另一个数值等,总之,View动画能做的他能做,View动画不能做的他也能做。对,你没看错,就是这么屌!
简单介绍
View动画,包括以下几种类型:
类型 | 说明 |
---|---|
AlphaAnimation | 渐变透明度 |
RotateAnimation | 画面旋转 |
ScaleAnimation | 尺寸缩放 |
TranslateAnimation | 位置移动 |
属性动画(Property Animation),包括以下几种类型:
类型 | 说明 |
---|---|
ObjectAnimator | 动画执行类,对对象进行操作 |
ValueAnimator | 动画执行类,对数值进行操作 |
今天我们将使用到的是ValueAnimation
类,接下来对动画进行分析,看看要实现指针偏转的动画需要用到什么方法。
- 指针偏转是通过旋转角度来实现的,如果我们要使偏转产生动画,就需要动态的改变旋转的角度。
- 旋转的角度参数类型是float,在ValueAnimator类中的ofFloat()方法正好是动态改变float数值的,所以我们要用到它。
- 数值每改变一次,我们都要把变化后的数值赋给rotate()方法,使指针旋转相应角度,所以这里需要对数值变化进行监听,因此会用到addUpdateListener()方法
- 赋值给rotate()方法后,需要对视图进行重绘,因此我们需要用到视图绘制过程中的invalidate()方法
思路
这里我们用mValue
表示指向数值,用变量mAngle
表示通过计算后的偏转角度
通常的做法,我们都是在Activity或者Fragment里通过调用一个方法,将指针要指向的数值(mValue
)数的方式传递过去,这样的话,我们就有两种思路。
一:使用ofFloat()
方法动态改变指针指向的数值,即传递过来的参数mValue
二:将传递过来的参数进行计算成指针偏转的角度(mAngle
),然后使用ofFloat()
方法动态改变角度数值
这两种方法都是可取的,具体情况具体分析,由于在界面上我们要动态显示指针指向的数值,如果采用第二种的话,那么我们要计算两次,一次是将指向mValue计算为mAngle,数值动态变化后还要将mAngle计算为mValue,这样比较麻烦,所以我们采用第一种思路。
因此,要实现指针的偏转动画,代码可以这么写:
private int mMaxValue = 50; //分值区间的最大值
private int mMinValue = -50; //分值区间的最小值
/**输入值,通过输入值来计算指针的旋转角度,即{@mAngle}的值,
* 最终在界面上呈现的效果是指针指向输入值的刻度上*/
private String mValue = "- -";
/**刻度盘呈现的总弧度,本案例中总弧度为180,呈半圆形*/
private float mArc = 180f;
/**指针旋转角度值*/
private float mAngle = 0f;
...
/**
* 设置指针指向数值,并产生旋转动画
* 这里我们动态改变指向数值
* @param value 指向数值
*/
public void setValue(float value){
//{@param value}为指针将要指向的数值,即界面上看到的数值
ValueAnimator startAnimator = ValueAnimator.ofFloat(0, value);
startAnimator.addUpdateListener(
new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
//通过getAnimatedValue()取变化后的值
float md = (float) animation.getAnimatedValue();
//计算指针当前应该偏转的角度
mAngle = md * (mArc / (float) (mMaxValue - mMinValue));
//界面上显示当前指针显示的数值
mValue = String.valueOf((int)md);
//调用重绘方法
invalidate();
}
});
startAnimator.setDuration(1000);
startAnimator.start();
}
在setValue()
方法里我们动态的改变了指针指向的数值和指针偏转的角度,并把这两个数值分别存放在全局变量mValue
和mAngle
,这样一来,我们只需要在onDraw()
方法中,对指针进行旋转和但前指向数值的显示就可以了,代码如下:
/**
* 注意:
* 下方的所以坐标计算和长度计算都是依据在屏幕宽度为621px情况下的
* @param canvas
*/
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
...
System.out.println("mAngle ==>" + mAngle);
canvas.rotate(mAngle, xc, yc);
//画指针
/**
* xc * 0.101449 = 深色刻度线条的长度
* mWidth * 0.064412 = 在屏幕宽度为621下,长度为40
* 所以下面第三个参数的值可以理解为距离深色刻度线下方有40倍数的间隙
*/
canvas.drawLine(xc, yc,
xc - radius + (xc * 0.101449f + mWidth * 0.064412f),
yc + 3, paintCursor);
...
//值
pitchValuePaint.setAntiAlias(true);
pitchValuePaint.setTextSize((mWidth * 0.080515f));
pitchValuePaint.setColor(getResources().getColor(R.color.colorAccent));
canvas.drawText(mValue,
xc - pitchValuePaint.measureText(mValue) / 2,
yc + (xc * 0.481481f + mWidth * 0.209339f),
pitchValuePaint);
...
}
效果如下:
详细的代码,请移步到我的GitHub:https://github.com/zhongzilu/TunerView
我是钟子路,Thanks for watching!