GLSurfaceView inside fragment does not appear on restart

I have a GLSurfaceView setup and rendering, as expected, using GLSurfaceView.Renderer . My application uses fragments from the Android support package. When I move to a new fragment, surfaceDestroyed is called, but when I return to the fragment through backstack, GLSurfaceView will not be displayed, calls to requestRender will not result in an onDraw call.

I know that I need to call onResume and onPause on a surface view, and I am doing this from a hosting fragment, but it does not seem to solve the problem. All examples of the htis method relate to activity, can this be a problem? And if so, how do you use GLSurfaceView inside the fragment.

Any insight is much appreciated, I am happy to post the code, but it seems to be a more general question for me,

thank

+59
android android-fragments opengl-es glsurfaceview
May 17 '12 at 2:05 a.m.
source share
5 answers

This is how I have the GLSurfaceView setting in the snippet:

 onCreateView() { glSurfaceView = new GLSurfaceView(getActivity()); ... } onPause() { if (glSurfaceView != null) { glSurfaceView.onPause(); } ... } onResume() { if (glSurfaceView != null) { glSurfaceView.onResume(); } ... } 

}

So, it looks like what you would do in your work. This works in my use case, so it seems like they work in fragments. It's hard to say more without knowing what your code looks like.

+4
Feb 22 '13 at 1:08
source share

I know this too late, but it can be useful for others. This is my answer, as I have already implemented it, and it works well both in the emulator and in the device. I have a fragment and support. I hope you will enjoy.

 import android.opengl.GLSurfaceView; import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentTransaction; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import com.example.opengles20.glsurfaceview.GlSurfaceViewClass; import com.example.opengles20.renderer.RendererClass; public class MYGlclass extends Fragment { private GlSurfaceViewClass mGLView; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { if (container == null) { return null; } View view=inflater.inflate(R.layout.main, container, false); mGLView=(GlSurfaceViewClasss)view.findViewById(R.id.gl_surface_view); mGLView.setEGLContextClientVersion(2); RendererClass rendererclass=new RendererClass(getActivity()); mGLView.setRenderer(rendererclass); mGLView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); return view; } } 
+4
Mar 21 '13 at 13:26
source share

A few things you need to implement when using fragments with glsurfaceview. It's a bit complicated, but stay with me. When you switch to a new fragment, ondestroyview is automatically called onto your fragment using glsurfaceview, which destroys your view (the glsurfaceview that you created and returned to oncreateview).

Therefore, when you move to a new fragment, then onpause, onstop, ondestroyview is called automatically, without any work on your part. when you return to this snippet using glsurfaceview, then oncreateview, onactivitycreated, onstart and onresume are automatically called, without any work on your part.

The key to your question is understanding the fragment life cycle that can be found on the Android developer website, as well as understanding how glsurfaceview works.

Now, using glsurfaceview, you must implement the renderer using onsurfacecreated, onsurfacechanged and ondrawframe. Moving to another fragment and then returning to the fragment using glsurfaceview will cause the onsurfacecreated function to be called again, since your glsurfaceview was destroyed in ondestroyview, your context was lost and you need to reload all your resources in the gl stream.

Finally, from your question you can see that the ondrawframe is not being called, which is probably due to the fact that you are not re-creating your view, not installing the renderer and not returning your view from oncreateview.

so in oncreateview you need something like this

 @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View mView = inflater.inflate(R.layout.fragment_layout, null); surface = (GLSurfaceView) mView.findViewById (R.id.glsurfaceview); surface.setEGLContextClientVersion(2); //return your view here return mView; } @Override public void onActivityCreated(Bundle mState) { super.onActivityCreated(mState); //setting your renderer here causes onSurfaceCreated to be called //if you set your renderer here then you have a context to load resources surface.setRenderer( shader ); } 

You do not want to create your own shader rendering class in oncreateview unless you want your rendering class to “start” every time you return to your fragment using glsurfaceview. Instead, create your rendering class in your onCreate snippets, so if you have something customized, you will start right where you left, because just setting up the rendering will provide you with a surface that will call onsurfacecreated, onsurfacechanged and ondrawframe automatically. Make sure that you reload all the resources that you last used onsurfacecreated in the ondrawframe before drawing them.

 @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); shader = new Shader(this); Log.d("Fragment", "OnCreate"); } 

when it comes to pausing and resuming a fragment, then in most cases it is automatically processed when you dynamically replace the fragment and add it to the stack, so just add surface.onpause () and surface.onResume () to the right spots, and you're good to go .

To make things crystal clear, try putting log entries in methods that revolve around the fragment life cycle and glsurfaceview renderer, and you can see what happens and what doesn't happen.

+3
Aug 03 '14 at 18:24
source share

I don’t work with fragments, but if glsurface was destroyed, you may have to create an instance of OpenGLRenderer again and reanimate it to glururface, this code works for me in actions when changing orientation and restoring the whole screen, in this case I need to set the contents of the layout again for reset glsurfaceview:

 view.onPause(); setContentView(R.layout.slidegl); view = (GLSurfaceView) this.findViewById(R.id.glSurface); renderer = new OpenGLRenderer(); view.setRenderer(renderer); view.onResume(); 

If you don’t restart and configure the entire viewing content, try creating a new GLSurface object:

 this.view = new GLSurfaceView(); 
+1
Sep 26
source share

I am not an expert with OpenGL ES , but I have tried my way around fragments and their life cycle. I suggest you set onCreateView for your fragment, tell the visualizer to start drawing again, and if that doesn't work, try to do this from onResume from the fragment. There is no need to do anything from the activity level when it comes to drawing the GL surface in a fragment.

+1
Jan 20 '13 at 16:27
source share



All Articles