使用GLSurfaceView

时间:2017-02-20 19:12:39

标签: android android-fragments glsurfaceview

我有一些当前在Activities上运行的代码,我正在使用一个主Activity和几个Frag来转换它。我的一个活动在onCreate()方法中运行GLSurfaceView。所以我将其修改为onCreateView。但问题是每当新的Fragment尝试启动时应用程序崩溃并且我收到以下错误:

E/GLSurfaceView: eglCreateWindowSurface
                 java.lang.IllegalArgumentException: Make sure the SurfaceView or associated SurfaceHolder has a valid Surface
                     at com.google.android.gles_jni.EGLImpl._eglCreateWindowSurface(Native Method)
                     at com.google.android.gles_jni.EGLImpl.eglCreateWindowSurface(EGLImpl.java:90)
                     at android.opengl.GLSurfaceView$DefaultWindowSurfaceFactory.createWindowSurface(GLSurfaceView.java:808)
                     at android.opengl.GLSurfaceView$EglHelper.createSurface(GLSurfaceView.java:1077)
                     at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1471)
                     at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1240)

任何人都可以暗示我在转换为片段时遇到了什么问题吗?

这是我在主Activity中启动第一个Fragment的地方:

                //Start the fragment
                Fragment gameManager = new GameManager();
                fragmentManager.beginTransaction()
                        .add(R.id.fragment_container,gameManager)
                        .addToBackStack(null)
                        .commit();

以下是GameManager的相关代码,它是一个片段: (1)空构造函数:

public GameManager(){
}

(2)onCreateView()代码:

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        fa = (FragmentActivity) super.getActivity();

        CatAndroidApp app = (CatAndroidApp) getActivity().getApplicationContext();

        RelativeLayout frame = new RelativeLayout(getActivity());

        TextureManager texture = app.getTextureManagerInstance();

        if (texture == null) {
            texture = new TextureManager(getResources());
            app.setTextureManagerInstance(texture);
        }

        //changed constructor
        view = new GameView(this,getActivity());
        renderer = new GameRenderer(view);
        view.setRenderer(renderer);
        view.requestFocus();
        view.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT,
                LinearLayout.LayoutParams.MATCH_PARENT, 1));
        frame.addView(view);

        boolean horizontal = getActivity().getResources().getDisplayMetrics().widthPixels < getActivity().getResources().getDisplayMetrics().heightPixels;
        resources = new ResourceView(getActivity());
        resources.setOrientation(horizontal ? LinearLayout.HORIZONTAL : LinearLayout.VERTICAL);
        RelativeLayout.LayoutParams params;
        if (horizontal)
            params = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
        else
            params = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
        params.addRule(horizontal ? RelativeLayout.ALIGN_PARENT_BOTTOM : RelativeLayout.ALIGN_PARENT_RIGHT, RelativeLayout.TRUE);
        frame.addView(resources, params);

        board = app.getBoardInstance();

        turnHandler = new UpdateHandler();

        return view;
    }

最后,这是GameView的代码:

package com.catandroid.app.common.ui.views;

import javax.microedition.khronos.opengles.GL10;

import com.catandroid.app.common.components.BoardGeometry;
import com.catandroid.app.CatAndroidApp;
import com.catandroid.app.common.controllers.GameManager;
import com.catandroid.app.common.controllers.GameRenderer;
import com.catandroid.app.common.ui.TextureManager;
import com.catandroid.app.common.ui.resources.UIButton;
import com.catandroid.app.common.ui.resources.UIButton.Type;
import com.catandroid.app.common.players.Player;

import android.content.Context;
import android.graphics.Canvas;
import android.opengl.GLSurfaceView;
import android.os.Vibrator;
import android.view.MotionEvent;
import android.view.GestureDetector;
import android.view.ScaleGestureDetector;
import android.view.ScaleGestureDetector.OnScaleGestureListener;
import android.view.View;
import android.view.GestureDetector.OnDoubleTapListener;
import android.view.GestureDetector.OnGestureListener;

