简体   繁体   English

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

[英]invalidate() on custom View does not cause onDraw(Canvas c) to be called

For my activity i use 3 custom views stacked. 对于我的活动,我使用3个自定义视图进行堆叠。 the lower one is a SurfaceView fullscreen, the middle one is derived from GridView and overrides onDraw to add custom graphic. 较低的是SurfaceView全屏,中间的是从GridView派生的,并覆盖onDraw以添加自定义图形。

The top one is derived directly from View, sits in a corner of the screen and act as a knob to control the others two views (this is the problematic view). 最上面的一个直接从View派生,它位于屏幕的一角,并充当旋钮来控制其他两个视图(这是有问题的视图)。

to add a custom animation to this view, i used this pattern: 要向此视图添加自定义动画,我使用了以下模式:

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();
        }
    }
}

ideally, if there is an animation pending, after each drawing cycle the view should auto invalidate. 理想情况下,如果有动画待处理,则在每个绘制周期之后,视图应自动失效。

right now this doesn't work, to force the animation i have to touch the screen to cause a onDraw cycle. 现在这不起作用,要强制动画,我必须触摸屏幕以引起onDraw循环。 Using "show screen updates" of Dev tools I see that no screen invalidate/update cycle happen , apart when i click the screen. 使用开发工具的“显示屏幕更新”,我发现单击屏幕时没有发生屏幕无效/更新周期的情况。 specifying the dirty rect also ha no effect. 指定脏矩形也不起作用。

So, any idea where to look to know why this invalidate/draw cycle does not work the way is intended? 那么,打算去哪里知道为什么这个无效/绘制周期不起作用的任何想法都打算?

I encontered this situation, and also doubted that invalidate() doesn't make onDraw() called again. 我遇到了这种情况,并且还怀疑invalidate()是否不会再次调用onDraw()

After simplified the business codes, it's turn out that there is a dead loop - exactly too much iterations, which blocks the UI thread. 在简化了业务代码之后,事实证明存在一个死循环-太多的迭代会阻塞UI线程。

So, my advice is that make sure the UI thread going smoothly first. 因此,我的建议是确保UI线程先平稳运行。

Try something like this with a private class in your View. 在您的View中使用私有类尝试类似的操作。 The idea is not to call invalidate() from within onDraw() . 这个想法不是在onDraw()调用invalidate() onDraw() Instead, post it on the running queue. 而是将其发布到正在运行的队列中。 Instantiate the private class in your View constructor and then just call animateKnob.start() when you want the animation. 实例化View构造函数中的私有类,然后在需要动画时仅调用animateKnob.start() The onDraw() can then just focus on drawing. 然后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()
       });
     }

   } 

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM