如何使用 C# 构建.NET MAUI条形码扫描器?
IronBarcode允许您直接从.NET MAUI应用程序内的图像文件中扫描条形码——无需摄像头流、无需驱动程序配置、无需特定于平台的权限循环。
只需一次方法调用,即可扫描 JPEG、PNG、GIF、TIFF 和 BMP 文件中的条形码。 同一段代码无需修改即可在 Windows、Android 和 iOS 上运行。 立即开始免费试用,并跟随以下代码示例进行学习。
如何创建一个用于条形码扫描的.NET MAUI项目?
在 Visual Studio 中设置.NET MAUI项目非常简单。 启动 Visual Studio 2022 或更高版本,选择"创建新项目" ,选择.NET MAUI应用程序模板,输入项目名称,然后选择目标平台。 本教程重点介绍 Windows 部署,但同一个项目也可以在 Android 和 iOS 上运行。 .NET MAUI是微软的跨平台框架,用于从单个共享代码库使用 C# 和 XAML 构建原生移动和桌面应用程序。
与ZXing.Net.MAUI等基于摄像头的解决方案不同,IronBarcode 不需要特殊配置,因为 ZXing.Net.MAUI 需要 CameraView 控制设置和 MauiProgram.cs 注册。 您的 MauiProgram.cs 仍处于默认模板状态。 这样可以避免启动代码中涉及第三方处理程序注册,并减少启动时初始化错误的发生范围。
要安装IronBarcode,请在软件包管理器控制台中运行以下命令:
Install-Package BarCode
Install-Package BarCode
这个单一软件包即可提供条形码扫描、二维码识别、多条形码检测和条形码生成功能。 无需其他依赖项。
要在生产环境中激活 IronBarcode,请将您的许可证密钥设置到 App.xaml.cs 或 MauiProgram.cs 中:
IronBarCode.License.LicenseKey = "YOUR_IRONBARCODE_LICENSE_KEY";
IronBarCode.License.LicenseKey = "YOUR_IRONBARCODE_LICENSE_KEY";
Imports IronBarCode
IronBarCode.License.LicenseKey = "YOUR_IRONBARCODE_LICENSE_KEY"
您可以从IronBarcode许可页面获取密钥,或者从免费试用许可证开始。
基于图像的扫描的权限有何不同?
传统的基于摄像头的条形码扫描器需要在平台清单中明确授权。 在 Android 系统中,您需要添加 AndroidManifest.xml:
<uses-permission android:name="android.permission.CAMERA" /><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
在 iOS 上,您在 Info.plist 中声明 NSCameraUsageDescription。 在运行时处理被拒绝的权限会增加容易被忽略的错误路径。
因为IronBarcode是从文件流而不是相机预览中读取数据,所以你只需要访问文件系统即可。 在Windows系统中,此权限会自动授予。 在 Android 和 iOS 上,FilePicker 会在用户选择图像时处理用户同意——无需手动请求权限。
MAUI条形码扫描器最适合使用哪种XAML接口?
一个极简的界面——一个图像选择按钮、一个图像显示区域和一个结果标签——就能满足大多数条形码扫描场景的需求。 以下 XAML 代码为 .NET MAUI 创建该布局 ContentPage:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="BarcodeScanner.MainPage">
<ScrollView>
<VerticalStackLayout Spacing="20" Padding="30">
<Label Text="MAUI Barcode Scanner"
FontSize="24"
HorizontalOptions="Center" />
<Button x:Name="SelectImageBtn"
Text="Select Image File"
Clicked="OnSelectImage" />
<Image x:Name="SelectedImageDisplay"
HeightRequest="250" />
<Label x:Name="ResultsLabel"
Text="Barcode results will appear here" />
</VerticalStackLayout>
</ScrollView>
</ContentPage>
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="BarcodeScanner.MainPage">
<ScrollView>
<VerticalStackLayout Spacing="20" Padding="30">
<Label Text="MAUI Barcode Scanner"
FontSize="24"
HorizontalOptions="Center" />
<Button x:Name="SelectImageBtn"
Text="Select Image File"
Clicked="OnSelectImage" />
<Image x:Name="SelectedImageDisplay"
HeightRequest="250" />
<Label x:Name="ResultsLabel"
Text="Barcode results will appear here" />
</VerticalStackLayout>
</ScrollView>
</ContentPage>
该布局提供了一个用于触发文件选择器的按钮、一个用于显示所选图像的区域以及一个用于显示解码后的条形码值的标签。 它在所有.NET MAUI目标平台上都能正确渲染,无需针对特定平台进行调整。
对于生产应用程序,请考虑将 ResultsLabel 替换为 CollectionView,以便在可滚动列表中显示多个条形码结果,尤其是在扫描包含多个条形码的文档时。
如何在.NET MAUI中扫描图像文件中的条形码?
MainPage.xaml.cs 中的代码隐藏处理图像选择和条形码读取。 BarcodeReader.Read 接受文件路径并返回一个 BarcodeResults 集合。 集合中的每个项目都显示条形码 Value、BarcodeType 和位置坐标。
以下是完整的实现代码:
using IronBarCode;
namespace BarcodeScanner;
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
}
private async void OnSelectImage(object sender, EventArgs e)
{
try
{
// Open the system file picker filtered to image types
var result = await FilePicker.PickAsync(new PickOptions
{
FileTypes = FilePickerFileType.Images,
PickerTitle = "Select a barcode image"
});
if (result != null)
{
// Display the selected image in the UI
var stream = await result.OpenReadAsync();
SelectedImageDisplay.Source = ImageSource.FromStream(() => stream);
// Decode all barcodes found in the image
var barcodes = BarcodeReader.Read(result.FullPath);
if (barcodes.Count > 0)
{
// Build a display string listing each barcode type and value
string output = string.Join("\n",
barcodes.Select(b => $"{b.BarcodeType}: {b.Value}"));
ResultsLabel.Text = output;
}
else
{
ResultsLabel.Text = "No barcodes detected in image";
}
}
}
catch (Exception ex)
{
ResultsLabel.Text = $"Error: {ex.Message}";
}
}
}
using IronBarCode;
namespace BarcodeScanner;
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
}
private async void OnSelectImage(object sender, EventArgs e)
{
try
{
// Open the system file picker filtered to image types
var result = await FilePicker.PickAsync(new PickOptions
{
FileTypes = FilePickerFileType.Images,
PickerTitle = "Select a barcode image"
});
if (result != null)
{
// Display the selected image in the UI
var stream = await result.OpenReadAsync();
SelectedImageDisplay.Source = ImageSource.FromStream(() => stream);
// Decode all barcodes found in the image
var barcodes = BarcodeReader.Read(result.FullPath);
if (barcodes.Count > 0)
{
// Build a display string listing each barcode type and value
string output = string.Join("\n",
barcodes.Select(b => $"{b.BarcodeType}: {b.Value}"));
ResultsLabel.Text = output;
}
else
{
ResultsLabel.Text = "No barcodes detected in image";
}
}
}
catch (Exception ex)
{
ResultsLabel.Text = $"Error: {ex.Message}";
}
}
}
Imports IronBarCode
Namespace BarcodeScanner
Public Partial Class MainPage
Inherits ContentPage
Public Sub New()
InitializeComponent()
End Sub
Private Async Sub OnSelectImage(sender As Object, e As EventArgs)
Try
' Open the system file picker filtered to image types
Dim result = Await FilePicker.PickAsync(New PickOptions With {
.FileTypes = FilePickerFileType.Images,
.PickerTitle = "Select a barcode image"
})
If result IsNot Nothing Then
' Display the selected image in the UI
Dim stream = Await result.OpenReadAsync()
SelectedImageDisplay.Source = ImageSource.FromStream(Function() stream)
' Decode all barcodes found in the image
Dim barcodes = BarcodeReader.Read(result.FullPath)
If barcodes.Count > 0 Then
' Build a display string listing each barcode type and value
Dim output As String = String.Join(vbCrLf, barcodes.Select(Function(b) $"{b.BarcodeType}: {b.Value}"))
ResultsLabel.Text = output
Else
ResultsLabel.Text = "No barcodes detected in image"
End If
End If
Catch ex As Exception
ResultsLabel.Text = $"Error: {ex.Message}"
End Try
End Sub
End Class
End Namespace
BarcodeReader.Read 处理给定路径下的文件,自动检测所有存在的条形码符号,并立即返回结果。 该方法支持所有主要的 1D 和 2D 条形码格式,包括 Code 128、Code 39、QR Code、Data Matrix、PDF417 和 EAN-13。
!a href="/static-assets/barcode/blog/net-maui-scan-barcode/net-maui-scan-barcode-1.webp">.NET MAUI 使用强大的条码扫描器库在 Windows 应用程序中扫描条码:图片 1 - 扫描条码输出。
FilePicker.PickAsync 调用将选择器限制为图像类型,因此用户不会意外选择非图像文件。 如果 result 是 null,则表示用户已取消 -- if (result != null) 守卫会默默地处理这种情况。
如何在对话框中显示扫描结果?
对于简短的确认消息,DisplayAlert 提供了一个模态对话框,无需额外的 UI 元素:
private async void ShowScanSummary(BarcodeResults barcodes)
{
if (barcodes.Count > 0)
{
// Inform the user how many barcodes were detected
string message = $"Found {barcodes.Count} barcode(s) in the image.";
await DisplayAlert("Scan Complete", message, "OK");
}
else
{
await DisplayAlert("No Results", "No barcodes were found in the image.", "OK");
}
}
private async void ShowScanSummary(BarcodeResults barcodes)
{
if (barcodes.Count > 0)
{
// Inform the user how many barcodes were detected
string message = $"Found {barcodes.Count} barcode(s) in the image.";
await DisplayAlert("Scan Complete", message, "OK");
}
else
{
await DisplayAlert("No Results", "No barcodes were found in the image.", "OK");
}
}
Private Async Sub ShowScanSummary(barcodes As BarcodeResults)
If barcodes.Count > 0 Then
' Inform the user how many barcodes were detected
Dim message As String = $"Found {barcodes.Count} barcode(s) in the image."
Await DisplayAlert("Scan Complete", message, "OK")
Else
Await DisplayAlert("No Results", "No barcodes were found in the image.", "OK")
End If
End Sub
这种模式适用于简单的确认流程。 对于需要对解码值执行操作的应用程序(例如,在条形码库存管理系统中通过条形码查找产品),请直接从 OnSelectImage 处理程序将 barcodes 集合传递给您的业务逻辑层。
如何扫描多个条形码并调整检测速度?
当图像中包含多个条形码时, IronBarcode默认会检测所有条形码。 为了在知道预期格式的情况下获得更好的性能,请在调用 BarcodeReader.Read 之前配置 BarcodeReaderOptions:
using IronBarCode;
// Target only QR codes and Code 128 for faster detection
var options = new BarcodeReaderOptions
{
ExpectMultipleBarcodes = true,
ExpectBarcodeTypes = BarcodeEncoding.QRCode | BarcodeEncoding.Code128,
Speed = ReadingSpeed.Balanced
};
var barcodes = BarcodeReader.Read(imagePath, options);
foreach (var barcode in barcodes)
{
Console.WriteLine($"Type: {barcode.BarcodeType} | Value: {barcode.Value}");
}
using IronBarCode;
// Target only QR codes and Code 128 for faster detection
var options = new BarcodeReaderOptions
{
ExpectMultipleBarcodes = true,
ExpectBarcodeTypes = BarcodeEncoding.QRCode | BarcodeEncoding.Code128,
Speed = ReadingSpeed.Balanced
};
var barcodes = BarcodeReader.Read(imagePath, options);
foreach (var barcode in barcodes)
{
Console.WriteLine($"Type: {barcode.BarcodeType} | Value: {barcode.Value}");
}
Imports IronBarCode
' Target only QR codes and Code 128 for faster detection
Dim options As New BarcodeReaderOptions With {
.ExpectMultipleBarcodes = True,
.ExpectBarcodeTypes = BarcodeEncoding.QRCode Or BarcodeEncoding.Code128,
.Speed = ReadingSpeed.Balanced
}
Dim barcodes = BarcodeReader.Read(imagePath, options)
For Each barcode In barcodes
Console.WriteLine($"Type: {barcode.BarcodeType} | Value: {barcode.Value}")
Next
!a href="/static-assets/barcode/blog/net-maui-scan-barcode/net-maui-scan-barcode-2.webp">.NET MAUI 使用强大的条码扫描器库在 Windows 应用程序中扫描条码:图像 2 - 扫描多个 BarCode 的输出。
ExpectBarcodeTypes 属性将检测引擎的范围缩小到指定的符号体系。 设置 Speed 到 ReadingSpeed.Faster 适用于高对比度、无失真的图像。 ReadingSpeed.Detailed 应用额外的图像校正过程,并处理旋转、倾斜和低分辨率输入,但代价是需要额外的处理时间。
ExpectMultipleBarcodes = true 告诉读者在第一次匹配后继续扫描,而不是提前返回。 在单条形码场景下,省略此选项可使每次扫描节省几毫秒时间。
这种配置使得扫描器适用于各种应用:零售应用程序读取产品条形码,仓库工具处理发货照片上的打印条形码标签,或者文档工作流程从上传的发票中提取二维码。
如何处理高难度或低质量图片?
生产过程中使用的图片很少是完美无瑕的。在强光下拍摄的仓库照片、电子邮件客户端的屏幕截图以及扫描的文档都会引入噪点、压缩伪影和几何失真。 IronBarcode 公开 ImageFilterCollection,以便在解码前对图像进行预处理:
using IronBarCode;
using IronSoftware.Drawing;
// Apply corrections for a low-quality warehouse photo
var options = new BarcodeReaderOptions
{
ImageFilters = new ImageFilterCollection
{
new SharpenFilter(),
new ContrastFilter(1.2f),
new DenoiseFilter()
},
Speed = ReadingSpeed.Detailed
};
var barcodes = BarcodeReader.Read(imagePath, options);
using IronBarCode;
using IronSoftware.Drawing;
// Apply corrections for a low-quality warehouse photo
var options = new BarcodeReaderOptions
{
ImageFilters = new ImageFilterCollection
{
new SharpenFilter(),
new ContrastFilter(1.2f),
new DenoiseFilter()
},
Speed = ReadingSpeed.Detailed
};
var barcodes = BarcodeReader.Read(imagePath, options);
Imports IronBarCode
Imports IronSoftware.Drawing
' Apply corrections for a low-quality warehouse photo
Dim options As New BarcodeReaderOptions With {
.ImageFilters = New ImageFilterCollection From {
New SharpenFilter(),
New ContrastFilter(1.2F),
New DenoiseFilter()
},
.Speed = ReadingSpeed.Detailed
}
Dim barcodes = BarcodeReader.Read(imagePath, options)
SharpenFilter 从压缩或失焦的捕获中恢复边缘定义。 ContrastFilter 在光线不均匀时发挥作用。 DenoiseFilter 减少低分辨率扫描产生的斑点。 将这些过滤器与 ReadingSpeed.Detailed 结合使用,可以最大限度地提高对困难材料的阅读率。
对于接受用户从各种来源上传图像的.NET MAUI应用程序,默认情况下应用保守的过滤器,并在第二次重试时升级到更积极的纠正措施,可以在常见情况下改善用户体验,而不会增加明显的延迟。 您还可以将 Uri 或 byte[] 直接传递给 BarcodeReader.Read,这在图像来自网络响应而不是文件系统时非常有用。 有关更多输入源示例,请参阅IronBarcode操作指南。
为什么基于图像的扫描适合.NET MAUI应用程序?
通过 CameraView 控件进行实时摄像头扫描需要平台特定的权限授予、摄像头预览的生命周期管理以及焦点事件的处理。 在 iOS 上,这也意味着配置 AVCaptureSession; 在 Android 上,CameraX。 每个平台都有其自身的故障模式。
基于图像的扫描完全消除了这类担忧。 IronBarcode API 参考表明 BarcodeReader.Read 接受文件路径、Stream、Bitmap 或 byte[] -- 您的 MAUI 应用程序可以生成的任何表示形式。 这意味着无论图像来自 FilePicker、网络下载、渲染为位图的 PDF 页面还是电子邮件附件,相同的扫描逻辑都能正常工作。
由于摄像头硬件保持关闭状态,因此电池消耗量更低。 实时预览不会出现界面闪烁,也无需在应用程序暂停和恢复期间管理相机生命周期事件。 在平板电脑和台式机等设备中,实时取景器很少适用,因此基于图像的解码是自然而然的默认选择,而非妥协之举。无论设备类型如何,用户都可以使用相同的 FilePicker 调用打开云存储、本地文件夹或相机胶卷中的文件。
对于用户拍摄条形码标签并上传的工作流程(在ASP.NET 条形码扫描器 Web 应用程序中很常见),同一个 BarcodeReader.Read 调用在移动客户端和服务器上都有效,无需维护两个扫描实现。
IronBarcode与 ZXing .NET.MAUI 相比如何?
ZXing .NET.MAUI针对实时相机扫描,当实时取景器反馈是产品要求时,它能很好地发挥作用。 它需要 CameraView 集成、平台处理程序注册和运行时权限请求。
IronBarcode 的目标是基于文件和基于流的解码,涵盖了大多数Enterprise文档工作流程。 它支持更广泛的符号体系,包括PDF417 、 Data Matrix和Code 128 ,并提供 ZXing 没有提供的图像滤镜预处理功能。 对于用户拍摄或上传图像而不是实时扫描物品的应用场景, IronBarcode是更直接的选择。
如果您的应用除了基于文件的解码之外还需要实时相机扫描,您可以将这两个库结合起来:ZXing .NET.MAUI 用于取景器工作流程, IronBarcode用于批量文件处理。
下一步计划是什么?
使用IronBarcode构建.NET MAUI条形码扫描器只需要不到 30 行 C# 代码。 图像文件方法使您的 MAUI 代码库无需相机权限逻辑和特定于平台的初始化,并且相同的扫描调用在 Windows、Android 和 iOS 上运行完全相同。
IronBarcode API 文档涵盖了其他功能:从 PDF 文档中读取条形码、批量处理多个图像、编写自定义图像过滤器以及在读取条形码的同时生成条形码。 功能概述列出了所有支持的符号体系和格式。
您可以开始免费试用,在您的项目中测试IronBarcode ,或者在准备好进行生产部署时购买许可证。
常见问题解答
如何在不使用摄像头的情况下,用.NET MAUI创建一个条形码扫描器?
通过NuGet安装IronBarcode (` Install-Package BarCode`),然后调用 `BarcodeReader.Read(filePath)` 并传入从 `FilePicker.PickAsync` 获取的文件路径。无需相机权限或 `CameraView` 设置。
IronBarcode能否在.NET MAUI中扫描 Android 和 iOS 上的条形码?
是的。同一个 `BarcodeReader.Read` 调用可以在 Windows、Android 和 iOS 上运行,无需任何平台特定的代码路径或清单更改。
IronBarcode支持哪些条形码扫描图像格式?
IronBarcode可以读取 JPEG、PNG、GIF、TIFF 和 BMP 文件中的条形码。它还接受 `Stream`、`Bitmap` 和 `byte[]` 输入,因此无需先写入磁盘即可处理来自网络响应的图像。
如何在.NET MAUI中扫描单个图像中的多个条形码?
在 `BarcodeReaderOptions` 中设置 `ExpectMultipleBarcodes = true`,并将这些选项传递给 `BarcodeReader.Read`。读取器会将所有检测到的条形码返回到一个 `BarcodeResults` 集合中。
IronBarcode和 ZXing .NET.MAUI 有什么区别?
IronBarcode .NET .MAUI 旨在通过 `CameraView` 控件实现实时摄像头扫描。IronBarcode 旨在实现基于文件和基于流的解码,支持更多符号体系(包括 PDF417 和 Data Matrix),并为低质量输入提供图像滤波预处理。
如何提高模糊或低质量图像上的条形码检测效果?
向 `BarcodeReaderOptions` 添加一个 `ImageFilterCollection`,其中包含 `SharpenFilter`、`ContrastFilter` 和 `DenoiseFilter`,并将 `Speed = ReadingSpeed.Detailed` 设置为 `Speed = ReadingSpeed.Detailed`。这会在解码过程之前应用图像校正。
IronBarcode在.NET MAUI中支持哪些条形码格式?
IronBarcode支持所有主流的一维和二维条码:Code 128、Code 39、QR 码、Data Matrix、PDF417、EAN-13、EAN-8、UPC-A、UPC-E、Aztec 等。完整列表请参见IronBarcode功能页面。

