【问题标题】:SurfaceView in Layout布局中的 SurfaceView
【发布时间】:2012-04-28 11:04:50
【问题描述】:

所以我进行了大量搜索,但似乎仍然无法找到 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 时,取消了其他所有内容。

这是实际的活动:

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 覆盖在其他所有内容上,使其半透明并绘制我需要的内容吗?任何帮助将不胜感激,因为我似乎无法掌握 SurfaceViews 的工作原理。似乎它们是我的视图层次结构的一部分,但是文档告诉我它们完全不同。

谢谢。

编辑 2012 年 4 月 17 日

提供更多信息: 我的 xml UI 设计器在中间为我的扩展 SurfaceView 类显示了一个大框,称为 MagnetView。我已经用红色勾勒了它。 (Stackoverflow 还不允许我发布图片)

UI 设计器视图(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

}

}

【问题讨论】:

    标签: android android-layout layout surfaceview


    【解决方案1】:

    我会检查 Eclipse UI 设计器中的布局,看看是否所有东西都按照您的意愿放置。表面视图只是布局方面的普通视图。

    【讨论】:

    • 我已经编辑了我的帖子以包含 UI 设计器的屏幕截图,其中我概述了 SurfaceView。它肯定在布局中,但它不会画出我想要的东西。我还发布了扩展的 SurfaceView 类(MagnetView)。它现在的功能是用黄色填充 Surface。
    • 你确定 surfaceCreated() 被调用并且你只是在它被调用后才开始绘图。您可以关注他们在 sdk 中的 LunarLander 示例
    • 我在Callback接口和surfaceCreated()中添加了(在OP中更新了)但是还是没有用。我的问题可能出在我在活动中设置内容视图的方式上吗?我是否将主 Activity 中的 SurfaceView 与我在 xml 中布局的 SurfaceView 正确链接?
    【解决方案2】:

    如果我没记错的话,我对您的查询的看法是:您希望某些内容与您在 xml 中提到的其他视图元素一起显示/渲染在表面视图之上。

    如果您想要在表面视图之上的视图,您需要扩展它(AFAIK 没有其他方法)。然后你需要重写 onDraw() 方法以在表面视图上显示你想要的所有东西。您还需要获取一个 SurfaceHolder 对象来获取画布。

    这是一个很好的链接显示,将图像视图放在表面视图的顶部: http://www.droidnova.com/playing-with-graphics-in-android-part-ii,160.html

    【讨论】:

    • 我更新了帖子以提供更多信息。有一个屏幕截图,显示了布局中的 SurfaceView。那是我要绘制的区域。 MagnetView (SurfaceView) 实现了 Runnable 以便能够在单独的线程上运行。
    • 所以你希望表面视图与其他布局元素视图一起出现......对吗?
    【解决方案3】:
    1. 从 xml 中删除表面视图,并放置一个线性布局来代替它,并将一个 id 与其关联。
    2. 获取一个线性布局实例。
    3. 使用添加子视图,即在这种情况下的磁铁视图到线性布局

      addView()

    这解决了问题。

    【讨论】:

    • 遗憾的是,它似乎并没有为我解决问题。根据您的指示,我更新了代码以反映我所做的事情。我错过了什么吗?
    • 如果可以的话,我将不胜感激。您能否将其添加到我最初问题的底部,以便我进行比较和对比?
    【解决方案4】:

    我只是放下更改。

    1. 用 LinearLayout 替换 xml 中的表面视图。

          <LinearLayout 
             android:id="@+id/middleSurface"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
          />
      
    2. 获取线性布局实例

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

    3. 将表面视图的实例添加到 LinearLayout

      surface.addView(new MagnetView(this));

    在setContentView(R.layout.main);之后应该执行2,3个步骤

    【讨论】:

    • 我不知道为什么它以前不起作用,但现在起作用了。感谢柴坦亚的帮助和耐心!
    【解决方案5】:

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

    【讨论】:

      【解决方案6】:

      你可以试试这个方法,把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);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-07-09
        • 2011-11-05
        • 2011-04-26
        • 2012-09-26
        • 2019-04-06
        • 1970-01-01
        相关资源
        最近更新 更多