Попробуйте сначала развернуть макет, прежде чем выполнять setContentView()
в действии. Затем вы можете проверить, подключает ли поведение макета по умолчанию GLSurfaceView к LinearLayout:
View parentView = getLayoutInflater().inflate(R.layout.main,null,false);
view = (GlView)parentView.findViewById(R.id.mySurfaceView);
if(view.getParent()==null || !view.getParent() instanceof View ){
// throw new Exception("GLView had no parent or wrong parent");
} else {
setContentView(parentView);
}
На самом деле вы не можете изменить родительское представление (линейный макет) или любые другие представления в вашем средстве визуализации из методов onDraw()
, onSurfaceChanged()
или onSurfaceCreated()
, так как все они вызываются потоком GL. Только основной поток / поток пользовательского интерфейса (тот, который вызывает onCreate()
в вашей активности) может изменить пользовательский интерфейс. Например, если вы попытаетесь сделать ((TextView)view.findViewById(R.id.textView2)).setText("Some text");
в onSurfaceCreated()
, это вызовет исключение
Лучший способ сделать это - установить средство визуализации внутри действия:
public class WholettheballoutActivity extends Activity {
GLView view;
GLRenderer renderer;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.score);
view = (GLView) findViewById(R.id.mySurfaceView);
LinearLayout parentView = findViewById(R.id.parent);
// Handler declaration goes in UI thread
Handler handle = new Handler(new Handler.Callback(){
@Override
public boolean handleMessage(Message msg){
// message is handled by the UI thread
TextView tv = WholettheballoutActivity .this.findViewById(R.id.textView2);
tv.setText("You Rock!");
return true;
}
});
renderer = new GLRenderer(context, parent, handler);
view.setRenderer(renderer);
}
}
Тогда в рендерере:
public class GLRenderer implements GLSurfaceView.Renderer{
View parent;
Context context;
Handler handler;
public GLRenderer(Context context, View parent, Handler handler){
this.context = context;
this.parent = parent;
this.handler = handler;
}
public void onDraw(GL10 gl){
// drawing etc
handler.sendEmptyMessage(0);
}
}
Все, что находится внутри метода handleMessage Обработчик , помещается в очередь для выполнения потока пользовательского интерфейса в следующий раз, когда он зацикливается. Существуют другие способы передачи сообщений между другими потоками и потоком пользовательского интерфейса , но этот, хотя и не сразу очевидный, наиболее целесообразен для потоков, не являющихся пользовательскими интерфейсами, которые выполняют отдельные асинхронные обновления пользовательского интерфейса
РЕДАКТИРОВАТЬ: обработчик должен быть объявлен в потоке, в котором он будет использоваться (если вы не делаете что-то напуганное см. Здесь )