How to make LibGDX GLSurfaceView transparent so that we can see the Android ImageView behind it?

The basic premise is that I have 2 Android views ... The background view, which fills the screen ( ImageViewin this case) and LibGDX GLSurfaceViewwhich is in the foreground, is the application LibGDX, I want to punch a hole in LibGDX GLSurfaceView, so that I can see background ImageView. those. the part LibGDXbehaves like an overlay. Unfortunately, I cannot get this to work at all. I deleted all the code to leave only the necessary items that hopefully demonstrate what I'm trying to do.

In the full application, this is an Android application where background Viewis the video, and the foreground displayed LibGDXis the set of video controls that should be superimposed on the video.

public class MiniClientGDXTestActivity extends AndroidApplication implements ApplicationListener {
    @Bind(R.id.surface)
    FrameLayout uiFrameHolder;

    Stage stage;
    Batch batch;
    Camera camera;
    Viewport viewport;
    ShapeRenderer shapeRenderer;


    private View miniClientView;

    public MiniClientGDXTestActivity() {
    }

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

        hideSystemUI(this);

        setContentView(R.layout.miniclientgltest_layout);
        ButterKnife.bind(this);

        AndroidApplicationConfiguration cfg = new AndroidApplicationConfiguration();
        //cfg.useGL20 = false;
        // we need to change the default pixel format - since it does not include an alpha channel
        // we need the alpha channel so the camera preview will be seen behind the GL scene
        cfg.r = 8;
        cfg.g = 8;
        cfg.b = 8;
        cfg.a = 8;

        miniClientView = initializeForView(this, cfg);

        if (graphics.getView() instanceof SurfaceView) {
            SurfaceView glView = (SurfaceView) graphics.getView();
            glView.setBackgroundColor(android.graphics.Color.TRANSPARENT);
            // force alpha channel - I'm not sure we need this as the GL surface is already using alpha channel
            glView.getHolder().setFormat(PixelFormat.TRANSLUCENT);
        }

        uiFrameHolder.addView(miniClientView);
    }

    @Override
    public void create() {
        camera = new OrthographicCamera();
        viewport = new StretchViewport(1920, 1080, camera);
        stage = new Stage(viewport);
        batch = stage.getBatch();
        shapeRenderer = new ShapeRenderer();

        Gdx.graphics.setContinuousRendering(false);
        Gdx.graphics.requestRendering();
    }

    @Override
    public void resize(int width, int height) {
        stage.getViewport().setWorldSize(1920, 1080);
        stage.getViewport().update(width, height, true);
        Gdx.graphics.requestRendering();
    }

    @Override
    public void render() {
        Gdx.gl20.glClearColor(0, 0, 0, 0);
        Gdx.gl20.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);

        // draw whatever we have on the stage
        stage.draw();

        // draw red rectangle
        drawRect(10, 10, 1000, 1000);

        // draw a blue box
        fillRect(50, 50, 800, 800);

        // punch a hole in the surface (ie, clear an area) so that we can see the view that is
        // behind this view
        clearRect(200, 200, 1600, 600);
    }

    @Override
    public void pause() {

    }

    @Override
    public void resume() {

    }

    @Override
    public void dispose() {

    }

    public void drawRect(final int x, final int y, final int width, final int height) {
        shapeRenderer.setProjectionMatrix(camera.combined);
        shapeRenderer.begin(ShapeRenderer.ShapeType.Line);
        shapeRenderer.rect(x, y, width, height, Color.RED, Color.RED, Color.RED, Color.RED);
        shapeRenderer.end();
    }

    public void fillRect(final int x, final int y, final int width, final int height) {
        shapeRenderer.setProjectionMatrix(camera.combined);
        shapeRenderer.begin(ShapeRenderer.ShapeType.Filled);
        shapeRenderer.rect(x, y, width, height, Color.BLUE, Color.BLUE, Color.BLUE, Color.BLUE);
        shapeRenderer.end();
    }

    public void clearRect(final int x, final int y, final int width, final int height) {
//                Gdx.gl.glEnable(GL20.GL_BLEND);
//                Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);


        shapeRenderer.setProjectionMatrix(camera.combined);
        shapeRenderer.begin(ShapeRenderer.ShapeType.Filled);
        shapeRenderer.setColor(Color.CLEAR);
        shapeRenderer.rect(x, y, width, height);
        shapeRenderer.end();

//                Gdx.gl.glDisable(GL20.GL_BLEND);
    }

}

And here is the XML layout

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent" android:layout_height="match_parent"
    android:keepScreenOn="true">

    <FrameLayout
        android:visibility="visible"
        android:id="@+id/surface"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">

        <!-- to see if we can see this -->
        <ImageView
            android:layout_width="fill_parent"
            android:layout_height="match_parent" android:scaleType="fitXY" android:src="@drawable/background"/>

        <!-- gdx gets added here -->
    </FrameLayout>


</FrameLayout>
+4
source share
1 answer

It seems that calling setZOrderOnTopusing PixelFormat.RGBA_8888did the trick.

    if (graphics.getView() instanceof SurfaceView) {
        GLSurfaceView glView = (GLSurfaceView) graphics.getView();
        glView.setZOrderOnTop(true);
        glView.getHolder().setFormat(PixelFormat.RGBA_8888);
    }

now when the method is called clearRect, it breaks a hole in GLSurfaceView to see the Android snapshot below.

+3
source

Source: https://habr.com/ru/post/1610860/


All Articles