Friday, March 14, 2014

Create animation on SurfaceView in background Thread

Last post "Simple SurfaceView example" draw bitmap in surfaceCreated() callback. In this step, a customized Thread, MyThread, is implemented to draw the bitmap running across screen in background thread.


MyThread.java
package com.example.androidsurfaceview;

import android.graphics.Canvas;

public class MyThread extends Thread {
 
 MySurfaceView myView;
 private boolean running = false;

 public MyThread(MySurfaceView view) {
  myView = view;
 }
 
 public void setRunning(boolean run) {
        running = run;    
 }

 @Override
 public void run() {
  while(running){
   
   Canvas canvas = myView.getHolder().lockCanvas();
   
   if(canvas != null){
    synchronized (myView.getHolder()) {
     myView.drawSomething(canvas);
    }
    myView.getHolder().unlockCanvasAndPost(canvas);
   }
   
   try {
    sleep(30);
   } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
   
  }
 }

}

Modify MySurfaceView.java in last post.
package com.example.androidsurfaceview;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class MySurfaceView extends SurfaceView {
 
    private SurfaceHolder surfaceHolder;
    private Bitmap bmpIcon;
    private MyThread myThread;
    int xPos = 0;
    int yPos = 0;
    int deltaX = 5;
    int deltaY = 5;
    int iconWidth;
    int iconHeight;

 public MySurfaceView(Context context) {
  super(context);
  init();
 }

 public MySurfaceView(Context context, 
   AttributeSet attrs) {
  super(context, attrs);
  init();
 }

 public MySurfaceView(Context context, 
   AttributeSet attrs, int defStyle) {
  super(context, attrs, defStyle);
  init();
 }
 
 private void init(){
  
  myThread = new MyThread(this);
  
  surfaceHolder = getHolder();
  bmpIcon = BitmapFactory.decodeResource(getResources(), 
    R.drawable.ic_launcher);

  iconWidth = bmpIcon.getWidth();
  iconHeight = bmpIcon.getHeight();
  
  surfaceHolder.addCallback(new SurfaceHolder.Callback(){

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

   @Override
   public void surfaceChanged(SurfaceHolder holder, 
     int format, int width, int height) {
    // TODO Auto-generated method stub
    
   }

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

 protected void drawSomething(Canvas canvas) {
  canvas.drawColor(Color.BLACK);
        canvas.drawBitmap(bmpIcon, 
          getWidth()/2, getHeight()/2, null);
        
        xPos += deltaX;
        if(deltaX > 0){
         if(xPos >= getWidth() - iconWidth){
             deltaX *= -1;
            }
        }else{
         if(xPos <= 0){
             deltaX *= -1;
            }
        }
        
        yPos += deltaY;
        if(deltaY > 0){
         if(yPos >= getHeight() - iconHeight){
             deltaY *= -1;
            }
        }else{
         if(yPos <= 0){
             deltaY *= -1;
            }
        }

        canvas.drawColor(Color.BLACK);
        canvas.drawBitmap(bmpIcon, 
          xPos, yPos, null);

 }

}

Other files, /res/layout/activity_main.xml and MainActivity.java, refer to last post.

download filesDownload the files.

Next:
Draw bitmap programmatically for SurfaceView

3 comments:

Anonymous said...

What's the point of calling drawBitmap at the very beginning of drawSomething and then again at the end. I understand the second call, but not the first. by the way - thanks for very good example!

Erik said...

Honestly speaking, I forgot the details.

Maybe to erase the old icon drawn in previous drawing.

Unknown said...

How can i add one more icon with tread to the bitmap ?