1

我想将 zbar 扫描仪的相机预览放置到我现有的布局中,但是我试图放置它的地方总是保持黑色并且不会启动相机来读取 qrs。如果我不使用自定义布局,而是示例中的那个(它在所有新活动中启动扫描仪并占用所有屏幕尺寸)一切都很好。这意味着我对权限或类似的东西没有问题。这是我现在使用的代码:

import net.sourceforge.zbar.Config;
import net.sourceforge.zbar.Image;
import net.sourceforge.zbar.ImageScanner;
import net.sourceforge.zbar.Symbol;
import net.sourceforge.zbar.SymbolSet;

import com.dm.zbar.android.scanner.CameraPreview;
import com.dm.zbar.android.scanner.ZBarConstants;
import com.dm.zbar.android.scanner.ZBarScannerActivity;

import android.os.Bundle;
import android.os.Handler;
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.hardware.Camera;
import android.text.TextUtils;
import android.view.Menu;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import android.widget.TextView;
import android.widget.Toast;

public class PointGivingActivity extends Activity implements Camera.PreviewCallback, ZBarConstants{

    private static final int ZBAR_SCANNER_REQUEST = 0;
    private static final int ZBAR_QR_SCANNER_REQUEST = 1;
    private static final String TAG = "ZBarScannerActivity";
    private CameraPreview mPreview;
    private Camera mCamera;
    private ImageScanner mScanner;
    private Handler mAutoFocusHandler;
    private boolean mPreviewing = true;
    static {
        System.loadLibrary("iconv");
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (!isCameraAvailable()) {
            cancelRequest();
            return;
        }
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
        setContentView(R.layout.activity_point_giving2);
        mAutoFocusHandler = new Handler();
        setupScanner();


        LinearLayout zbarLayout = (LinearLayout) findViewById(R.id.zbar_layout_area);

        mPreview = new CameraPreview(zbarLayout.getContext(), this, autoFocusCB);
        mPreview.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
        zbarLayout.addView(mPreview);
    }

    public void launchScanner(View v) {
        if (isCameraAvailable()) {
            Intent intent = new Intent(this, ZBarScannerActivity.class);
            startActivityForResult(intent, ZBAR_SCANNER_REQUEST);
        } else {
            Toast.makeText(this, "Rear Facing Camera Unavailable",
                    Toast.LENGTH_SHORT).show();
        }
    }
    public void launchScanner() {
        if (isCameraAvailable()) {
            Intent intent = new Intent(this, ZBarScannerActivity.class);
            startActivityForResult(intent, ZBAR_SCANNER_REQUEST);
        } else {
            Toast.makeText(this, "Rear Facing Camera Unavailable",
                    Toast.LENGTH_SHORT).show();
        }
    }
    public void launchQRScanner(View v) {
        if (isCameraAvailable()) {
            Intent intent = new Intent(this, ZBarScannerActivity.class);
            intent.putExtra(ZBarConstants.SCAN_MODES,
                    new int[] { Symbol.QRCODE });
            startActivityForResult(intent, ZBAR_SCANNER_REQUEST);
        } else {
            Toast.makeText(this, "Rear Facing Camera Unavailable",
                    Toast.LENGTH_SHORT).show();
        }
    }

    public void MyMethod(View v) {
        Intent intent = new Intent(this, ZBarScannerActivity.class);
        startActivityForResult(intent, ZBAR_SCANNER_REQUEST);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == RESULT_OK) {
            TextView someText = (TextView) findViewById(R.id.givePointtv1);
            someText.setText(data.getStringExtra(ZBarConstants.SCAN_RESULT));
            // Toast.makeText(this, "Scan Result = " +
            // data.getStringExtra(ZBarConstants.SCAN_RESULT),
            // Toast.LENGTH_SHORT).show();
            // Toast.makeText(this, "Scan Result Type = " +
            // data.getStringExtra(ZBarConstants.SCAN_RESULT_TYPE),
            // Toast.LENGTH_SHORT).show();

        } else if (resultCode == RESULT_CANCELED) {
            // Toast.makeText(this, "Camera unavailable",
            // Toast.LENGTH_SHORT).show();
        }
    }

    public boolean isCameraAvailable() {
        PackageManager pm = getPackageManager();
        return pm.hasSystemFeature(PackageManager.FEATURE_CAMERA);
    }

    public void cancelRequest() {
        Intent dataIntent = new Intent();
        dataIntent.putExtra(ERROR_INFO, "Camera unavailable");
        setResult(Activity.RESULT_CANCELED, dataIntent);
        finish();
    }

    public void onPreviewFrame(byte[] data, Camera camera) {
        Camera.Parameters parameters = camera.getParameters();
        Camera.Size size = parameters.getPreviewSize();

        Image barcode = new Image(size.width, size.height, "Y800");
        barcode.setData(data);

        int result = mScanner.scanImage(barcode);

        if (result != 0) {
            mCamera.cancelAutoFocus();
            mCamera.setPreviewCallback(null);
            mCamera.stopPreview();
            mPreviewing = false;
            SymbolSet syms = mScanner.getResults();
            for (Symbol sym : syms) {
                String symData = sym.getData();
                if (!TextUtils.isEmpty(symData)) {
                    Intent dataIntent = new Intent();
                    dataIntent.putExtra(SCAN_RESULT, symData);
                    dataIntent.putExtra(SCAN_RESULT_TYPE, sym.getType());
                    setResult(Activity.RESULT_OK, dataIntent);
                    finish();
                    break;
                }
            }
        }
    }
    private Runnable doAutoFocus = new Runnable() {
        public void run() {
            if(mCamera != null && mPreviewing) {
                mCamera.autoFocus(autoFocusCB);
            }
        }
    };

    // Mimic continuous auto-focusing
    Camera.AutoFocusCallback autoFocusCB = new Camera.AutoFocusCallback() {
        public void onAutoFocus(boolean success, Camera camera) {
            mAutoFocusHandler.postDelayed(doAutoFocus, 1000);
        }
    };
    public void setupScanner() {
        mScanner = new ImageScanner();
        mScanner.setConfig(0, Config.X_DENSITY, 3);
        mScanner.setConfig(0, Config.Y_DENSITY, 3);

        int[] symbols = getIntent().getIntArrayExtra(SCAN_MODES);
        if (symbols != null) {
            mScanner.setConfig(Symbol.NONE, Config.ENABLE, 0);
            for (int symbol : symbols) {
                mScanner.setConfig(symbol, Config.ENABLE, 1);
            }
        }
    }
}

