叠加图像按钮不可见 (Android)

Overlay image button is invisible (Android)

我想在我的相机应用程序的相机预览顶部叠加一个图像按钮,这样相机预览就可以占据整个屏幕,用户仍然可以拍照。

我的activity_camera.xml是:

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

    <FrameLayout
        android:id="@+id/preview"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">

        <ImageButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/camera_photo"
            android:id="@+id/take_photoimageButton"
            android:visibility="visible"
            android:layout_gravity="center_horizontal|bottom" />
    </FrameLayout>

</LinearLayout>

有没有一种方法可以编辑布局,以便在相机预览时按钮可见?

编辑 - 这是我的预览 class:

class Preview extends SurfaceView implements SurfaceHolder.Callback {
    private static final String TAG = "Preview";

    SurfaceHolder mHolder;
    public Camera camera;

    Preview(Context context, Camera inCamera) {
        super(context);
        camera = inCamera;

        // Install a SurfaceHolder.Callback so we get notified when the
        // underlying surface is created and destroyed.
        mHolder = getHolder();
        mHolder.addCallback(this);

        // deprecated setting, but required on Android versions prior to 3.0
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }

    public void surfaceCreated(SurfaceHolder holder) {
        try {
            camera.setPreviewDisplay(holder);
            camera.startPreview();
        } catch (IOException e) {
            Log.d(TAG, "Error setting camera preview: " + e.getMessage());
        }

    }

    public void OLDsurfaceCreated(SurfaceHolder holder) {
        // The Surface has been created, acquire the camera and tell it where
        // to draw.
       // camera = Camera.open();
        camera.setDisplayOrientation(90);
        try {
            camera.setPreviewDisplay(holder);

//            camera.setPreviewCallback(new PreviewCallback() {
//
//                public void onPreviewFrame(byte[] data, Camera arg1) {
//                    FileOutputStream outStream = null;
//                    try {
//                        outStream = new FileOutputStream(String.format(
//                                "/sdcard/%d.jpg", System.currentTimeMillis()));
//                        outStream.write(data);
//                        outStream.close();
//                        Log.d(TAG, "onPreviewFrame - wrote bytes: "
//                                + data.length);
//                    } catch (FileNotFoundException e) {
//                        e.printStackTrace();
//                    } catch (IOException e) {
//                        e.printStackTrace();
//                    } finally {
//                    }
//                    Preview.this.invalidate();
//                }
//            });
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void surfaceDestroyed(SurfaceHolder holder) {
        // Surface will be destroyed when we return, so stop the preview.
        // Because the CameraDevice object is not a shared resource, it's very
        // important to release it when the activity is paused.
        camera.stopPreview();
        camera.release();

    }

    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
        // If your preview can change or rotate, take care of those events here.
        // Make sure to stop the preview before resizing or reformatting it.

        if (mHolder.getSurface() == null){
            // preview surface does not exist
            return;
        }

        // stop preview before making changes
        try {
            camera.stopPreview();
        } catch (Exception e){
            // ignore: tried to stop a non-existent preview
        }

        // set preview size and make any resize, rotate or
        // reformatting changes here

        // start preview with new settings
        try {
            camera.setPreviewDisplay(mHolder);
            camera.startPreview();

        } catch (Exception e){
            Log.d(TAG, "Error starting camera preview: " + e.getMessage());
        }
    }

    public void OLDsurfaceChanged(SurfaceHolder holder, int format, int w, int h) {
        // Now that the size is known, set up the camera parameters and begin
        // the preview.
        Camera.Parameters parameters = camera.getParameters();
        //parameters.setPreviewSize(w, h);
        //camera.setParameters(parameters);
        List<Camera.Size> sizes = parameters.getSupportedPreviewSizes();
        Camera.Size cs = sizes.get(0);
        parameters.setPreviewSize(cs.width, cs.height);
        //parameters.setRotation(90);
        camera.setParameters(parameters);
        camera.startPreview();
    }

    @Override
    public void draw(Canvas canvas) {
        super.draw(canvas);
        Paint p = new Paint(Color.RED);
        Log.d(TAG, "draw");
        canvas.drawText("PREVIEW", canvas.getWidth() / 2,
                canvas.getHeight() / 2, p);
    }
}

假设您在代码中为预览创建了一个 SurfaceView,并使用 addView() 将其添加到预览 FrameLayout,将您的布局更改为:

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

    <FrameLayout
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">

        <FrameLayout
            android:id="@+id/preview"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent">

            <!-- Empty layout where SurfaceView will be placed in code-->

        </FrameLayout>

        <ImageButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/camera_photo"
            android:id="@+id/take_photoimageButton"
            android:visibility="visible"
            android:layout_gravity="center_horizontal|bottom" />

    </FrameLayout>

</LinearLayout>

就 z 顺序而言,布局中后面声明的视图绘制在前面声明的视图之上,代码中添加的视图绘制在顶部,就好像它们已添加到布局的末尾一样(除非您指定一个索引)。放置一个空布局以添加 SurfaceView 以允许它在 ImageButton 下绘制。

或者您可以尝试使用索引 0 调用 addView(),但是问题是询问如何在布局中实现此目的 XML。

除非出于某些其他原因需要使用 LinearLayout,否则您可以去掉它并使外部 FrameLayout 成为顶级 ViewGroup。