I have a GLSurfaceView
set up and rendering as expected using a GLSurfaceView.Renderer
. My App uses fragments from the android support package. When I navigate to a new fragment surfaceDestroyed
is called but when I come back to the fragment via the backstack the GLSurfaceView
will not render, calls to requestRender
do not result in an onDraw
call.
I am aware that I need to call onResume
and onPause
on the surface view and I am doing this from the hosting fragment but it doesn't seem to solve the issue. All examples about htis method refer to the activity, could this be the issue? And if so how do you use a GLSurfaceView
inside a fragment.
Any insight greatly appreciated, I'm happy to post code but it seems to be more of a general question to me,
Thanks
Here's how I have my GLSurfaceView setup in a fragment:
onCreateView() {
glSurfaceView = new GLSurfaceView(getActivity());
...
}
onPause() {
if (glSurfaceView != null) { glSurfaceView.onPause(); }
...
}
onResume() {
if (glSurfaceView != null) { glSurfaceView.onResume(); }
...
}
}
So, similar to what you'd do in an activity. This works in my use case, so it seems like they do work in fragments. It's hard to say more without knowing what your code looks like.
I know it's too late but it may be useful for others This is my answer as i have already implemented it and it works well in both emulator and in device as well.i have use fragment and supportV4.Hope you will like it.
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;
}
}
A couple of things you need to realize when using fragments with a glsurfaceview. It gets a little tricky but stay with me. When you navigate to a new fragment, ondestroyview gets called on your fragment with the glsurfaceview automatically, which destroys your view (the glsurfaceview that you created and returned in oncreateview).
So when you navigate to a new fragment then onpause, onstop, ondestroyview gets called automatically, without any work on your part. when you come back to that fragment with the glsurfaceview then oncreateview, onactivitycreated, onstart and onresume gets called automatically, without any work on your part.
The key to your question is understanding the fragment lifecycle which can be found at the android developer website, and understanding how glsurfaceview functions as well.
Now, using the glsurfaceview you have to implement the renderer, using onsurfacecreated, onsurfacechanged, and ondrawframe. Navigating to another fragment and then coming back to your fragment with the glsurfaceview will result in onsurfacecreated being called again, since your glsurfaceview was destroyed in ondestroyview, your context has been lost and you need to reload all of your resources on the gl thread.
Lastly, it looks from your question that ondrawframe is not being called, which is probably due to you not recreating your view, set the renderer, and 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 don't want to create your rendering class (shader) in oncreateview unless you want your rendering class to 'start over' every time you come back to your fragment with the glsurfaceview. Instead create your rendering class in your Fragments onCreate, that way if you have things set up then you will start right where you left since simply setting the renderer will provide you with the surface which will cause the onsurfacecreated, onsurfacechanged, and ondrawframe to be invoked automatically. Make sure you reload whatever resources you were last using in onsurfacecreated, on in the ondrawframe prior to 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 your fragment, then in most cases this is automatically handled when you dynamically replace a fragment and add it to the backstack, so just simply put surface.onpause() and surface.onResume() in the right spots and you are good to go.
To make things crystal clear try putting log statements in the methods revolving around the fragment lifecycle and glsurfaceview renderer and you will be able to see what is and isn't happening.
I not work with fragments but if the glsurface was destroyed, perhaps have to create an instance again of the OpenGLRenderer and reassing to the glsurface, this code work for me in activities when change orientation and recreate all the screen, in this case I have to set the contentview of layout again for reset the glsurfaceview:
view.onPause();
setContentView(R.layout.slidegl);
view = (GLSurfaceView) this.findViewById(R.id.glSurface);
renderer = new OpenGLRenderer();
view.setRenderer(renderer);
view.onResume();
If you wan´t restart and setup all content of view try creating a new object of GLSurface:
this.view = new GLSurfaceView();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With