Kizik Studios
Kizik Studios

Reputation: 179

GLSurfaceView parent is null even though it is nested in a LinearLayout

I have a custom view called GLView that extends the GLSurfaceView class. Inside of this GLView I want to access the other TextView that is contained in a parent Linear Layout. When I call this.getParent it returns NULL, so I looked and eclipse indeed says that mparent is null. does anyone know why?

Activity class that calls the View

package org.kizik.WLTBO;



import android.app.Activity;
import android.os.Bundle;




import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;


public class WholettheballoutActivity extends Activity {
   GLView view;



   @Override
   public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.score);
      view = (GLView) findViewById(R.id.mySurfaceView);


   // You can use a FrameLayout to hold the surface view
      /*FrameLayout frameLayout = new FrameLayout(this);
      frameLayout.addView(view);

      // Then create a layout to hold everything, for example a RelativeLayout
      RelativeLayout relativeLayout= new RelativeLayout(this);
      relativeLayout.addView(frameLayout);
      relativeLayout.addView(score);
      setContentView(relativeLayout);*/
   }

   @Override
   protected void onPause() {
       super.onPause();
       view.onPause();
   }

   @Override
   protected void onResume() {
       super.onResume();
       view.onResume();
   }
}

XML File

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:id="@+id/parent" >


    <TextView android:id="@+id/textView2"
        android:text = "Points 12345 Time:"
        android:gravity="center_horizontal"

        android:textSize="22sp"

        android:layout_width="fill_parent"
        android:layout_height="wrap_content"/>


    <org.kizik.WLTBO.GLView
        android:id="@+id/mySurfaceView"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"/>        

</LinearLayout>

Probably not needed but here are the constructors within the GLView class

public GLView(Context context) {
      super(context);
      // Uncomment this to turn on error-checking and logging
      //setDebugFlags(DEBUG_CHECK_GL_ERROR | DEBUG_LOG_GL_CALLS);
      renderer = new GLRenderer(context, view);
      setRenderer(renderer);
   }

   public GLView(Context context, AttributeSet attrs){

       super(context,attrs);
       view = this.getParent();

       renderer = new GLRenderer(context, view);
       setRenderer(renderer);

   }

Upvotes: 1

Views: 1692

Answers (2)

James Coote
James Coote

Reputation: 1973

Try expanding the layout first before you do setContentView() in activity. You can then check whether the default layout behavior is attaching the GLSurfaceView to the 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);
}

You can't actually change the parent view (the linear layout) or any other views in your renderer from inside the onDraw(), onSurfaceChanged() or onSurfaceCreated() methods as they are all called by the GL thread. Only the main/UI thread (the one that calls onCreate() in your activity) can change the UI. If you tried for example to do ((TextView)view.findViewById(R.id.textView2)).setText("Some text"); in onSurfaceCreated(), it would cause an exception

A better way to do this would be to set the renderer from inside the activity:

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

    }

}

Then in 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);

    }

}

Anything inside the handleMessage method of a Handler gets queued for the UI thread to execute next time it loops round. There are other ways to pass messages between other threads and the UI thread, but this one although not immediately obvious, makes most sense for non-UI threads making single asynchronous updates to the UI

EDIT: Handler has to be declared in the thread it is to be used in (unless you're doing something funky see here)

Upvotes: 2

poitroae
poitroae

Reputation: 21367

The documentation says

Gets the parent of this view. Note that the parent is a ViewParent and not necessarily a View.

Upvotes: 0

Related Questions