【问题标题】:invalidate() on custom View does not cause onDraw(Canvas c) to be called自定义视图上的 invalidate() 不会导致调用 onDraw(Canvas c)
【发布时间】:2011-10-26 16:42:43
【问题描述】:

对于我的活动,我使用堆叠的 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();
        }
    }
}

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

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

那么,有什么想法可以去哪里了解为什么这个无效/绘制循环不能按预期的方式工作?

【问题讨论】:

    标签: android view


    【解决方案1】:

    我遇到了这种情况,也怀疑invalidate()不会让onDraw()再次调用。

    简化业务代码后,发现有一个死循环——迭代太多,阻塞了UI线程。

    所以,我的建议是先确保 UI 线程顺利进行。

    【讨论】:

      【解决方案2】:

      在您的视图中尝试这样的私有类。我们的想法是不要从onDraw() 内部调用invalidate()。相反,将其发布到正在运行的队列中。在 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()
             });
           }
      
         } 
      
      }
      

      【讨论】:

      • 最后我使用的解决方案和这个类似
      猜你喜欢
      • 2016-09-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多