布局中的SurfaceView

9

我搜索了很多,但似乎仍然找不到我的SurfaceView无法显示的确切原因。这是我正在做的一些背景:

我有一个水平设置的线性布局。其中包含一个ImageView,然后是垂直线性布局,最后是另一个ImageView。在垂直线性布局中,基本上有三件事情:顶部有另一个ImageView,下面有一个扩展的SurfaceView(称为MagnetView)和一个下面的ImageView。

这是xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" >

 <!-- Left Magnetrak -->

 <ImageView
    android:layout_width="wrap_content"
    android:layout_height="fill_parent"
    android:src="@drawable/vectorparts_01"
    android:adjustViewBounds="true" />

<!-- Middle Linear Layout -->        
<LinearLayout 
    android:layout_width="0dip"
    android:layout_height="fill_parent"
    android:orientation="vertical"
    android:layout_weight="1">

    <!-- Top Bar with Lifes and Score counter -->
    <RelativeLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:adjustViewBounds="true">

    <ImageView
    android:adjustViewBounds="true"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:src="@drawable/vectorparts_22"/>

    <!-- Score counter -->
    <TextView
    android:id="@+id/myImageViewText"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentRight="true"
    android:layout_marginRight="10dp"
    android:layout_marginTop="5dp"
    android:gravity="center"
    android:text="000000000000"
    android:textColor="#000000" />

    <!-- Life1 -->
     <ImageView
        android:id = "@+id/life1"
        android:adjustViewBounds="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/vectorparts_13" 
        android:layout_alignParentLeft="true"
        android:layout_marginLeft="5dp"
        android:layout_marginTop="1dp"
        android:gravity="center" />

     <!-- Life2 -->
     <ImageView
        android:id = "@+id/life2"
        android:adjustViewBounds="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/vectorparts_13" 
        android:layout_toRightOf="@id/life1"
        android:layout_marginTop="1dp"
        android:layout_marginLeft="1dp"
        android:gravity="center" />

     <!-- Life3 -->
     <ImageView
        android:id = "@+id/life3"
        android:adjustViewBounds="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/vectorparts_13" 
        android:layout_toRightOf="@id/life2"
        android:layout_marginTop="1dp"
        android:layout_marginLeft="1dp"
        android:gravity="center" />

    </RelativeLayout>

    <!-- SurfaceView -->
    <LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:id="@+id/middlesurface">

    </LinearLayout>

     <!-- Bottom Bar -->   
    <RelativeLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:adjustViewBounds="true"> 

    <ImageView
    android:adjustViewBounds="true"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:src="@drawable/vectorparts_02"/>


    </RelativeLayout>


</LinearLayout>

<!-- Right Magnetrak -->
   <ImageView
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:src="@drawable/vectorparts_01"
android:adjustViewBounds="true" />

基本上,我希望 MagnetView 在布局中的位置能够透过或打洞。但它并没有显示出来。事实上,唯一一次我的 SurfaceView 显示出来的时候是当我将活动的 setContentView() 显式地设置为 SurfaceView 时,取消了其他所有内容。
以下是实际的 Activity:
public class Magnetraks extends Activity {

MagnetView midSurf;

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    midSurf = new MagnetView(this);
    LinearLayout midLL = new LinearLayout(this);

    midLL.findViewById(R.id.middlesurface);
    midLL.addView(midSurf);

    setContentView(R.layout.main);

    //Debugging purposes: run to see if middleSurface view is showing up when on its own.
    //setContentView(midSurf);


}

@Override
protected void onResume() {
 // TODO Auto-generated method stub
 super.onResume();
 midSurf.resume();
}

@Override
protected void onPause() {
 // TODO Auto-generated method stub
 super.onPause();
 midSurf.pause();
}

