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
во фрагменте.