对于我的活动,我使用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循环。 使用开发工具的“显示屏幕更新”,我看到没有屏幕无效/更新周期发生,除了我点击屏幕。 指定脏矩形也没有效果。
那么,任何想知道为什么这个无效/绘制周期不起作用的想法是什么意思?
答案 0 :(得分:2)
我很喜欢这种情况,并且怀疑invalidate()
没有再次调用onDraw()
。
在简化了业务代码之后,结果发现存在一个死循环 - 过多的迭代会阻塞UI线程。
所以,我的建议是确保UI线程首先顺利进行。
答案 1 :(得分:0)
在View中使用私有类尝试类似的操作。我们的想法是不要在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()
});
}
}
}