[英]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.