59 votes

GLSurfaceView dans le fragment non rendu au redémarrage

J'ai un GLSurfaceView mis en place et rendu comme prévu à l'aide d'un GLSurfaceView.Moteur de rendu. Mon Application utilise des fragments à partir de l'android support package. Lorsque je navigue à un nouveau fragment surfaceDestroyed est appelée, mais quand je reviens à la fragment via la backstack l' GLSurfaceView ne sera pas rendu, les appels à l' requestRender celui-ci, n' onDraw appel.

Je Suis conscient que je dois appeler onResume et onPause sur la surface d'affichage et je fais de l'hébergement fragment, mais il ne semble pas résoudre le problème. Tous les exemples sur ce méthode se référer à l'activité, cela pourrait être le problème? Et si oui, comment utilisez-vous un GLSurfaeView à l'intérieur d'un fragment.

Aucune information beaucoup apprécié, je suis heureux de publier le code, mais il semble être plus une question d'ordre général à moi,

Merci

4voto

Learn OpenGL ES Points 932

Voici comment j'ai la configuration de GLSurfaceView dans un fragment:

 onCreateView() {
    glSurfaceView = new GLSurfaceView(getActivity());
   ...
}

onPause() {
    if (glSurfaceView != null) { glSurfaceView.onPause(); }
    ...
}

onResume() {
    if (glSurfaceView != null) { glSurfaceView.onResume(); }
    ...
}
 

}

Donc, semblable à ce que vous feriez dans une activité. Cela fonctionne dans mon cas d'utilisation, il semble donc qu'ils fonctionnent par fragments. Il est difficile d'en dire plus sans savoir à quoi ressemble votre code.

4voto

ravi Points 32

Je sais que c’est trop tard, mais cela peut être utile pour d’autres. C’est ma réponse car je l’ai déjà mise en oeuvre et cela fonctionne aussi bien dans l’émulateur que dans le périphérique.J'ai utilisé fragment et supportV4.Espoir.

 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;
}
}
 

3voto

SavageKing Points 86

Un couple de choses que vous devez réaliser lors de l'utilisation de fragments avec une glsurfaceview. Ça devient un peu délicat, mais rester avec moi. Lorsque vous accédez à un nouveau fragment, ondestroyview est appelée sur votre fragment avec le glsurfaceview automatiquement, ce qui détruit votre point de vue (la glsurfaceview que vous avez créé et est retourné dans oncreateview).

Ainsi, lorsque vous accédez à un nouveau fragment puis onpause, onstop, ondestroyview est appelée automatiquement, sans aucun travail de votre part. lorsque vous revenez à ce fragment avec le glsurfaceview puis oncreateview, onactivitycreated, onstart et onresume est appelée automatiquement, sans aucun travail de votre part.

La clé de votre question est de comprendre le fragment du cycle de vie qui peut être trouvé à l'android développeur de site web, et de comprendre comment glsurfaceview fonctions.

Maintenant, à l'aide de la glsurfaceview vous avez à mettre en œuvre la fonctionnalité de rendu, à l'aide de onsurfacecreated, onsurfacechanged, et ondrawframe. L'accès à un autre fragment, puis revenir à votre fragment avec le glsurfaceview entraînera onsurfacecreated être appelée de nouveau, depuis votre glsurfaceview a été détruit dans ondestroyview, votre contexte a été perdu et vous avez besoin de recharger toutes vos ressources sur le gl fil.

Enfin, il semble de votre question que ondrawframe n'est pas appelée, ce qui est probablement en raison pour vous de ne pas recréer de votre point de vue, réglez le moteur de rendu, et le retour de votre point de vue de oncreateview.

ainsi, dans oncreateview vous besoin de quelque chose comme cela

@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); 

    //set the renderer here, important or ondrawframe will not be called! 
    surface.setRenderer( shader );

    //you may need to configure rendermode here

    //return your view here
    return mView; 
}

Vous ne voulez pas créer votre classe de rendu (shader) dans oncreateview, sauf si vous voulez que votre classe de rendu de "recommencer" à chaque fois que vous revenez à votre fragment avec le glsurfaceview. Au lieu de créer votre classe de rendu dans vos Fragments onCreate, de cette façon, si vous avez des choses mis en place puis vous allez commencer à exactement où vous avez quitté depuis le simple réglage, le moteur de rendu sera de vous fournir avec la surface qui sera la cause de la onsurfacecreated, onsurfacechanged, et ondrawframe être invoquée automatiquement. Assurez-vous de recharger toutes les ressources que vous avez été le dernier à onsurfacecreated, dans le ondrawframe avant de les dessiner.

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

    shader = new Shader(this); 

    Log.d("Fragment", "OnCreate"); 

}

quand il s'agit de la suspension et la reprise de votre fragment, puis dans la plupart des cas, cela est géré automatiquement lorsque vous remplacer dynamiquement un fragment et l'ajouter à la backstack, il suffit donc simplement de mettre de la surface.onpause() et de la surface.onResume() dans les bons endroits et vous êtes bon pour aller.

Pour rendre les choses limpides, essayez de mettre du journal des déclarations dans les méthodes tournant autour de l'fragment du cycle de vie et glsurfaceview moteur de rendu et vous serez en mesure de voir ce qui est et n'est pas le cas.

1voto

Zeus Monolitics Points 283

J'ai pas de travail avec les fragments, mais si le glsurface a été détruit, peut-être faut créer une instance de nouveau de la OpenGLRenderer et reassing à la glsurface, ce code fonctionne pour moi dans les activités où les changements d'orientation et de recréer tout l'écran, dans ce cas, je dois mettre les contentview de mise en page à nouveau pour réinitialiser le glsurfaceview:

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

Si vous voulez redémarrer et installation de tout le contenu de vue essayez de créer un nouvel objet de GLSurface:

this.view = new GLSurfaceView(); 

1voto

Shaun Points 1706

Je ne suis pas un expert avec OpenGL ES , mais je me suis assez battu pour éviter les fragments et leur cycle de vie. Ce que je vous suggère de faire est de définir onCreateView pour votre fragment, de dire au générateur de rendu de recommencer à dessiner, et si cela ne fonctionne pas, essayez de le faire à partir du onResume du fragment. Il ne devrait y avoir aucune nécessité de faire quelque chose à partir du niveau d'activité lorsqu'il s'agit de dessiner la surface GL dans le fragment.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X