Android自定义弧形动画

11
首先,让我解释一下我的目标。我试图制作一个动画,改变一个ArcShape的属性。ArcShape的构造函数需要两个字段:startAngle和sweepAngle。我想要动画sweepAngle,使其在屏幕上呈现为不断缩小的圆形。
你可以通过想象PacMan来想象这个动画。想象他的嘴是闭着的。这个动画就像是他越来越张开上颚,直到没有PacMan了。
现在...我有几个问题要实现这个。首先,一旦创建了一个ArcShape,就没有内置的方法可以更改它的sweepAngle。这带来了我的第一个问题:有没有办法覆盖ArcShape并实现一些setSweepAngle方法?还是我必须为每个我想显示的sweepAngle创建一个新的ArcShape?
现在到第二个问题...假设我找到了第一个问题的解决方案,我怎么能创建这个Animation呢?这是我现在的要点:
public class OpenPacman extends Animation {
  public OpenPacman(float startAngle, float sweepAngle) {
    mStartAngle = startAngle;
    mSweepAngle = sweepAngle;
  }

  @Override
  protected void applyTransformation(float interpolatedTime, Transformation t) {
    /* This represents the current sweepAngle */
    float currAngle = mStartAngle + ((mSweepAngle - mStartAngle) * interpolatedTime);

    //Now I need to update the ArcShape's sweepAngle to currAngle. But HOW?
  }
}
2个回答

16

我找到了一个解决方案。我有一个继承自View的类,我们称之为Pacman。我在Pacman类中嵌套了我的自定义Animation。这样我就可以访问Pacman类的成员变量了。

public class Pacman extends View {
  float mSweepAngle;
  ...
  //include constructors
  //override onMeasure
  ...

  /* Here we override onDraw */
  @Override
  protected void onDraw(final Canvas canvas) {
    Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
    RectF oval = new RectF(canvas.getClipBounds());
    canvas.drawArc(oval, 0, mCurrAngle, true, p);
  }

  /* Here we define our nested custom animation */
  public class OpenPacman extends Animation {
    float mStartAngle;
    float mSweepAngle;

    public OpenPacman (int startAngle, int sweepAngle, long duration) {
      mStartAngle = startAngle;
      mSweepAngle = sweepAngle;
      setDuration(duration);
      setInterpolator(new LinearInterpolator());
    }

    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
      float currAngle = mStartAngle + ((mSweepAngle - mStartAngle) * interpolatedTime);
      Pacman.this.mCurrAngle = -currAngle; //negative for counterclockwise animation.
    }
  }
}

现在,当自定义动画更新容器类 mCurrAngleonDraw 时,会自动调用,这将绘制适当的 ArcShape

4
我必须在applyTransformation方法中添加“invalidate();”,以便视图能够使用新角度重新绘制。 - marmor
1
我按照说明进行了操作,但我的自定义视图没有显示在用户界面上。你能否发布你的完整代码? - Reg Mem
3
我知道这是一篇老帖子……但我不明白这如何使弧线动起来。它只更新了当前角度,然后你可以重新绘制它,但并没有实现动画效果。那么……你具体是如何实现动画效果的呢? - New Guy
不要使用这个过时的“解决方案”。它不起作用。即使你浪费时间画一条线,它也不会动画。请参见https://medium.com/@dbottillo/animate-android-custom-view-a94473412054。 - CoolMind

1
我认为你最好扩展Drawable并覆盖draw()函数以修改每个调用的扫描角度并绘制相应的弧形。当对象更新时,通常会调用Draw,这意味着每次绘制时都必须创建一个新的ArcShape。 动画更适合在视图和其他UI组件上执行变换。
例如:
public class OpenPacman  
{

public OpenPacman(float startAngle, float sweepAngle) {  
    this.mStartAngle = startAngle;  
    this.mSweepAngle = sweepAngle;  
    this.wakaWaka = new ArcShape(this.startAngle, this.mSweepAngle);  
} 

public void draw(Canvas c){  
  //Do drawing stuff here with the canvas
}

//Your other functions for calculating angle, etc and making the ArcShape changes
//Can call these from inside draw function so that when the view that contains your
//object calls draw, it updates correctly.

public float mStartAngle;  
public float msweepAngle;  
private ArcShape wakaWaka;  
}

希望这能让你走上正确的轨道。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接