简体   繁体   中英

Android SurfaceView never becomes valid

SurfaceView is never available for drawing after creation.

Other SO questions indicate that it can be managed with the callback functions handed to it, and it must be assigned to setContentView before the lifecycle starts.

Logcat indicates that the callbacks are assigned successfully, however they are never fired.

Full code here but I think relevant parts can be found in the main activity:

package com.example.gavin.pixelarraytest;

import android.app.Activity;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        GameView theGame = new GameView(this, 0,0);

        SurfaceHolder testt;
        testt = theGame.getHolder();

        setContentView(theGame);

        while(true){

            if(testt.getSurface().isValid()){ // this never becomes true. isCreating is also consistently false at this point

                theGame.prepareCanvas();
                break;
            }
        }

    }

}

And in the SurfaceView object:

package com.example.gavin.pixelarraytest;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.util.Log;
import android.view.Display;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;

public class GameView extends SurfaceView implements Runnable {


    private Paint paint;
    private Canvas canvas;
    private Bitmap _buffer;

    private SurfaceHolder ourHolder;

    private boolean running;
    private boolean paused = false;


    private long fps;

    public GameView(Context context, int screenX, int screenY){

        ourHolder = getHolder();

        ourHolder.addCallback(new MyCallback());

        paint = new Paint();

    }

    public void prepareCanvas(){

        running = true;

        run();

    }

@Override
    public void run(){

        while(running){


            long startFrameTime = System.currentTimeMillis();

            draw();

            long endFrameTime = System.currentTimeMillis() - startFrameTime;
            if(endFrameTime  >= 1){
                fps = 1000 / endFrameTime;
            }

        }


    private void update(){

    class MyCallback implements SurfaceHolder.Callback {
        @Override
        public void surfaceChanged(SurfaceHolder holder, int format,
                                   int width, int height) {

        }

        @Override
        public void surfaceCreated(SurfaceHolder holder) {


        }

        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {


        }
    }


    private void draw(){

        this.setWillNotDraw(false);

        if(ourHolder.getSurface().isValid()){

            canvas = ourHolder.lockCanvas();

            canvas.drawColor(Color.argb(255,100,40,40));

            int width = 100;
            int height = 100;
            int colors[] = new int[width*height];
            for (int i = 0; i < colors.length; i++){

                int a = 255, r = 40, g = 100, b = 40;


                colors[i] = (a << 24) | (r << 16) | (g << 8) | b;


                _buffer = Bitmap.createBitmap(colors, width, height, Bitmap.Config.RGB_565);

               canvas.drawBitmap(_buffer, 0,0,null);

            }

        }

}

Am I misunderstanding how SurfaceView is used or am I using it incorrectly in the above?

To inflate a canvas object you can try this:

First create a layout file in res>layout

    <?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">

    <GameView
        android:id="+@id/mGameView"
        android:layout_height="match_parent"
        android:layout_width="match_parent"
        />

</LinearLayout>

Then you can inflate this by calling

setContentView(R.layout.your_file_name);

And finally access the gameview by using:

GameView gameView = findViewById(R.id.mGameView);
gameView.prepareCanvas();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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