【问题标题】:Android - Predraw canvas for onDrawAndroid - 用于 onDraw 的预绘制画布
【发布时间】:2012-08-11 20:50:25
【问题描述】:

我曾经在 onDraw 方法中的 ImageView 中进行绘图。 但是,我了解到最好在 onDraw 之外绘制画布并在 onDraw 中更新画布。

我知道这显然是错误的(因为它不起作用)但是我将如何完成我正在尝试做的事情:

@Override 
public void onDraw(Canvas c) {
  c = this.newCanvas;
  super.onDraw(c);
}

【问题讨论】:

    标签: android android-canvas android-ui


    【解决方案1】:
        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) {}
          }
    }
    }
    

    让那个线程然后在你的活动中做这样的事情

        @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));
    }
    

    然后在 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
       }
    }
    

    这里重要的是线程手动自动重复调用 onDraw() 方法,并且您正在锁定画布,在其上绘图,然后发布它。如果您不需要超快的刷新率,那么您最好执行以下操作:

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

    我只是不知道最后一点是否有效,从未测试过。 此外,如果您想在 on draw 方法之外进行绘图,您可以在线程中运行更新(在画布上绘图),并且每次调用 onDraw 方法时检查 Canvas 是否已准备好邮政。例如,让您的线程有一个布尔值,一旦画布被拉动,它就会设置为 false,因此线程会为您绘制一个新的,但一旦完成绘制,将布尔值设置为 true。在 ondraw 方法中检查布尔值是否为真,是否拉画布。

    【讨论】:

      【解决方案2】:

      Canvas 只是用于在某物上绘图的句柄——您需要获取某物本身。您在 onDraw() 之外绘制的画布需要由位图支持。然后在 onDraw() 中,简单地将 Bitmap 绘制到提供的 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() 将是初始化位图的合理位置,因为您知道它的大小:

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

      要在 my_bitmap 上绘图,只需使用以下命令制作一个新的 Canvas:

      Canvas c = new Canvas(my_bitmap);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-11-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多