我需要实施条形码扫描应用。具体的特点是我需要片段的预览显示,适合半个屏幕(或说250 dp)。因此,我使用this库及其ScannerFragment类来实现相机预览和条形码扫描。 问题是在纵向(我只需要此模式,而不是横向)模式相机预览被拉伸,扫描仪无法识别其中的条形码。它的横向模式工作正常。
我的布局文件:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:orientation="horizontal">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="top">
<fragment android:name="ua.xajker.inventarization.BarcodeScanActivity.ScannerFragment"
android:id="@+id/headlines_fragment"
android:layout_weight="1"
android:layout_width="fill_parent"
android:layout_height="250dp"/>
</FrameLayout>
</LinearLayout>
My Fragment课程:
public class ScannerFragment extends Fragment implements ZXingScannerView.ResultHandler {
private ZXingScannerView mScannerView;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mScannerView = new ZXingScannerView(getActivity());
return mScannerView;
}
@Override
public void onResume() {
super.onResume();
mScannerView.setResultHandler(this);
mScannerView.startCamera();
mScannerView.setAutoFocus(false);
}
@Override
public void handleResult(Result rawResult) {
Toast.makeText(getActivity(), "Contents = " + rawResult.getText() +
", Format = " + rawResult.getBarcodeFormat().toString(), Toast.LENGTH_SHORT).show();
mScannerView.startCamera();
}
@Override
public void onPause() {
super.onPause();
mScannerView.stopCamera();
}
}
我发现我们可以替换lib的ZXingScannerView.java类,我们可以用Camera对象操作,也许它会有所帮助吗?
public class ZXingScannerView extends BarcodeScannerView {
public interface ResultHandler {
public void handleResult(Result rawResult);
}
private MultiFormatReader mMultiFormatReader;
public static final List<BarcodeFormat> ALL_FORMATS = new ArrayList<BarcodeFormat>();
private List<BarcodeFormat> mFormats;
private ResultHandler mResultHandler;
static {
ALL_FORMATS.add(BarcodeFormat.UPC_A);
ALL_FORMATS.add(BarcodeFormat.UPC_E);
ALL_FORMATS.add(BarcodeFormat.EAN_13);
ALL_FORMATS.add(BarcodeFormat.EAN_8);
ALL_FORMATS.add(BarcodeFormat.RSS_14);
ALL_FORMATS.add(BarcodeFormat.CODE_39);
ALL_FORMATS.add(BarcodeFormat.CODE_93);
ALL_FORMATS.add(BarcodeFormat.CODE_128);
ALL_FORMATS.add(BarcodeFormat.ITF);
ALL_FORMATS.add(BarcodeFormat.CODABAR);
ALL_FORMATS.add(BarcodeFormat.QR_CODE);
ALL_FORMATS.add(BarcodeFormat.DATA_MATRIX);
ALL_FORMATS.add(BarcodeFormat.PDF_417);
}
public ZXingScannerView(Context context) {
super(context);
initMultiFormatReader();
}
public ZXingScannerView(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
initMultiFormatReader();
}
public void setFormats(List<BarcodeFormat> formats) {
mFormats = formats;
initMultiFormatReader();
}
public void setResultHandler(ResultHandler resultHandler) {
mResultHandler = resultHandler;
}
public Collection<BarcodeFormat> getFormats() {
if(mFormats == null) {
return ALL_FORMATS;
}
return mFormats;
}
private void initMultiFormatReader() {
Map<DecodeHintType,Object> hints = new EnumMap<DecodeHintType,Object>(DecodeHintType.class);
hints.put(DecodeHintType.POSSIBLE_FORMATS, getFormats());
mMultiFormatReader = new MultiFormatReader();
mMultiFormatReader.setHints(hints);
}
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
Camera.Parameters parameters = camera.getParameters();
Camera.Size size = parameters.getPreviewSize();
int width = size.width;
int height = size.height;
if(DisplayUtils.getScreenOrientation(getContext()) == Configuration.ORIENTATION_PORTRAIT) {
byte[] rotatedData = new byte[data.length];
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++)
rotatedData[x * height + height - y - 1] = data[x + y * width];
}
int tmp = width;
width = height;
height = tmp;
data = rotatedData;
}
Result rawResult = null;
PlanarYUVLuminanceSource source = buildLuminanceSource(data, width, height);
if(source != null) {
BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
try {
rawResult = mMultiFormatReader.decodeWithState(bitmap);
} catch (ReaderException re) {
// continue
} catch (NullPointerException npe) {
// This is terrible
} catch (ArrayIndexOutOfBoundsException aoe) {
} finally {
mMultiFormatReader.reset();
}
}
if (rawResult != null) {
stopCamera();
if(mResultHandler != null) {
mResultHandler.handleResult(rawResult);
}
} else {
camera.setOneShotPreviewCallback(this);
}
}
public PlanarYUVLuminanceSource buildLuminanceSource(byte[] data, int width, int height) {
Rect rect = getFramingRectInPreview(width, height);
if (rect == null) {
return null;
}
// Go ahead and assume it's YUV rather than die.
PlanarYUVLuminanceSource source = null;
try {
source = new PlanarYUVLuminanceSource(data, width, height, rect.left, rect.top,
rect.width(), rect.height(), false);
} catch(Exception e) {
}
return source;
}
}
发布照片我没有声誉,因此您可以看到 here 的截图。
非常感谢任何建议。