【问题标题】:SurfaceView, onDraw and postInvalidate() something wrongSurfaceView、onDraw 和 postInvalidate() 出了点问题
【发布时间】:2012-03-24 21:48:21
【问题描述】:

应用程序的行为很奇怪。我有一个类扩展了 SurfaceView 并实现了 SurfaceHolder.Callback 。
我尝试了 3 种代码选项,只有一个可以像我需要的那样工作(但我怀疑它是否是正确的解决方案),而其他的则有不同的行为。
所以,我的问题是为什么和什么是错的,以及是否“正确”解决方案是错误的,为什么它会起作用...

适合所有人:

  1. 我试过setWillNotDraw(boolean flag)flag(true/false)
  2. 在清单集中android:changeConfiguration="orientation"
  3. 在主布局设置背景中,平铺图片通过 xml 资源定义。

现在“正确”的实现: 我有调用 postInvalidate(); 的线程,在 lockCanvas 和 unlockCanvas 之间有延迟和调用:
我的 onDraw() 和 draw(Canvas c,int deg) 在所有变体中都相同:

@Override
public void onDraw(Canvas c) {
    draw(c,lastHeading);
    super.onDraw(c);
}

public synchronized void draw(Canvas c,int degrees) {
    Paint p=new Paint();
    p.setAntiAlias(true);
    c.save();

    rotateLayer(degrees,layer1, cLayers.getDrawable(0),false);
    rotateLayer(lastSideAngle, layer2, sLayers.getDrawable(1),true);
    rotateLayer(lastFrontAngle, layer2, fLayers.getDrawable(1),true);

    c.drawBitmap(layer1,0, 0, p);
    c.drawBitmap(layer2,0, 0, p);
    c.drawBitmap(layer3, 0,0, p);   
    c.restore();
}

问题代码变体 A(和“正确”):

@Override
public void run() {
    Canvas c=null;
    try
    {
        c=holder.lockCanvas(null);
        synchronized (holder) {
        postInvalidate();
    }
    finally
    {
        if(c!=null)
        holder.unlockCanvasAndPost(c);
    }
}

为什么它没有问题但没有画布锁定/解锁的相同代码不能正确工作?

随着下一个实现应用程序运行良好,直到手机不改变方向。虽然改变方向需要时间来重绘表面,但在下一个方向改变时它会快速变化。但在这两种变体中,我都调用了 postInvalidate(),但我不明白锁定/解锁 Canvas 对 postInvalidate() 有何影响?

@Override
public void run() {
    postInvalidate();
}

在这个变体中,我在屏幕上看到了一个永远不会改变的冻结图像:

@Override
public void run() {
    Canvas c=null;
    try
    {
        c=holder.lockCanvas(null);
        synchronized (holder) {
        draw(c,deg);
        //OR
        //onDraw(c)
    }
    finally
    {
        if(c!=null)
        holder.unlockCanvasAndPost(c);
    }
}

当应用程序绘制所有位图但背景被全部覆盖时,还有另一种变体。 那么我做错了什么,我需要做什么?

【问题讨论】:

    标签: java android surfaceview ondraw


    【解决方案1】:

    这里:

    @Override
    public void run() {
    Canvas c=null;
       try
       {
           c=holder.lockCanvas(null);
           synchronized (holder) {
           draw(c,deg);
           //OR
           //onDraw(c)
       }
       finally
       {
           if(c!=null)
           holder.unlockCanvasAndPost(c);
       } 
    }
    

    您需要设置一个循环,否则您只会调用一次 onDraw() 方法。 这将创建一个连续的重绘:

    while(true) {
       try
       {
           c=holder.lockCanvas(null);
           synchronized (holder) {
           draw(c,deg);
           //OR
           //onDraw(c)
       }
       finally
       {
           if(c!=null)
           holder.unlockCanvasAndPost(c);
       } 
    }
    

    Source

    【讨论】:

      猜你喜欢
      • 2011-09-19
      • 2011-09-09
      • 2011-08-04
      • 2013-03-11
      • 1970-01-01
      • 2014-03-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多