我很确定问题出在某个地方:

LinearLayout zbarLayout = (LinearLayout) findViewById(R.id.zbar_layout_area);

mPreview = new CameraPreview(zbarLayout.getContext(), this, autoFocusCB);
mPreview.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
zbarLayout.addView(mPreview);

但无法弄清楚如何让它按我想要的方式工作。

如果需要,这是我的 xml 文件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/pointgivingll1"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#f1f1f1"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:weightSum="10" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:orientation="horizontal"
        android:weightSum="8" >

        <Button
            android:id="@+id/givePointMenuBut"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:visibility="invisible" />

        <TextView
            android:id="@+id/givePointtv1"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="6"
            android:gravity="center"
            android:text="@string/pointGiving"
            android:textColor="@android:color/black"
            android:textSize="22sp" />

        <Button
            android:id="@+id/givePointMenuBut"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_marginBottom="10dp"
            android:layout_marginTop="10dp"
            android:layout_weight="1"
            android:gravity="center"
            android:text="@string/ruchno"
            android:textSize="10sp" />
    </LinearLayout>

    <LinearLayout
        android:gravity="center"
        android:layout_weight="9"
        android:id="@+id/zbar_layout_area"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:orientation="vertical" >
    </LinearLayout>


</LinearLayout>
4

1 回答 1

0

我遇到了同样的问题,并通过以编程方式向 FrameLayout 添加/删除视图来做了一些技巧。我在这里找到了这个解决方案:

使用 zbar 为 Android 自定义相机视图

这是我的 activity_qr_code_reader.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="@android:color/black" >

    <FrameLayout
        android:id="@+id/flytCamera"
        android:layout_width="match_parent"
        android:layout_height="0dip"
        android:layout_weight="1" >

        <ImageView
            android:id="@+id/ivScanner"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:src="@drawable/im_qr_scan"/>

    </FrameLayout>

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom"
        android:padding="10dp"
        android:textColor="@android:color/white"
        android:textSize="16sp"
        android:background="@color/transparent_black"
        android:text="@string/qr_code_reading"/>
</LinearLayout>

到目前为止,我在底部有一个信息文本视图和一个 QR 码阅读框图像(只有 4 个白色角)。我想将相机预览放在整个 FrameLayout 中,但最终只将它放在中心。这是代码。它并不完美,但至少更加用户友好。

public class QRCodeReaderActivity extends ZBarScannerActivity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.layout_qr_code_reader);
        FrameLayout flytCamera = (FrameLayout)     findViewById(R.id.flytCamera);
        ImageView ivScanner = (ImageView) findViewById(R.id.ivScanner);

        flytCamera.addView(mPreview);
        flytCamera.removeView(ivScanner);
        flytCamera.addView(ivScanner);
    }
}

顺便说一句,我希望我的 ZBarScanner 是纵向的,所以我还强制相机旋转 90 度。 http://developer.android.com/reference/android/hardware/Camera.html#setDisplayOrientation(int)

   @Override
    protected void onResume() {
        super.onResume();
        setCameraDisplayOrientation(this, Camera.CameraInfo.CAMERA_FACING_BACK, mCamera);
    }

    public static void setCameraDisplayOrientation(Activity activity,
                                                   int cameraId, android.hardware.Camera camera) {
        android.hardware.Camera.CameraInfo info =
                new android.hardware.Camera.CameraInfo();
        android.hardware.Camera.getCameraInfo(cameraId, info);
        int rotation = activity.getWindowManager().getDefaultDisplay()
                .getRotation();
        int degrees = 0;
        switch (rotation) {
            case Surface.ROTATION_0: degrees = 0; break;
            case Surface.ROTATION_90: degrees = 90; break;
            case Surface.ROTATION_180: degrees = 180; break;
            case Surface.ROTATION_270: degrees = 270; break;
        }

        int result;
        if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            result = (info.orientation + degrees) % 360;
            result = (360 - result) % 360;  // compensate the mirror
        } else {  // back-facing
            result = (info.orientation - degrees + 360) % 360;
        }
        camera.setDisplayOrientation(result);
    }
于 2015-02-03T21:16:05.770 回答