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