Просмотр через GLSurfaceView мерцает или не отображается вообще

#android #opengl-es #glsurfaceview

#Android #opengl-es #glsurfaceview

Вопрос:

Мы используем, ViewGroup содержащий большое GLSurfaceView и маленькое представление. Вид отображается поверх GLSurfaceView . Вид виден при перетаскивании, но он исчезает, как только движение заканчивается и палец отрывается от планшета. Мы обнаружили, что это происходит только в том случае, если это setRenderMode(RENDERMODE_WHEN_DIRTY) установлено. Это работает, когда изображение отображается непрерывно, но это имеет довольно плохие последствия для производительности.

При использовании RelativeLayout вместо ViewGroup вид отображается после того, как палец отпущен от планшета, но он мерцает, когда вид перемещается медленно.

Невозможно нарисовать представление с помощью OpenGL, потому что GLSurfaceView не заполняет всю ViewGroup, и представление можно перемещать по всей ViewGroup.

Вот полный пример, показывающий проблему:

 package test.gl.app;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.app.Activity;
import android.content.Context;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;

public class GLTestAppActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mGLViewGroup = new GLViewGroup(this);
        setContentView(mGLViewGroup);
    }

    @Override
    protected void onPause() {
        super.onPause();
        mGLViewGroup.onPause();
    }

    @Override
    protected void onResume() {
        super.onResume();
        mGLViewGroup.onResume();
    }

    private GLViewGroup mGLViewGroup;
}



class ImageView extends View {

    private Drawable _drawable;

    public ImageView(Context context) {
        super(context);
        _drawable = new BitmapDrawable(BitmapFactory.decodeResource(context.getResources(), R.drawable.icon_192));
        _drawable.setBounds(0,0,_drawable.getIntrinsicWidth(),_drawable.getIntrinsicHeight());
        measure(0,0);
    }

    protected void onMeasure(int m, int m2) {
        setMeasuredDimension(_drawable.getIntrinsicWidth(), _drawable.getIntrinsicHeight());
    }

    protected void onDraw (Canvas canvas) {
        _drawable.draw(canvas);
    }
}



class GLViewGroup extends ViewGroup {

    private ClearGLSurfaceView mGLView;
    private ImageView mImageView;
    private int mX = 300;
    private int mY = 200;

    public GLViewGroup(Context context) {
        super(context);

        mGLView = new ClearGLSurfaceView(context);
        addView(mGLView);

        mImageView = new ImageView(context);
        addView(mImageView);

        setOnTouchListener(new OnTouchListener() {
            public boolean onTouch(View v, final MotionEvent event) {
                mX = (int)event.getX();
                mY = (int)event.getY();

                mImageView.layout(mX, mY, mX mImageView.getMeasuredWidth(), mY mImageView.getMeasuredHeight());

                mGLView.setColor(event);
                if (mGLView.getRenderMode()==GLSurfaceView.RENDERMODE_WHEN_DIRTY)
                    mGLView.requestRender();

                return true;
            }
        });

        measure(0, 0);
    }

    public void onResume() {
       mGLView.onResume();
    }

    public void onPause() {
        debug(0);
        mGLView.onPause();
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        mGLView.layout(l, t, r, b);
        mImageView.layout(mX, mY, mX mImageView.getMeasuredWidth(), mY mImageView.getMeasuredHeight());
    }
}


class ClearGLSurfaceView extends GLSurfaceView {
    public ClearGLSurfaceView(Context context) {
        super(context);
        mRenderer = new ClearRenderer();
        setRenderer(mRenderer);
        setRenderMode(RENDERMODE_WHEN_DIRTY);                       // <- remove this line and it works, but app is slow
        measure(0, 0);
    }

    public boolean onTouchEvent(final MotionEvent event) {
        setColor(event);
        return false;
    }

    public void setColor(final MotionEvent event) {
        queueEvent(new Runnable(){
            public void run() {
                mRenderer.setColor(event.getX() / getWidth(),
                        event.getY() / getHeight(), 1.0f);
            }});
    }

    private ClearRenderer mRenderer;
}



class ClearRenderer implements GLSurfaceView.Renderer {

    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
    }

    public void onSurfaceChanged(GL10 gl, int w, int h) {
        gl.glViewport(0, 0, w, h);
    }

    public void onDrawFrame(GL10 gl) {
        gl.glClearColor(mRed, mGreen, mBlue, 1.0f);
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
    }

    public void setColor(float r, float g, float b) {
        mRed = r;
        mGreen = g;
        mBlue = b;
    }

    private float mRed   = 0.5f;
    private float mGreen = 0.5f;
    private float mBlue  = 0.5f;
}
  

Комментарии:

1. мы добавили mImageView.requestLayout(); в конце onTouch() , и теперь это работает нормально.

2. Вызов requestLayout () для нарушающего ImageView сработал для меня.