Android SurfaceView永远不会生效

时间:2016-12-10 14:12:07

标签: android android-activity android-canvas surfaceview surfaceholder

SurfaceView在创建后永远不可用于绘图。

其他SO问题表明它可以通过传递给它的回调函数进行管理,并且必须在生命周期开始之前将其分配给setContentView。

Logcat表示回调已成功分配,但永远不会被触发。

完整代码here但我认为相关部分可以在主要活动中找到:

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

    }

}

在SurfaceView对象中:

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

            }

        }

}

我是否误解了SurfaceView的使用方式,或者我在上面错误地使用了它?

1 个答案:

答案 0 :(得分:1)

要为画布对象充气,您可以试试这个:

首先在res&gt; 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>

然后你可以通过调用

来膨胀它
setContentView(R.layout.your_file_name);

最后使用以下方式访问游戏视图:

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