试图以编程方式将GLSurfaceView添加到布局中

3

好的,先简单介绍一下背景...我有一个完全运作良好的游戏,使用画布进行绘制,现在正在尝试学习并将绘图转换为OpenGL ES 1.0。(保持兼容性。)

我一直在尝试的是,找出一种方法将GLSurfaceView和Renderer合并到程序中,以便我可以逐步切换绘图。(有许多精灵需要经常更新,所以我不希望花费一个月来发布下一个更新。)

有人建议我在当前SurfaceView上使用GLSurfaceView,我正在努力实现,但遇到了一些问题。

我基本上是使用LunarLander示例,尝试添加一个简单的OpenGL渲染器,用于在方块上绘制纹理并呈现它。目标是在画布上方绘制方块。

以下是Activity中相关的代码:

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);



        setContentView(R.layout.lunar_layout);


        LinearLayout detailListView = (LinearLayout) findViewById(R.id.dets); // Find the layout where you want to add button

    Button button = new Button(this);
    button.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT));
    detailListView.addView(button);//add view to add



    mGLSV = new BasicGLSurfaceView(this);
    mGLSV.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT));
    detailListView.addView(mGLSV);

    //clipped
文件的内容如下:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:ads="http://schemas.android.com/apk/lib/com.google.ads"

    android:layout_width="match_parent"
    android:layout_height="match_parent">



    <com.example.android.lunarlander.LunarView
        android:id="@+id/lunar"
      android:layout_width="match_parent"
      android:layout_height="match_parent"/>

    <LinearLayout
       android:id="@+id/dets"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_alignParentLeft="true"
       android:layout_alignParentTop="true"
       android:layout_marginLeft="0dp"
       android:layout_marginTop="50dp"
       android:orientation="vertical" >

         <com.google.ads.AdView
             android:id="@+id/adView"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             ads:adSize="BANNER"
             ads:adUnitId="a14ecf8f2d9ef49"
             ads:loadAdOnCreate="true" >
         </com.google.ads.AdView>

    </LinearLayout>



     <RelativeLayout   
         android:id="@+id/relLayout"
         android:layout_width="match_parent"
         android:layout_height="match_parent" >

         <TextView
             android:id="@+id/text"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_centerInParent="true"
             android:gravity="center_horizontal"
             android:text="@string/lunar_layout_text_text"
             android:textColor="#88ffffff"
             android:textSize="24sp"
             android:visibility="visible" />

      </RelativeLayout>

</FrameLayout>

很简单,我想使用LinearLayout在Surface View上添加一些东西。请注意,我还添加了一个按钮,只是为了检查这个概念是否可行。 结果是画布和按钮正确显示,但没有GLSurfaceView的迹象。我做错了什么?

3个回答

4

我建议您在XML中将BasicGLSurfaceView添加到您的帧布局中,并使用findViewById(R.id.basicGLSurfaceView1)来获取它,而不是尝试通过编程创建它:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:ads="http://schemas.android.com/apk/lib/com.google.ads"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.example.android.lunarlander.BasicGLSurfaceView 
        android:id="@+id/glSurfaceView1" 
        android:layout_width="match_parent" 
        android:layout_height="match_parent">
    </com.example.android.lunarlander.BasicGLSurfaceView>

    <com.example.android.lunarlander.LunarView
      android:id="@+id/lunar"
      android:layout_width="match_parent"
      android:layout_height="match_parent"/>

    <LinearLayout
       android:id="@+id/dets"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_alignParentLeft="true"
       android:layout_alignParentTop="true"
       android:layout_marginLeft="0dp"
       android:layout_marginTop="50dp"
       android:orientation="vertical" >

         <com.google.ads.AdView
             android:id="@+id/adView"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             ads:adSize="BANNER"
             ads:adUnitId="a14ecf8f2d9ef49"
             ads:loadAdOnCreate="true" >
         </com.google.ads.AdView>

    </LinearLayout>



     <RelativeLayout   
         android:id="@+id/relLayout"
         android:layout_width="match_parent"
         android:layout_height="match_parent" >

         <TextView
             android:id="@+id/text"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_centerInParent="true"
             android:gravity="center_horizontal"
             android:text="@string/lunar_layout_text_text"
             android:textColor="#88ffffff"
             android:textSize="24sp"
             android:visibility="visible" />

      </RelativeLayout>

</FrameLayout>

您需要告诉GLSurfaceView开始渲染。在GLSurfaceView中,您需要调用(或甚至覆盖)GLSurfaceView.start()。另外,setRenderer是公共的,因此如果您在Activity中调用mGLSV.setRenderer(myRenderer);,其中myRenderer是实现GLSurfaceView.Renderer的MyRenderer的实例,则应自动启动渲染,而无需您触摸start()

