我有一个带开始按钮的简单屏幕。按下“开始”按钮后,我想转到带有SurfaceView的新屏幕以显示摄像机。
一切正常,但相机需要一段时间才能加载,这给了我一个黑屏。 我想加载新的布局。并且在装载后启动相机......
因此,我在后台线程中完成所有相机加载,但仍然,我得到一个黑屏...... 这是我的布局:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout android:id="@+id/RelativeLayout1"
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@drawable/blue_bg">
<SurfaceView
android:id="@+id/surface_camera"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_marginLeft="25dp"
android:layout_marginRight="25dp"
android:layout_below="@id/scan_header"
android:layout_above="@id/scan_footer">
</SurfaceView>
</RelativeLayout>
以下是我的Activity中的方法,它加载了新视图:
private void setContent()
{
setContentView(R.layout.scan)
Thread t = new Thread()
{
public void run()
{
final SurfaceView mSurfaceView = (SurfaceView)findViewById(R.id.surface_camera);
final SurfaceHolder mSurfaceHolder = mSurfaceView.getHolder();
try
{
cameraView = new CameraView();
mSurfaceHolder.addCallback(cameraView);
cameraView.setPictureListener(SunpluggedActivity.this);
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
} catch(Exception e)
{
Log.d(TAG, "Another exception");
e.printStackTrace();
}
}
};
t.start();
}
为什么新的布局没有显示,直到线程完成加载相机?
编辑:我已经尝试在Thread内部的Thread.sleep(200)睡了一段时间......当我这样做时,新的布局会被显示出来,但相机永远不会启动......答案 0 :(得分:22)
好吧,问题是我在xml布局中使用了SurfaceView。 你打电话的那一刻:setContentView(your_layout) - &gt; XML文件被夸大了。 这意味着,SurfaceView也会膨胀。这再次意味着调用SurfaceView onSurfaceCreated方法,触发打开相机等。
因此,整个过程需要一段时间,因此,您之前的活动(例如,使用SurfaceView启动活动的活动)似乎没有响应......
我在BG线程中创建CameraView的解决方案解决了无响应问题。但未能在SurfaceView中显示Camera输出。
解决方案是从xml中删除SurfaceView。这将立即启动您的活动(因为SurfaceView&amp; Camera未实例化)。 加载新的“活动”布局后,可以以编程方式将新的SurfaceView添加到屏幕上。当然,这也需要时间,但您的UI会快速切换到新活动,并且您可以在SurfaceView和Camera加载时显示加载程序!
SO:从XML中删除SURFACEVIEW - &gt;在程序上添加它: 启动活动:
public class Launch extends Activity implements OnClickListener
{
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button btn = (Button)findViewById(R.id.button1);
btn.setOnClickListener(this);
}
@Override
public void onClick(View v) {
Intent intent = new Intent(Launch.this, SurfaceTestActivity.class);
startActivity(intent);
}
}
Main.xml(只是一个启动新活动的按钮)
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout android:id="@+id/RelativeLayout1"
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#ff6600">
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button" />
</RelativeLayout>
这是第二个活动(包含SurfaceView)
public class SurfaceTestActivity extends Activity {
private Context mContext;
private CameraView cameraView;
private Handler mHandler = new Handler();
private final Runnable mLoadCamera = new Runnable()
{
public void run()
{
startCamera();
}
};
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContent();
mContext = getApplicationContext();
}
private void startCamera()
{
RelativeLayout rl = (RelativeLayout)findViewById(R.id.surface_camera);
SurfaceView surfaceView = new SurfaceView(mContext);
final SurfaceHolder mSurfaceHolder = surfaceView.getHolder();
try
{
cameraView = new CameraView();
mSurfaceHolder.addCallback(cameraView);
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
} catch(Exception e)
{
Log.d("debug", "Another exception");
e.printStackTrace();
}
if(rl != null && surfaceView != null)
rl.addView(surfaceView);
}
private void setContent()
{
setContentView(R.layout.scan);
// Post the Runnable with a Slight delay -> than your layout will be
// shown. Without the delay -> your UI will feel inresponsive
mHandler.postDelayed(mLoadCamera, 100);
}
}
这是第二个Activity的布局(没有SURFACEVIEW)
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout android:id="@+id/RelativeLayout1"
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#ff6600">
<RelativeLayout
android:id="@+id/header"
android:layout_width="fill_parent" android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:text="Explanation Txt"></TextView>
</RelativeLayout>
<RelativeLayout
android:id="@+id/footer"
android:layout_width="fill_parent" android:layout_height="wrap_content"
android:layout_alignParentBottom="true">
<TextView
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:text="Explanation Txt"></TextView>
</RelativeLayout>
<RelativeLayout
android:id="@+id/surface_camera"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:layout_above="@+id/footer"
android:layout_below="@+id/header"
android:background="#ff0066">
</RelativeLayout>
</RelativeLayout>
最后,要完成答案,这里是CameraView()的代码。打开相机并显示内容真的只是一个简单的实现:
public class CameraView implements SurfaceHolder.Callback{
// Variables
private Camera mCamera = null;
private boolean mPreviewRunning = false;
private boolean mProcessing = false;
private int mWidth = 0;
private int mHeight = 0;
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height)
{
if(mPreviewRunning )
{
mCamera.stopPreview();
}
// Store width and height
mWidth = width;
mHeight = height;
// Set camera parameters
Camera.Parameters p = mCamera.getParameters();
mCamera.setParameters(p);
if(android.os.Build.VERSION.SDK_INT >= 8)
{ // If API >= 8 -> rotate display...
mCamera.setDisplayOrientation(90);
}
try
{
mCamera.setPreviewDisplay(holder);
} catch(IOException e)
{
e.printStackTrace();
}
mCamera.startPreview();
mPreviewRunning = true;
}
@Override
public void surfaceCreated(final SurfaceHolder holder)
{
try {
mCamera = Camera.open();
mCamera.setPreviewDisplay(holder);
} catch (IOException e)
{
mCamera.release();
mCamera = null;
e.printStackTrace();
}
}
@Override
public void surfaceDestroyed(SurfaceHolder holder)
{
if(mCamera != null)
{
mCamera.setPreviewCallback(null);
mCamera.stopPreview();
mCamera.setPreviewCallback(null);
mPreviewRunning = false;
mCamera.release();
mCamera = null;
}
}
}