如何为 ZXing Scanner 创建和实现 Android CustomOverlay? [英] How to create and implement a Android CustomOverlay for ZXing Scanner?
问题描述
我正在为我的 Xamarin.Forms 项目使用 ZXing 条形码扫描仪插件.根据一些帖子,我需要为 ZXing 扫描仪使用自定义叠加层才能有取消按钮.但我不熟悉 Xamarin.Forms 项目中的 Android 开发.
到目前为止,我知道一个扫描器(ZXing 插件的 MobileBarcodeScanner)接受一个 Android.Views.View 作为覆盖来替换默认的扫描页面视图.
public async Task扫描异步(){MobileBarcodeScanner 扫描仪 = new MobileBarcodeScanner();扫描仪.UseCustomOverlay = true;扫描仪.CustomOverlay = ???????;var scanResult = 等待scanner.Scan();如果(扫描结果!= null){ 返回 scanResult.Text;}返回空;}
但我不知道如何创建视图页面(以 XML 设计或以编程方式)并将其设置为scanner.CustomOverlay.
我不确定是否可以将常见的 Android 视图用于扫描仪,任何详细的参考资料都会非常有用.
谢谢.
如果要自定义叠加层,则必须为每个平台创建自己的视图.您可以像这样自定义叠加层(创建一个名为 ZxingOverlayView
的自定义叠加层,将其设置为 scanner.CustomOverlay
):
var scanner = new ZXing.MobileMobileBarcodeScanner();扫描仪.UseCustomOverlay = true;myCustomOverlayInstance = new ZxingOverlayView(this,scanner);扫描仪.CustomOverlay = myCustomOverlayInstance;
ZxingOverlayView
应该继承 view
然后将您的控件添加到自定义视图中.您可以查看有关此链接的详细信息.
这是一个很好的简单代码.你可以参考一下.https://github.com/Wenfengcheng/ZXing.Sample_Xamarin
I'm using ZXing barcode scanner plugin for my Xamarin.Forms project. According to some posts, I need to use custom overlay for ZXing scanner in order to have cancel button. But I'm not familiar with Android development in a Xamarin.Forms project.
So far, I know a scanner (MobileBarcodeScanner of ZXing plugin) accept an Android.Views.View as an overlay to replace the default scanning page view.
public async Task<string> ScanAsync()
{
MobileBarcodeScanner scanner = new MobileBarcodeScanner();
scanner.UseCustomOverlay = true;
scanner.CustomOverlay = ???????;
var scanResult = await scanner.Scan();
if (scanResult != null)
{ return scanResult.Text; }
return null;
}
But I don't know how to create a view page (either in XML design or programmatically) and set it to scanner.CustomOverlay.
I'm not sure if a common Android view can be used for scanner, any detailed reference would be really appreicated.
Thanks.
If you want to customize the overlay, you must create your own View for each platform. You can customize your overlay like this( create a custom overlay called ZxingOverlayView
set it to the scanner.CustomOverlay
):
var scanner = new ZXing.MobileMobileBarcodeScanner();
scanner.UseCustomOverlay = true;
myCustomOverlayInstance = new ZxingOverlayView(this, scanner);
scanner.CustomOverlay = myCustomOverlayInstance;
ZxingOverlayView
should inherit the view
then add your control to the custom view.
You can see details about this link.
http://slackshotindustries.blogspot.com/2013/04/creating-custom-overlays-in-xzing.html
Edit
There are completely steps.
First of all, you could create a interface for dependence service.
public interface IDeviceService
{
Task<string> ScanAsync();
}
You can use this interface in the PCL code.
private async void DependencyButton_Clicked(object sender, EventArgs e)
{
var result = await DependencyService.Get<IDeviceService>().ScanAsync();
if (!string.IsNullOrEmpty(result))
{
await DisplayAlert(result, null, "OK");
}
}
In the android platform. You can design your layout. First of all, create a layout
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/imgClose"
android:layout_width="30dp"
android:layout_height="30dp"
android:src="@drawable/close"
android:layout_marginTop="20dp"
android:layout_marginLeft="20dp"/>
<RelativeLayout
android:id="@+id/llScan"
android:layout_width="240dp"
android:layout_height="240dp"
android:layout_centerInParent="true"
android:background="@drawable/scan">
<ImageView
android:id="@+id/imgLine"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:src="@drawable/scan_line"
android:layout_centerHorizontal="true" />
</RelativeLayout>
<View
android:id="@+id/viewTop"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@id/llScan"
android:background="@color/title_black"/>
<View
android:id="@+id/viewBottom"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/llScan"
android:background="@color/title_black"
android:layout_alignParentBottom="true"/>
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/viewTop"
android:layout_toLeftOf="@id/llScan"
android:layout_above="@id/viewBottom"
android:background="@color/title_black"/>
<View
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/viewTop"
android:layout_above="@id/viewBottom"
android:layout_toRightOf="@id/llScan"
android:background="@color/title_black"/>
</RelativeLayout>
Then achieve the dependence service interface and use your new layout.
[assembly: Xamarin.Forms.Dependency(typeof(DeviceService))]
namespace Sample.Droid
{
public class DeviceService : IDeviceService
{
public async Task<string> ScanAsync()
{
var scanner = new ZXing.Mobile.MobileBarcodeScanner
{
UseCustomOverlay = true
};
//scanner.CustomOverlay = new CustomScanView(Application.Context);
var options = new ZXing.Mobile.MobileBarcodeScanningOptions()
{
TryHarder = true,
AutoRotate = false,
UseFrontCameraIfAvailable = false,
CameraResolutionSelector = new CameraResolutionSelectorDelegate(SelectLowestResolutionMatchingDisplayAspectRatio),
PossibleFormats = new List<ZXing.BarcodeFormat>()
{
ZXing.BarcodeFormat.QR_CODE
}
};
View scanView = LayoutInflater.From(Application.Context).Inflate(Resource.Layout.ScanView, null);
ImageView imgLine = scanView.FindViewById<ImageView>(Resource.Id.imgLine);
ImageView imgClose = scanView.FindViewById<ImageView>(Resource.Id.imgClose);
imgClose.Click += delegate
{
scanner.Cancel();
};
scanner.CustomOverlay = scanView;
ObjectAnimator objectAnimator = ObjectAnimator.OfFloat(imgLine, "Y", 0, DpToPixels(240));
objectAnimator.SetDuration(2500);
objectAnimator.RepeatCount = -1;
objectAnimator.SetInterpolator(new LinearInterpolator());
objectAnimator.RepeatMode = ValueAnimatorRepeatMode.Restart;
objectAnimator.Start();
ZXing.Result scanResults = await scanner.Scan(CrossCurrentActivity.Current.Activity, options);
if (scanResults != null)
{
return scanResults.Text;
}
return string.Empty;
}
private int DpToPixels(double dp)
{
return (int)(dp * Application.Context.Resources.DisplayMetrics.Density);
}
private CameraResolution SelectLowestResolutionMatchingDisplayAspectRatio(List<CameraResolution> availableResolutions)
{
CameraResolution result = null;
//a tolerance of 0.1 should not be visible to the user
double aspectTolerance = 0.1;
var displayOrientationHeight = DeviceDisplay.MainDisplayInfo.Orientation == DisplayOrientation.Portrait ? DeviceDisplay.MainDisplayInfo.Height : DeviceDisplay.MainDisplayInfo.Width;
var displayOrientationWidth = DeviceDisplay.MainDisplayInfo.Orientation == DisplayOrientation.Portrait ? DeviceDisplay.MainDisplayInfo.Width : DeviceDisplay.MainDisplayInfo.Height;
//calculatiing our targetRatio
var targetRatio = displayOrientationHeight / displayOrientationWidth;
var targetHeight = displayOrientationHeight;
var minDiff = double.MaxValue;
//camera API lists all available resolutions from highest to lowest, perfect for us
//making use of this sorting, following code runs some comparisons to select the lowest resolution that matches the screen aspect ratio and lies within tolerance
//selecting the lowest makes Qr detection actual faster most of the time
foreach (var r in availableResolutions.Where(r => Math.Abs(((double)r.Width / r.Height) - targetRatio) < aspectTolerance))
{
//slowly going down the list to the lowest matching solution with the correct aspect ratio
if (Math.Abs(r.Height - targetHeight) < minDiff)
minDiff = Math.Abs(r.Height - targetHeight);
result = r;
}
return result;
}
}
}
IOS code.
[assembly: Xamarin.Forms.Dependency(typeof(DeviceService))]
namespace Sample.iOS
{
public class DeviceService : IDeviceService
{
public async Task<string> ScanAsync()
{
var scanner = new ZXing.Mobile.MobileBarcodeScanner()
{
UseCustomOverlay = true
};
var options = new ZXing.Mobile.MobileBarcodeScanningOptions()
{
TryHarder = true,
AutoRotate = false,
UseFrontCameraIfAvailable = false,
PossibleFormats = new List<ZXing.BarcodeFormat>()
{
ZXing.BarcodeFormat.QR_CODE
}
};
ScannerOverlayView customOverlay = new ScannerOverlayView();
customOverlay.OnCancel += () =>
{
scanner?.Cancel();
};
customOverlay.OnResume += () =>
{
scanner?.ResumeAnalysis();
};
customOverlay.OnPause += () =>
{
scanner?.PauseAnalysis();
};
scanner.CustomOverlay = customOverlay;
ZXing.Result scanResults = null;
scanResults = await scanner.Scan(options);
//customOverlay.Dispose();
if (scanResults != null)
{
return scanResults.Text;
}
return string.Empty;
}
}
Here is running GIF.
Here is a good simple code. you could refer to it. https://github.com/Wenfengcheng/ZXing.Sample_Xamarin
这篇关于如何为 ZXing Scanner 创建和实现 Android CustomOverlay?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!