GLSurfaceView внутри фрагмента не отображается при перезапуске

У меня есть GLSurfaceView настройка и рендеринг, как ожидалось, с помощью GLSurfaceView.Renderer. Мое приложение использует фрагменты из пакета поддержки Android. Когда я перехожу к новому фрагменту, surfaceDestroyed вызывается, но когда я возвращаюсь к фрагменту через backstack, GLSurfaceView не будет отображаться, вызовы requestRender не приводят к вызову onDraw.

Мне известно, что мне нужно вызвать onResume и onPause на поверхностном представлении, и я делаю это из фрагмента хостинга, но, похоже, это не решает проблему. Все примеры о методе htis относятся к активности, может ли это быть проблемой? И если да, то как вы используете GLSurfaceView внутри фрагмента.

Любое понимание очень ценится, я рад опубликовать код, но, похоже, это более общий вопрос для меня,

Спасибо

Ответ 1

Вот как у меня есть настройка GLSurfaceView в фрагменте:

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

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

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

}

Итак, похоже на то, что вы делали бы в своей деятельности. Это работает в моем случае использования, поэтому кажется, что они работают в фрагментах. Трудно сказать больше, не зная, как выглядит ваш код.

Ответ 2

Я знаю это слишком поздно, но может быть полезно для других Это мой ответ, поскольку я уже реализовал его, и он хорошо работает как в эмуляторе, так и в устройстве. У меня есть фрагмент и поддержка. Надеюсь, вам понравится.

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

Ответ 3

Несколько вещей, которые вам нужно реализовать при использовании фрагментов с glsurfaceview. Это немного сложно, но оставайтесь со мной. Когда вы переходите к новому фрагменту, ondestroyview автоматически вызывается на ваш фрагмент с помощью glsurfaceview, что разрушает ваше представление (glsurfaceview, которое вы создали и вернули в oncreateview).

Поэтому, когда вы переходите к новому фрагменту, тогда onpause, onstop, ondestroyview вызывается автоматически, без какой-либо работы с вашей стороны. когда вы возвращаетесь к этому фрагменту с помощью glsurfaceview, тогда oncreateview, onactivitycreated, onstart и onresume автоматически вызываются, без какой-либо работы с вашей стороны.

Ключом к вашему вопросу является понимание жизненного цикла фрагмента, который можно найти на веб-сайте разработчика Android, а также понимание того, как работает glsurfaceview.

Теперь, используя glsurfaceview, вы должны реализовать средство визуализации, используя onsurfacecreated, onsurfacechanged и ondrawframe. Переход к другому фрагменту, а затем возврат к фрагменту с помощью glsurfaceview приведет к тому, что функция onsurfacecreated будет вызвана снова, так как ваше glsurfaceview было уничтожено в ondestroyview, ваш контекст был потерян, и вам нужно перезагрузить все ваши ресурсы в потоке gl.

Наконец, из вашего вопроса видно, что ondrawframe не вызывается, что, вероятно, связано с тем, что вы не воссоздаете свое представление, не устанавливаете средство визуализации и не возвращаете свое представление из oncreateview.

поэтому в oncreateview вам нужно что-то вроде этого

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

Вы не хотите создавать свой класс рендеринга (shader) в oncreateview, если вы не хотите, чтобы ваш класс рендеринга "начинал" каждый раз, когда вы возвращаетесь к вашему фрагменту с помощью glsurfaceview. Вместо этого создайте свой класс рендеринга в своих фрагментах onCreate, таким образом, если у вас есть что-то настроенное, вы начнете прямо там, где вы ушли, поскольку просто настройка рендеринга предоставит вам поверхность, которая вызовет вызов onsurfacecreated, onsurfacechanged и ondrawframe автоматически. Убедитесь, что вы перезагрузите все ресурсы, которые вы в последний раз использовали в onsurfacecreated, в ondrawframe перед их рисованием.

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

    shader = new Shader(this); 

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

}

когда дело доходит до приостановки и возобновления фрагмента, тогда в большинстве случаев это автоматически обрабатывается, когда вы динамически заменяете фрагмент и добавляете его в стопку, поэтому просто добавляйте surface.onpause() и surface.onResume() в правильные пятна, и вам хорошо идти.

Чтобы сделать вещи кристально чистыми, попробуйте помещать записи журнала в методы, вращающиеся вокруг жизненного цикла фрагмента и средства визуализации glsurfaceview, и вы сможете увидеть, что происходит и чего не происходит.

Ответ 4

Я не работаю с фрагментами, но если glsurface был уничтожен, возможно, вам придется снова создать экземпляр OpenGLRenderer и реанимировать его на glururface, этот код работает для меня в действиях при изменении ориентации и воссоздании всего экрана, в этом случае Мне нужно снова установить содержимое макета для reset glsurfaceview:

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

Если вы не перезапустите и не настроите все содержимое просмотра, попробуйте создать новый объект GLSurface:

this.view = new GLSurfaceView(); 

Ответ 5

Я не эксперт с OpenGL ES, но я пробовал свой путь вокруг фрагментов и их жизненного цикла. Я предлагаю вам установить onCreateView для вашего фрагмента, сообщить визуализатору снова начать рисование, и если это не сработает, попробуйте сделать это из onResume из фрагмента. Не нужно ничего делать из уровня активности, когда дело касается рисования поверхности GL во фрагменте.