【问题标题】:Android SurfaceView never becomes validAndroid SurfaceView 永远不会生效
【发布时间】:2017-04-25 21:08:47
【问题描述】:

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 的使用方式还是我在上面的使用中不正确?

【问题讨论】:

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


    【解决方案1】:

    要给画布对象充气,你可以试试这个:

    首先在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>
    

    然后你可以通过调用来膨胀它

    setContentView(R.layout.your_file_name);
    

    最后通过以下方式访问游戏视图:

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

    【讨论】:

    • findViewById 似乎期望与给出的类型不同。具体要求:com.example.gavin.pixelarraytest.GameView 却发现:android.view.View 好像xml布局和GameView类无法连接?
    • findViewById 将返回一个视图对象。所以你需要把它转换成你想要的。例如 GameView gameView = (GameView) findViewById(R.id.mGameView);
    • 这会引发错误 'android.view.InflateException: Binary XML file line #6: Error inflating class mGameView' with a large stack trace: pastebin.com/CtHuDDVa 现在由于某种原因,在运行 Android 时模拟器,脚本无法访问资源文件夹,因为它“无法解析符号'R'”,但这似乎只在emu运行时发生。现在不清楚是不是和上面有关……
    猜你喜欢
    • 1970-01-01
    • 2012-06-02
    • 2013-05-08
    • 1970-01-01
    • 2015-04-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-08
    相关资源
    最近更新 更多