即使GLSurfaceView父嵌套在LinearLayout中,它也是null

时间:2011-12-24 02:25:04

标签: android view opengl-es android-linearlayout

我有一个名为GLView的自定义视图,它扩展了GLSurfaceView类。在这个GLView内部,我想访问父线性布局中包含的另一个TextView。当我调用this.getParent时它返回NULL,所以我看了,eclipse确实说mparent为null。有谁知道为什么?

调用视图的活动类

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文件

<?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>

可能不需要,但这里是GLView类中的构造函数

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

   }

2 个答案:

答案 0 :(得分:2)

在活动中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线程。只有主/ UI线程(在您的活动中调用onCreate()的线程)才能更改UI。如果您尝试在((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);

    }

}

Handler的handleMessage方法中的任何内容都会排队等待UI线程在下一次循环时执行。有other ways to pass messages between other threads and the UI thread,但这个虽然不是很明显,但对于非UI线程对UI进行单个异步更新最有意义

编辑:处理程序必须在要使用的线程中声明(除非你正在做一些时髦的see here

答案 1 :(得分:0)

文档说

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