Animation with SurfaceView

Compare with custom view drawing:

1.view drawing does not have a double buffering mechanism, while surfaceview has

2. When the view drawing is updated, the entire picture needs to be updated, and the surfaceview can update some areas

3. The new thread cannot directly update the view drawing, and requires the cooperation of the handler.

Animation of fish swimming:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <com.example.liuyan.testbutfly.FishView
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</LinearLayout>
public class FishView extends SurfaceView implements SurfaceHolder.Callback{
    private SurfaceHolder holder;
    private UpdateViewThread updatethread;
    private boolean hasSurface;
    private Bitmap back;
    private Bitmap[] fishs;
    private int fishIndex = 0;//Draw the first fish
    // initial position of the fish
    private float fishx = 778;
    private float fishy = 500;
    private float fishSpeed ​​= 6; // fish swimming speed
    //The swimming angle of the fish
    private int fishAngle = new Random().nextInt(60);
    Matrix matrix = new Matrix();

    public FishView(Context context) {
        super(context);
        Log.i("mydate" , "开始");
        //Get the surfaceholder of the surfaceview and use an instance of this class as its callback
        holder = getHolder ();
        holder.addCallback(this);//Use itself as callback, callback method
        hasSurface = false;
        back = BitmapFactory.decodeResource(context.getResources() , R.drawable.fishbg);//背景
        int[] id = new int[]{R.drawable.fish0 , R.drawable.fish1 , R.drawable.fish2 ,R.drawable.fish3 ,R.drawable.fish4 ,R.drawable.fish5 ,R.drawable.fish6 ,R.drawable.fish7 ,R.drawable.fish8, R.drawable.fish9};
        fishs = new Bitmap[10];
        //Initialize 10 pictures of fish swimming
        for (int i = 0 ; i < 10 ; i++){
            try {
                fishs[i] = BitmapFactory.decodeResource(context.getResources() , id[i]);
            } catch (Exception e){
                e.printStackTrace ();
            }
        }
        Log.i("mydate" , "结束");
    }

    public FishView(Context context, AttributeSet attrs) {
        super(context, attrs);
        Log.i("mydate" , "开始");
        //Get the surfaceholder of the surfaceview and use an instance of this class as its callback
        holder = getHolder ();
        holder.addCallback(this);//Use itself as callback, callback method
        hasSurface = false;
        back = BitmapFactory.decodeResource(context.getResources() , R.drawable.fishbg);//背景
        int[] id = new int[]{R.drawable.fish0 , R.drawable.fish1 , R.drawable.fish2 ,R.drawable.fish3 ,R.drawable.fish4 ,R.drawable.fish5 ,R.drawable.fish6 ,R.drawable.fish7 ,R.drawable.fish8, R.drawable.fish9};
        fishs = new Bitmap[10];
        //Initialize 10 pictures of fish swimming
        for (int i = 0 ; i < 10 ; i++){
            try {
// int fishId = (Integer) R.drawable.class.getField("fish" + i).get(null);//The reflection mechanism gets the picture
//                Log.i("mydate" , "  "+ fishId);
                fishs[i] = BitmapFactory.decodeResource(context.getResources() , id[i]);
            } catch (Exception e){
                e.printStackTrace ();
            }
        }
        Log.i("mydate" , "结束");
    }


    public void resume(){
        //Create and start the image update thread
        if (updatethread == null){
            updatethread = new UpdateViewThread();
            if (hasSurface == true){
                updatethread.start();
            }
        }
    }

    public void pause(){
        //stop the image update thread
        if (updatethread != null){
            updatethread.requestExitAndWait();
            updatethread = null;
        }
    }


    @Override
    public void surfaceCreated(SurfaceHolder holder) { //This method is called back when the surfaceview is created
        hasSurface = true;
        resume(); //Start thread update
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {//This method is called back when the surfaceview changes
        if (updatethread != null){
            updatethread.onWindowResize(width , height);
        }
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {//The method is called back when the surfaceview is destroyed
        hasSurface = false;
        pause(); //stop thread update
    }

    class UpdateViewThread extends Thread{
        //Define whether the image is updated or not
        private boolean done;

        public UpdateViewThread() {
            super();
            done = false;
        }

        @Override
        public void run() {
            SurfaceHolder surfaceholder = holder;
            //Loop drawing until the thread stops
            while (!done){
                Canvas canvas = surfaceholder.lockCanvas();//Lock surfaceview, ready to draw
                // draw background
                canvas.drawBitmap(back , 0 , 0 , null);
                //The fish swims out of the screen and re-initializes the fish's position
                if (fishx < 0 ){
                    fishx = 778;
                    fishy = 500;
                    fishAngle = new Random().nextInt(60);
                }
                if (fishy < 0){
                    fishx = 778;
                    fishy = 500;
                    fishAngle = new Random().nextInt(60);
                }
                //Use matrix to control the rotation angle and position of the fish
                matrix.reset();
                matrix.setRotate(fishAngle);//The following position calculation is explained as follows:
                matrix.postTranslate(fishx -= fishSpeed * Math.cos(Math.toRadians(fishAngle)) , fishy -= fishSpeed * Math.sin(Math.toRadians(fishAngle)));
                canvas.drawBitmap(fishs[fishIndex++%fishs.length] , matrix , null);
                surfaceholder.unlockCanvasAndPost(canvas);//Unlock the canvas, render the drawing image
                try {
                    Thread.sleep(60);
                } catch (Exception e){
                    e.printStackTrace ();
                }
            }
        }

        public void requestExitAndWait() {
            //Mark the drawing thread as complete and merge into the main thread
            done = true;
            try {
                join();
            } catch (Exception e){
                e.printStackTrace ();
            }
        }

        public void onWindowResize(int width, int height) {
            //Handle the size change event of surfaceview
        }
    }

}

The position calculation picture is explained as follows:

Math.toRadians(fishAngle)

First understand the meaning of this code: convert the 0-360 angle system angle to the pi radian system angle


The fish keeps swimming, and the coordinate change is actually:

current x coordinate - velocity * cos angle, current y coordinate - velocity * sin angle



Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324849800&siteId=291194637