自定义 View 上的 invalidate() 不会导致 onDraw(Canvas c) 被调用

and*_*jcr 5 android view

对于我的活动,我使用堆叠的 3 个自定义视图。下一个是 SurfaceView 全屏,中间一个派生自 GridView 并覆盖 onDraw 以添加自定义图形。

最上面的一个直接派生自 View,位于屏幕的一角,充当旋钮来控制其他两个视图(这是有问题的视图)。

要向此视图添加自定义动画,我使用了以下模式:

public class StubKnobView extends View{

    private Drawable knob;
    private Point knobPos;
    private float rotation;
    private boolean needsToMove;

    public void moveKnob(){
            /* ...various calculations... */
            this.needsToMove=true;
            invalidate();   //to notify the intention to start animation
    }

    private void updateAnimation(){
        /* ........... */
        this.needsToMove= !animationComplete;
        invalidate();        
    }

    @Override
    protected void onDraw(Canvas canvas) {
        int saveCount=canvas.getSaveCount();
        canvas.save();
        canvas.rotate(this.rotation, this.knobPos.x, this.knobPos.y );
        this.knob.draw(canvas);
        canvas.restoreToCount(saveCount);
        if(this.needsToMove){
            updateAnimation();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

理想情况下,如果有动画挂起,在每个绘制周期后视图应该自动失效。

现在这不起作用,要强制动画我必须触摸屏幕以导致 onDraw 循环。使用开发工具的“显示屏幕更新”,我看到没有屏幕失效/更新周期发生,除了当我单击屏幕时。指定脏矩形也无效。

那么,知道在哪里查看为什么这个无效/绘制周期不能按照预期的方式工作吗?

dbr*_*son 0

在您的视图中尝试使用私人课程进行类似的操作。这个想法不是invalidate()从内部调用onDraw()。相反,将其发布到运行队列中。在 View 构造函数中实例化私有类,然后animateKnob.start()在需要动画时调用。然后就可以onDraw()专注于绘画。

public void moveKnob(){

  // update the state to draw... KnobPos, rotation
  invalidate()

}


private class AnimateKnob{
   public void start(){
      // Do some calculations if necessary 
      // Start the animation
      MyView.this.post( new Runnable() {
        stepAnimation()
      });
   }

   public void stepAnimation(){
     // update the animation, maybe use an interpolator.
     // Here you could also determine if the animation is complete or not

     MyView.this.moveKnob();

     if( !animationComplete ){
       // Call it again
       MyView.this.post( new Runnable() {
          stepAnimation()
       });
     }

   } 

}
Run Code Online (Sandbox Code Playgroud)