[英]Rotation animation with custom view
我有一个自定义的View,IndicatorView,它本质上是一个三角形,它根据半径等于三角形长度的圆的指定角度对自身进行定向。 三角形指向的角度经常更新,我想在这两个位置之间设置动画,类似于时钟上的指针如何移动。 以下是我的自定义视图的图示(未按比例绘制或按比例绘制;根据Android View坐标平面绘制):
在IndicatorView类中,我使用Path对象和三个PointF对象绘制三角形:
@Override
protected void onDraw(Canvas canvas){
path = new Path();
path.setFillType(Path.FillType.EVEN_ODD);
//a, b, and c are PointF objects
path.moveTo(a.x, a.y);
path.lineTo(b.x, b.y);
path.lineTo(c.x, c.y);
path.close();
canvas.drawPath(path, paint);
}
为了计算给定角度的不同点,我使用参数方程式:
public void showAngle(){
//x = centerX + radius * cos(angle)
//y = centerY + radius * sin(angle)
//TODO sloppy; tidy up / optimize once finished
//centerX, centerY, length, and bottomWidth are all values
//calculated in onSizeChanged
a = new PointF((float) (centerX + (length * Math.cos(angle))), (float) (centerY + (length * Math.sin(angle))));
//perpendicular bilateral radius
double pRadius = bottomWidth / 2;
//perpendicular angle plus or minus 90 degrees depending on point
float pAngle = angle - 90;
pAngle = (pAngle < 0) ? 360 - Math.abs(pAngle) : pAngle;
pAngle = (pAngle > 360) ? pAngle % 360 : pAngle;
b = new PointF((float) (centerX + (pRadius * Math.cos(pAngle))), (float) (centerY + (pRadius * Math.sin(pAngle))));
pAngle = angle + 90;
pAngle = (pAngle < 0) ? 360 - Math.abs(pAngle) : pAngle;
pAngle = (pAngle > 360) ? pAngle % 360 : pAngle;
c = new PointF((float) (centerX + (pRadius * Math.cos(pAngle))), (float) (centerY + pRadius * Math.sin(pAngle)));
invalidate();
}
当我有一个新角度时,我使用ObjectAnimator在两个角度之间设置动画。 我将AnimatorUpdateListener放在ObjectAnimator上,并使用从Animator指定的中间值在我的IndicatorView中调用showAngle()方法:
public void updateAngle(float newAngle){
//don't animate to an angle if the previous angle is the same
if(view.getAngle() != newAngle){
if(anim != null && anim.isRunning()){
anim.cancel();
}
anim = ObjectAnimator.ofFloat(view, "angle", view.getAngle(), newAngle);
anim.setDuration(duration);
anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
if(view != null){
view.showAngle();
}
}
});
}
}
但是,此代码会产生一些奇怪的意外行为:
显然,尽管如此,我的计算肯定是不正确的,但我一直在努力找出哪里出了问题。 问题:是否有更有效的方法来使我的自定义视图对旋转到给定角度进行动画处理? 如果我正确地解决了这个问题,那我哪里出错了?
因此,解决我的问题的方法相当简单,但又足够容易被忽略。 计算中使用的角度场以度为单位,只需将其转换为弧度即可使用sin和cos方法。
更改所有PointF
实例,例如:
a = new PointF((float) (centerX + (length * Math.cos(angle))), (float) (centerY + (length * Math.sin(angle))));
使用弧度角:
a = new PointF((float) (centerX + (length * Math.cos(Math.toRadians(angle))),
(float) (centerY + (length * Math.sin(Math.toRadians(angle)))));
另外,部分问题是由于不断分析声音并在上一个动画有时间渲染几帧之前更新了视图。 这导致在频繁更新角度时,IndicatorView几乎不动,而在不更新角度时,它会迅速移至其目的地。 发生这种情况是因为在设置另一个动画之前,先前的动画被取消了(这是防止延迟的必要步骤)。 这是一个棘手的问题,但是我发现一个优化是避免在当前角度和前一个角度相对接近的情况下避免启动新动画。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.