Android 布局中的 SurfaceView

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10185624/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 02:47:29  来源:igfitidea点击:

SurfaceView in Layout

androidandroid-layoutlayoutsurfaceview

提问by akappel

So I've done a lot of searching but still can't seem to find the exact reason as to why my SurfaceView won't display. Here's a little background as to what I'm doing:

因此,我进行了大量搜索,但似乎仍然无法找到 SurfaceView 无法显示的确切原因。这里有一些关于我在做什么的背景:

I have a Linear Layout that is set Horizontally. It contains an ImageView, then a vertical Linear Layout, and finally another ImageView. In the vertical Linear Layout, there are essential three things: another ImageView at the top, an extended SurfaceView (called MagnetView) and an ImageView below that.

我有一个水平设置的线性布局。它包含一个 ImageView,然后是一个垂直的线性布局,最后是另一个 ImageView。在垂直线性布局中,有三个必不可少的东西:顶部的另一个 ImageView,扩展的 SurfaceView(称为 MagnetView)和下面的 ImageView。

Here's the xml:

这是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" />

Essentially, I want the MagnetView to show through (or punch a hole) where I put it in the Layout. But it does not display. In fact, the only time my SurfaceView displays is when I set the activity's setContentView() to the SurfaceView explicitly, canceling out everything else.

本质上,我希望 MagnetView 通过(或打孔)显示我在布局中放置它的位置。但它不显示。事实上,我的 SurfaceView 显示的唯一时间是当我将活动的 setContentView() 显式设置为 SurfaceView 时,取消其他所有内容。

Here is the actually 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();
}

Should I place the SurfaceView at the top of my layout xml? Are there more attributes I must set? Can I just overlay the SurfaceView over everything else, make it translucent and draw what I need? Any help would be greatly appreciated, as I cannot seem to grasp how SurfaceViews work. It seems they are apart of my View hierarchy, but then documentation tells me they are something different entirely.

我应该将 SurfaceView 放在布局 xml 的顶部吗?我必须设置更多属性吗?我可以将 SurfaceView 覆盖在其他所有内容上,使其半透明并绘制我需要的内容吗?任何帮助将不胜感激,因为我似乎无法理解 SurfaceViews 是如何工作的。似乎它们是我的视图层次结构的一部分,但是文档告诉我它们完全不同。

Thank you.

谢谢你。

EDIT 04/17/2012

编辑 04/17/2012

To offer a little more info: My xml UI Designer shows a big box in the middle for my extended SurfaceView class, called MagnetView. I've outlined it in red. (Stackoverflow won't allow me to post images yet)

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

UI Designer view(http://24.media.tumblr.com/tumblr_m2mmqvBNwW1qcreoco1_500.jpg) http://24.media.tumblr.com/tumblr_m2mmqvBNwW1qcreoco1_500.jpg

UI 设计器视图 (http://24.media.tumblr.com/tumblr_m2mmqvBNwW1qcreoco1_500.jpg) http://24.media.tumblr.com/tumblr_m2mmqvBNwW1qcreoco1_500.jpg

Here's the MagnetView (SurfaceView) class:

这是 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

}

}

回答by Chaitanya

I am just putting down the changes.

我只是放下更改。

  1. Replace surface view in the xml with LinearLayout.

        <LinearLayout 
           android:id="@+id/middleSurface"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
        />
    
  2. Get an instance of linear layout

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

  3. Add the surface view's instance to LinearLayout

    surface.addView(new MagnetView(this));

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

2,3 steps should be performed after setContentView(R.layout.main);

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

回答by Alexander Kulyakhtin

I would examine the layout in the Eclipse UI designer to see if everything is placed as you want to. Surface Views are just ordinary views in regards to layout.

我会检查 Eclipse UI 设计器中的布局,看看是否一切都按照您的意愿放置。表面视图只是关于布局的普通视图。

回答by Chaitanya

If I am not wrong, the way I perceived your query is: You want something to be displayed/rendered on top of the surface view along with the other view elements as you mentioned in the xml.

如果我没有错,我认为您的查询的方式是:您希望在表面视图之上显示/渲染某些内容以及您在 xml 中提到的其他视图元素。

If you want a view on top of surface view, you need to extend it(AFAIK there is no other way). Then you need to override the onDraw() method to display what all things you want on the surface view. You also need to get an object of SurfaceHolder which gets the canvas.

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

Here is a good link showing, putting an imageview on top of surface view: http://www.droidnova.com/playing-with-graphics-in-android-part-ii,160.html

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

回答by Chaitanya

  1. Remove the surface view from the xml and place a linearlayout in place of that and associate an id with it.
  2. Get an instance of linearlayout.
  3. add child view i.e., magnet view in this case to the linearlayout using

    addView()

  1. 从 xml 中删除表面视图并放置一个线性布局来代替它,并将一个 id 与其关联。
  2. 获取一个线性布局的实例。
  3. 添加子视图,即在这种情况下的磁铁视图到线性布局使用

    添加视图()

This solved the problem.

这解决了问题。

回答by PyChen

Have you set the background of the SurfaceView? I found that if you set the background of the SurfaceView, it will not display what you draw on the secondary thread.

你有没有设置SurfaceView的背景?我发现如果你设置SurfaceView的背景,它不会显示你在辅助线程上画的东西。

回答by Alv_quena

You could try this other way, move setContentView(R.layout.main);after super.onCreate(savedInstanceState);

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