编辑:实际上,在视图布局时(即当您使用setContentView()或将其添加到设置为内容视图的任何布局中时),会调用start(),而不是在调用setRenderer时调用。

听起来有些前后颠倒,但实现Renderer是为了如果您只想以标准的android/opengl-es方式呈现某些内容,而扩展GLSurfaceView则是为了实际上要深入了解并编辑android呈现的方式。事实上,我建议根本不要扩展GLSurfaceView,而是尽可能多地在GLSurfaceView.Renderer中完成。我已经编写了整个3D游戏的代码,而没有扩展GLSurfaceView。我的代码看起来像这样:

public class stackoverflowTest extends Activity {

MyGLSurfaceView glSurface;
MyRenderer myRenderer;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.main);

    myRenderer = new MyRenderer();

    //Get hold of our GLSurfaceView
    glSurface = (MyGLSurfaceView) findViewById(R.id.graphics_glsurfaceview1);
    // optional
    glSurface.setEGLConfigChooser(true);

    glSurface.setRenderer(myRenderer);
    //Set the renderer. setRenderer will call start() and start the GL thread, which then calls onSurfaceCreated, onDraw etc in the Renderer



}

    @Override
public void onPause(){
    super.onPause();
     glSurface.onPause();
}

@Override
public void onResume() {
       super.onResume();
       glSurface.onResume();
    }
}

}

渲染器:

public class MyRenderer implements Renderer {

@Override
public void onDrawFrame(GL10 gl) {
    // openGL drawing code goes here


}

@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {

    // etc


}

@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
    // etc


}

}

GLSurfaceView:

public class MyGLSurfaceView extends GLSurfaceView {

public MyGLSurfaceView(Context context) {
    super(context);

}

public MyGLSurfaceView(Context context, AttributeSet attribs) {
    super(context, attribs);

}

@Override
public void onPause(){
    super.onPause();
}

@Override
public void onResume(){
    super.onResume();
}

}

如果您能升级到Android 2.1(opengl-es 1.1),则可以使用点精灵而不是渲染纹理四边形或其他内容。

这是我困惑的地方...我已经让它达到了这样的程度,当我点击“返回”按钮时,画布消失了,我可以看到渲染出来的图像。所以,似乎画布在渲染器的上面,但令人困惑的是,那个按钮和Adview也消失了???同时,注释掉添加Open GL渲染器的代码会使按钮和添加视图重新出现。???我不明白。如果画布在按钮/添加视图下面,GL表面视图如何影响按钮和广告的可见性? - cody
现在我确定布局与问题有关,如果我将GLSurface视图的可见性设置为消失或不可见,则按钮和广告重新出现。因此,如果您可以想象深度,我希望画布位于底部,GLSurfaceView位于中间,按钮/广告位于顶部。好的,前两个是正确的,但每当Surface视图应该可见时,它会使按钮/广告不可见,而画布仍然可见? - cody
啊啊啊啊啊,这太让人沮丧了。我把 SurfaceView 的高度改成了 500 像素,这样我就可以在它下面看到东西了,但是我的渲染器却在画布下面而不是上面。我该怎么办?我无法交换它们的顺序。 - cody
交换lunarView和basicGLSurfaceView,使得lunarView在XML中排在basicGLSurfaceView之前。这将把lunarView放在底部,而basicGLSurfaceView则绘制在其上方。由于framelayout呈现的方式类似于队列而不是堆栈,因此很容易混淆;framelayout的第一个子元素被渲染,然后第二个子元素在第一个子元素的上面渲染,第三个子元素在第二个子元素的上面渲染,以此类推。您需要使GLSurfaceView的背景透明,因为默认情况下它不是透明的。我不知道如何使画布透明。 - James Coote
由于最终的目标是替换画布,因此将画布和GLSurfaceView并排放置可能更容易进行开发。 - James Coote
我找到了解决方法,我需要调用setZOrderOnTop(true)函数;你不能使用bringtofront()函数来指定SurfaceViews的顺序。 - cody

2
我自己想出了解决办法。虽然SurfaceView是View的子类,但SurfaceView通过窗口显示的方式有点奇怪。基本上,画布实际上经过了SurfaceView,但在Z顺序上却在其后面。因此,必须使用surfaceview.setZOrderOnTop(true)对多个SurfaceView进行排序。
现在我只需要担心如何使GLSurfaceView透明。

-1
取自min3d,这应该可以使GLSurfaceView透明。
_glSurfaceView.setEGLConfigChooser(8,8,8,8, 16, 0); 
_glSurfaceView.getHolder().setFormat(PixelFormat.TRANSLUCENT);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接