public class GameView extends GLSurfaceView implements OnGestureListener,
        OnDoubleTapListener, OnScaleGestureListener {

    private int width, height;
    private GameRenderer renderer;
    private GestureDetector gesture;
    private ScaleGestureDetector pinch;

    private UIButton[] buttons;
    private boolean buttonsPlaced = false;
    private GameManager game;

    public GameView(GameManager manager, Context context) {
        super(context);

        game = manager;

        gesture = new GestureDetector(context, this);
        pinch = new ScaleGestureDetector(context, this);

        setSystemUiVisibility(getSystemUiVisibility() | View.SYSTEM_UI_FLAG_LOW_PROFILE);

        buttons = new UIButton[UIButton.Type.values().length];
        int size = (int) (0.5 * BoardGeometry.BUTTON_SIZE * getResources().getDisplayMetrics().density);
        for (UIButton.Type type : UIButton.Type.values())
            buttons[type.ordinal()] = new UIButton(type, size, size);

        buttonsPlaced = false;
    }

    @Override
    public void setRenderer(Renderer renderer) {
        super.setRenderer(renderer);
        this.renderer = (GameRenderer) renderer;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        width = MeasureSpec.getSize(widthMeasureSpec);
        height = MeasureSpec.getSize(heightMeasureSpec);
        setMeasuredDimension(width, height);
        renderer.setSize(getContext().getResources().getDisplayMetrics(), width, height);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        // handle touch events in GestureDetector
        return gesture.onTouchEvent(event) || pinch.onTouchEvent(event);
    }

    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distX, float distY) {
        // ignore scrolling started over a button
        for (UIButton button : buttons)
            if (button.isPressed())
                return false;

        // shift the board
        renderer.getGeometry().translate(distX, distY);

        return true;
    }

    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float vx, float vy) {
        // throw out button press if scrolling over a button
        release((int) e2.getX(), (int) e2.getY(), false);

        // ignore flings
        return false;
    }

    @Override
    public boolean onDown(MotionEvent event) {
        setSystemUiVisibility(getSystemUiVisibility() | View.SYSTEM_UI_FLAG_LOW_PROFILE);

        // press down (consider activating buttons)
        press((int) event.getX(), (int) event.getY());

        // always return true to allow gestures to register
        return true;
    }

    @Override
    public void onShowPress(MotionEvent event) {
        // this is handled already in onDown
    }

    @Override
    public boolean onSingleTapUp(MotionEvent event) {
        // handle in onSingleTapConfirmed
        return false;
    }

    @Override
    public boolean onSingleTapConfirmed(MotionEvent event) {
        // button click
        return release((int) event.getX(), (int) event.getY(), true);
    }

    @Override
    public void onLongPress(MotionEvent event) {
        // TODO: long press resource to trade for it

        Vibrator vibrator = (Vibrator) getContext().getSystemService(
                Context.VIBRATOR_SERVICE);

        // consider buttons then a click on the board
        if (release((int) event.getX(), (int) event.getY(), true) ||
                click((int) event.getX(), (int) event.getY())) {

            vibrator.vibrate(50);
        } else {
            vibrator.vibrate(20);
        }
    }

    @Override
    public boolean onDoubleTapEvent(MotionEvent event) {
        // ignore intermediate events triggered in a double tap
        return false;
    }

    @Override
    public boolean onDoubleTap(MotionEvent event) {
        // try to ignore double taps on a button
        if (release((int) event.getX(), (int) event.getY(), false))
            return true;

        // double top zooms to point or zooms out
        BoardGeometry boardGeometry = renderer.getGeometry();
        boardGeometry.toggleZoom((int) event.getX(), (int) event.getY());

        return true;
    }

    @Override
    public boolean onScale(ScaleGestureDetector detector) {
        BoardGeometry boardGeometry = renderer.getGeometry();
        boardGeometry.zoomBy(detector.getScaleFactor());
        return true;
    }

    @Override
    public boolean onScaleBegin(ScaleGestureDetector detector) {
        return true;
    }

    @Override
    public void onScaleEnd(ScaleGestureDetector detector) {
    }

    @Override
    public void onDraw(Canvas canvas) {
        super.onDraw(canvas);
    }

    public void addButton(Type type) {
        buttons[type.ordinal()].setEnabled(true);
        buttonsPlaced = false;
    }

    public void removeButtons() {
        for (UIButton button : buttons)
            button.setEnabled(false);
    }

    public void placeButtons(int width, int height) {
        if (buttonsPlaced)
            return;

        // first button is always in the top left corner
        int x = 0;
        int y = height;

        for (UIButton button : buttons) {
            if (!button.isEnabled())
                continue;

            int endwidth = width - button.getWidth() / 2;
            int endheight = button.getHeight() / 2;

            // set position
            UIButton.Type type = button.getType();
            if (type == UIButton.Type.CANCEL || type == UIButton.Type.ROLL
                    || type == UIButton.Type.ENDTURN) {
                // set position to far right/bottom
                if (width < height)
                    button.setPosition(endwidth,
                            height - button.getHeight() / 2);
                else
                    button.setPosition(button.getWidth() / 2, endheight);
            } else {
                // set to next available position
                button.setPosition(x + button.getWidth() / 2,
                        y - button.getHeight() / 2);

                // get next position
                if (height >= width) {
                    // portrait
                    int size = button.getWidth();
                    x += size;
                    if (x + 1.5 * size > endwidth) {
                        x = 0;
                        y -= button.getHeight();
                    }
                } else {
                    // landscape
                    int size = button.getHeight();
                    y -= size;
                    if (y - 1.5 * size < endheight) {
                        y = height;
                        x += button.getWidth();
                    }
                }
            }
        }

        buttonsPlaced = true;
    }

    public void drawButtons(TextureManager texture, GL10 gl) {
        for (UIButton button : buttons) {
            if (button.isEnabled())
                texture.draw(button, gl);
        }
    }

    private boolean click(int x, int y) {
        Player player = CatAndroidApp.getInstance().getBoardInstance().getCurrentPlayer();
        BoardGeometry boardGeometry = renderer.getGeometry();
        GameRenderer.Action action = renderer.getAction();

        if (!player.isHuman())
            return false;

        int select = -1;

        switch (action) {
        case NONE:
            return false;

        case ROBBER:
            // select a hexagon
            select = boardGeometry.getNearestHexagon(x, y);
            break;

        case TOWN:
        case CITY:
            // select a vertex
            select = boardGeometry.getNearestVertex(x, y);
            break;

        case ROAD:
            // select an edge
            select = boardGeometry.getNearestEdge(x, y);
            break;
        }

        if (select >= 0) {
            game.select(action, select);
            return true;
        }

        return false;
    }

    private boolean press(int x, int y) {
        // consider buttons
        for (UIButton button : buttons) {
            if (button != null && button.press(x, height - y))
                return true;
        }

        return false;
    }

    private boolean release(int x, int y, boolean activate) {
        boolean released = false;

        // consider buttons
        for (UIButton button : buttons) {
            if (button.release(x, height - y)) {
                released = true;
                if (activate)
                    game.buttonPress(button.getType());
            }
        }

        return released;
    }
}

1 个答案:

答案 0 :(得分:0)

在活动中调用finish(),使其停止并移除曲面。删除finish()修复了问题。