求助:如何在纯Xamarin Android项目中读取二维码/条形码?
在纯Xamarin Android中实现二维码/条形码扫描
一、安装必要的NuGet包
安装以下两个包:
ZXing.Net.MobileZXing.Net.Mobile.Android
二、方式1:使用内置扫描Activity(快速实现,无需自定义布局)
这种方式无需自行编写axml布局,直接调用ZXing提供的现成扫描界面,能避开布局适配问题:
- 添加相机权限
在AndroidManifest.xml中加入权限声明:
<uses-permission android:name="android.permission.CAMERA" /> <uses-feature android:name="android.hardware.camera" /> <uses-feature android:name="android.hardware.camera.autofocus" />
- 动态申请权限(Android 6.0+)
启动扫描前先检查并申请相机权限:
private async Task<bool> CheckCameraPermission() { var status = await Permissions.CheckStatusAsync<Permissions.Camera>(); if (status != PermissionStatus.Granted) { status = await Permissions.RequestAsync<Permissions.Camera>(); } return status == PermissionStatus.Granted; }
- 启动扫描
在按钮点击或需要触发扫描的事件中执行:
private async void btnScan_Click(object sender, EventArgs e) { if (!await CheckCameraPermission()) { Toast.MakeText(this, "需要相机权限才能扫描", ToastLength.Short).Show(); return; } var scanner = new MobileBarcodeScanner(this); var result = await scanner.Scan(); if (result != null) { Toast.MakeText(this, $"扫描结果:{result.Text}", ToastLength.Long).Show(); } }
三、方式2:自定义扫描布局(解决axml适配问题)
如果需要自定义扫描界面,按以下步骤操作:
- 创建适配性布局axml
在Resources/layout下新建ScanLayout.axml,示例布局适配不同屏幕尺寸:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <!-- 相机预览控件 --> <zxing.android.CameraPreview android:id="@+id/camera_preview" android:layout_width="match_parent" android:layout_height="match_parent" /> <!-- 扫描框(可替换为自定义9-Patch图片保证拉伸不变形) --> <ImageView android:layout_width="250dp" android:layout_height="250dp" android:layout_centerInParent="true" android:src="@drawable/scan_frame" android:background="@android:color/transparent" /> <!-- 返回按钮 --> <Button android:id="@+id/btn_back" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="16dp" android:text="返回" /> </RelativeLayout>
- 编写扫描Activity逻辑
新建ScanActivity.cs,代码如下:
[Activity(Label = "扫描")] public class ScanActivity : AppCompatActivity { private CameraPreview _cameraPreview; private MobileBarcodeScanner _scanner; protected override void OnCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); SetContentView(Resource.Layout.ScanLayout); _cameraPreview = FindViewById<CameraPreview>(Resource.Id.camera_preview); var btnBack = FindViewById<Button>(Resource.Id.btn_back); btnBack.Click += (s, e) => Finish(); // 初始化扫描器 _scanner = new MobileBarcodeScanner(this) { UseCustomOverlay = true, CustomOverlay = _cameraPreview }; // 开始扫描,获取结果后返回 _scanner.ScanContinuously((result, cancel) => { if (result != null && !string.IsNullOrEmpty(result.Text)) { Intent intent = new Intent(); intent.PutExtra("ScanResult", result.Text); SetResult(Result.Ok, intent); Finish(); } }); } protected override void OnPause() { _scanner?.PauseScanning(); base.OnPause(); } protected override void OnResume() { _scanner?.ResumeScanning(); base.OnResume(); } protected override void OnDestroy() { _scanner?.StopScanning(); base.OnDestroy(); } }
- 调用自定义扫描界面
在主Activity中启动该Activity并接收扫描结果:
private const int ScanRequestCode = 100; private async void btnCustomScan_Click(object sender, EventArgs e) { if (!await CheckCameraPermission()) { Toast.MakeText(this, "需要相机权限才能扫描", ToastLength.Short).Show(); return; } StartActivityForResult(typeof(ScanActivity), ScanRequestCode); } protected override void OnActivityResult(int requestCode, Result resultCode, Intent data) { base.OnActivityResult(requestCode, resultCode, data); if (requestCode == ScanRequestCode && resultCode == Result.Ok) { var scanResult = data.GetStringExtra("ScanResult"); Toast.MakeText(this, $"自定义扫描结果:{scanResult}", ToastLength.Long).Show(); } }
四、常见适配问题解决
- 布局适配:尽量使用
match_parent、wrap_content和dp单位,避免固定像素值;扫描框使用9-Patch图片,保证拉伸时边框不变形。 - 相机启动失败:确认权限申请成功,设备相机功能正常;Android 10+需注意系统隐私权限设置。
内容的提问来源于stack exchange,提问作者Samara Bravo
相关产品推荐
相关产品推荐