我应该将SurfaceView放在布局xml的顶部吗?我需要设置更多属性吗? 我是否可以将SurfaceView覆盖在其他所有内容上,使其半透明并绘制所需内容?任何帮助都将不胜感激,因为我似乎无法理解SurfaceView的工作原理。它们似乎是我的View层次结构的一部分,但文档告诉我它们完全不同。
谢谢。
编辑04/17/2012
提供更多信息: 我的xml UI设计器显示一个大框中间是我扩展的SurfaceView类,称为MagnetView。我已经用红色勾勒出来了。(Stackoverflow还不允许我发布图片)
UI Designer视图(http://24.media.tumblr.com/tumblr_m2mmqvBNwW1qcreoco1_500.jpg) http://24.media.tumblr.com/tumblr_m2mmqvBNwW1qcreoco1_500.jpg 这是MagnetView(SurfaceView)类:
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.PixelFormat;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class MagnetView extends SurfaceView implements Runnable, SurfaceHolder.Callback{
Thread mThread;
SurfaceHolder mSurfaceHolder;
volatile boolean running = false;

//Creates new surface view as well as a new surfaceholder, which allows access to the surface
public MagnetView (Context context){
    super(context);

    mSurfaceHolder = getHolder();
            mSurfaceHolder.addCallback(this);
    //this.setZOrderOnTop(true);
    //getHolder().setFormat(PixelFormat.TRANSLUCENT);


}

public void resume(){
    running = true;
    mThread = new Thread(this);
    mThread.start();
}

public void pause(){
       boolean retry = true;
       running = false;
       while(retry){
        try {
         mThread.join();
         retry = false;
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
       }
}

@Override
public void run() {
  // TODO Auto-generated method stub
    while(running){
        if(mSurfaceHolder.getSurface().isValid()){
            Canvas canvas = mSurfaceHolder.lockCanvas();
            //... actual drawing on canvas

            canvas.drawARGB(100, 255, 255, 80);

            mSurfaceHolder.unlockCanvasAndPost(canvas);
        }
    }
}


@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
        int height) {
    // TODO Auto-generated method stub

}

@Override
public void surfaceCreated(SurfaceHolder holder) {
    // TODO Auto-generated method stub
    this.resume();

}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
    // TODO Auto-generated method stub

}

}
6个回答

17

我只是记录下更改。

  1. 将xml中的SurfaceView替换为LinearLayout。

    <LinearLayout 
       android:id="@+id/middleSurface"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
    />
  • 获取LinearLayout的实例

    LinearLayout surface = (LinearLayout)findViewById(R.id.surface);

  • 将SurfaceView的实例添加到LinearLayout中

    surface.addView(new MagnetView(this));

  • 在setContentView(R.layout.main)之后执行2、3步骤。


    我不知道为什么之前它没能工作,但现在它可以了。感谢Chaitanya的帮助和耐心! - akappel

    0
    你设置了SurfaceView的背景吗?我发现如果你设置了SurfaceView的背景,它不会显示在次线程上绘制的内容。

    0

    如果我没理解错的话,您的问题是:您想要在xml中提到的其他视图元素的顶部显示/渲染某些内容。

    如果您想要在surface view上方显示视图,则需要扩展它(据我所知没有其他方法)。然后,您需要覆盖onDraw()方法以显示您想要在surface view上显示的所有内容。您还需要获取SurfaceHolder对象,该对象获取画布。

    这里有一个很好的链接,显示如何将imageview放在surface view的顶部: http://www.droidnova.com/playing-with-graphics-in-android-part-ii,160.html


    我已经更新了帖子,提供了更多的信息。有一张截图,显示了布局中的SurfaceView。那是我想要绘制的区域。MagnetView(SurfaceView)实现了Runnable以便能够在单独的线程上运行。 - akappel
    所以您希望Surface View与其他布局元素视图一起显示,对吗? - Chaitanya

    0
    1. 从xml中删除surface view,并将一个linearlayout放在它的位置,并为其关联一个id。
    2. 获取linearlayout的实例。
    3. 使用addView()将子视图,即磁铁视图,在此情况下添加到linearlayout中

    这解决了问题。


    很遗憾,对我来说似乎并没有解决问题。我根据你的指示更新了代码以反映我所做的更改。我有什么遗漏吗? - akappel
    如果您能这样做,我将不胜感激。您可以把它添加到我的原始问题底部,这样我就可以进行比较和对照了吗? - akappel

    0

    我会在Eclipse UI设计师中检查布局,看是否所有东西都放置在您想要的位置。Surface Views在布局方面只是普通视图。


    我已经编辑了我的帖子,包括UI设计师的截图,在那里我勾画了SurfaceView。它肯定在布局中,但它不会绘制我想要的内容。我还发布了扩展的SurfaceView类(MagnetView)。它目前的功能是用黄色填充Surface。 - akappel
    你确定surfaceCreated()被调用了,并且你是在它被调用后才开始绘制的吗?你可以参考sdk中的LunarLander示例。 - Alexander Kulyakhtin
    我已经添加了回调接口和surfaceCreated()(在原始帖子中更新),但仍然无济于事。我的问题可能出在我在活动中设置Content View的方式上吗?我是否正确地将主Activity中的SurfaceView与我在xml中布置的SurfaceView链接起来了? - akappel

    0
    你可以尝试另一种方法,将 setContentView(R.layout.main); 移动到 super.onCreate(savedInstanceState); 之后。
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    midSurf = new MagnetView(this);
    LinearLayout midLL = new LinearLayout(this);
    
    midLL.findViewById(R.id.middlesurface);
    midLL.addView(midSurf);
    

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