简体   繁体   English

Android-为onDraw预绘制画布

[英]Android - Predraw canvas for onDraw

I used to do my drawing in an ImageView in the onDraw method. 我以前是在onDraw方法的ImageView中绘制的。 However, I've learnt that's better to draw the canvas outside of the onDraw and just update the canvas in onDraw. 但是,我了解到最好在onDraw外部绘制画布,然后在onDraw中更新画布。

I know this is clearly wrong (because it's not working) but how would I accomplish what I'm trying to do: 我知道这显然是错误的(因为它不起作用),但是我将如何完成我想做的事情:

@Override 
public void onDraw(Canvas c) {
  c = this.newCanvas;
  super.onDraw(c);
}
    public class GameLoopThread extends Thread {
private GameView view;
private boolean running = false;

public GameLoopThread(GameView view) {
      this.view = view;
}

public void setRunning(boolean run) {
      running = run;
}

@Override
public void run() {

      while (running) {
             Canvas c = null;

             try {
                    c = view.getHolder().lockCanvas();
                    synchronized (view.getHolder()) {
                        if (c != null) {
                            view.onDraw(c);
                        }

                    }
             } finally {
                    if (c != null) {
                           view.getHolder().unlockCanvasAndPost(c);
                    }
             }

             try {

                           sleep(10);
             } catch (Exception e) {}
      }
}
}

make that thread then in your activity do something like this 使该线程然后在您的活动中执行以下操作

    @Override
public void onCreate(Bundle savedInstanceState) {
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
    WindowManager.LayoutParams.FLAG_FULLSCREEN);
    super.onCreate(savedInstanceState);
    setContentView(new GameView(GameActivity.this));
}

then in a GameViewClass do something like this 然后在GameViewClass中做这样的事情

   public class GameView extends SurfaceView {

   private SurfaceHolder holder;
   private GameLoopThread gameLoopThread;


   public GameView(Context context) {
         super(context);
         gameLoopThread = new GameLoopThread(this);
         holder = getHolder();
         holder.addCallback(new SurfaceHolder.Callback() {

                @Override
                public void surfaceDestroyed(SurfaceHolder holder) {
                       boolean retry = true;
                       gameLoopThread.setRunning(false);
                       while (retry) {
                              try {
                                    gameLoopThread.join();
                                    retry = false;
                              } catch (InterruptedException e) {
                              }
                       }
                }

                @Override
                public void surfaceCreated(SurfaceHolder holder) {
                       gameLoopThread.setRunning(true);
                       gameLoopThread.start();
                }

                @Override
                public void surfaceChanged(SurfaceHolder holder, int format,
                              int width, int height) {
                }
         });

   }

   @Override
   protected void onDraw(Canvas canvas) {
         //Do Drawing
   }
}

The important things here is that the thread is manually auto calling the onDraw() method repeatedly, and that you are locking a canvas, drawing on it, and then posting it. 这里重要的是,线程是手动反复自动调用onDraw()方法,并且您要锁定画布,在其上绘图然后将其发布。 If you dont need a super fast refresh rate then you might be better off doing something like this: 如果您不需要超快的刷新率,那么最好这样做:

    @Override 
    public void onDraw(Canvas c) {
        c = this.getHolder().lockCanvas();
        if (c != null) {
           //draw on canvas
        }
        if (c != null) {
            this.getHolder().unlockCanvasAndPost(c);
        }
    }

I just dont know if that last bit there will work, never tested it. 我只是不知道最后一点是否会起作用,所以从未测试过。 also if you want to do your drawing outside the on draw method, you could run your updating (drawing on your canvas) in a thread, and every time the onDraw method is called have it check to see if the Canvas is ready for it to post. 另外,如果您想在on draw方法之外进行绘制,则可以在线程中运行更新(在画布上绘制),并且每次调用onDraw方法时都要检查它是否可以使用Canvas。发布。 for example have your thread have a boolean that once the canvas gets pulled it is set to false, so the thread will draw you a new one, but once it is done drawing set the boolean to true. 例如,让您的线程具有一个布尔值,一旦拉出画布,它将设置为false,因此线程将为您绘制一个新布尔值,但是一旦绘制完成,就将布尔值设置为true。 in the ondraw method check to see if the boolean is true and if it is pull the canvas. 在ondraw方法中检查布尔值是否为true,以及是否将其拉到画布上。

A Canvas is just a handle for drawing onto something -- you need to get at the something itself. 画布只是用于绘制对象的句柄-您需要了解对象本身。 The Canvas that you draw into outside of onDraw() needs to be backed by a Bitmap. 绘制到onDraw()外部的Canvas需要由位图支持。 Then in onDraw(), simply draw that Bitmap into the Canvas provided: 然后在onDraw()中,只需将该位图绘制到提供的Canvas中即可:

Bitmap my_bitmap = null; /* this needs to be initialized whereever it is drawn into */
@Override
public void onDraw(Canvas c) {
   if (my_bitmap != null) {
      c.drawBitmap(my_bitmap, 0.0, 0.0, null);
   }
}

onSizeChanged() would be a reasonable place to initialize the Bitmap, because then you know its size: onSizeChanged()将是初始化位图的合理位置,因为这样您便知道其大小:

@Override
public void onSizeChanged(int w, int h, int oldw, int oldh) {
   my_bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
}

And to draw on my_bitmap, just make a new Canvas with: 要绘制my_bitmap,只需使用以下内容制作一个新的Canvas:

Canvas c = new Canvas(my_bitmap);

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

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