Friday, 1 August 2025

Barcode/QR Code Scanning in MAUI Apps

 

Implementing barcode and QR code scanning in a .NET MAUI application is straightforward with the right libraries. Here are the main approaches:

Option 1: Using ZXing.Net.MAUI

The most popular solution is the ZXing.Net.MAUI library:

  1. Install the package:

    bash
    dotnet add package ZXing.Net.MAUI
  2. Initialize in MauiProgram.cs:

    csharp
    builder.UseMauiApp<App>()
           .UseBarcodeReader(); // Add this line
  3. Add camera permission:

    • For Android, add to AndroidManifest.xml:

      xml
      <uses-permission android:name="android.permission.CAMERA" />
    • For iOS, add to Info.plist:

      xml
      <key>NSCameraUsageDescription</key>
      <string>This app needs camera access to scan barcodes</string>
  4. Create a scanning page:

    xaml
    <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
                 xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                 xmlns:zxing="clr-namespace:ZXing.Net.MAUI.Controls;assembly=ZXing.Net.MAUI"
                 x:Class="YourApp.ScanPage">
        <zxing:CameraBarcodeReaderView
            x:Name="barcodeReader"
            BarcodesDetected="BarcodesDetected" />
    </ContentPage>
  5. Handle the scan results:

    csharp
    private void BarcodesDetected(object sender, BarcodeDetectionEventArgs e)
    {
        foreach (var barcode in e.Results)
        {
            Console.WriteLine($"Barcode: {barcode.Format} -> {barcode.Value}");
            // Process the scanned value
        }
    }

Option 2: Using Google's ML Kit (Android/iOS)

For more advanced scanning capabilities:

  1. Install Google ML Kit for MAUI

  2. Follow the platform-specific setup instructions

  3. Implement scanning similar to ZXing but with ML Kit's enhanced features

Option 3: Device Camera + Custom Processing

For complete control:

  1. Use MAUI's MediaPicker to take photos

  2. Process images with a library like ZXing.Net:

    csharp
    var photo = await MediaPicker.CapturePhotoAsync();
    using var stream = await photo.OpenReadAsync();
    var reader = new BarcodeReader();
    var result = reader.Decode(stream);

Tips for Better Scanning

  • Ensure proper camera permissions are requested at runtime

  • Add a viewfinder overlay to guide users

  • Consider adding vibration on successful scan

  • Handle low-light conditions with torch/toggle flash option

  • Test with various barcode types (QR, UPC, EAN, etc.)



Adding a Viewfinder Overlay for Barcode Scanning in MAUI

To improve the user experience when scanning barcodes/QR codes, you can add a viewfinder overlay that helps users align the code properly. Here's how to implement it with ZXing.Net.MAUI:

Option 1: Simple Rectangle Overlay (XAML)

xaml
<Grid>
    <!-- Camera Preview -->
    <zxing:CameraBarcodeReaderView
        x:Name="barcodeReader"
        BarcodesDetected="BarcodesDetected" />
    
    <!-- Viewfinder Overlay -->
    <Grid>
        <!-- Semi-transparent surrounding area -->
        <BoxView Color="Black" Opacity="0.6"/>
        
        <!-- Transparent center area with border -->
        <Frame 
            HorizontalOptions="Center"
            VerticalOptions="Center"
            WidthRequest="250"
            HeightRequest="250"
            CornerRadius="10"
            BackgroundColor="Transparent"
            BorderColor="White"
            Padding="0">
            
            <!-- Corner marks (optional) -->
            <Grid>
                <!-- Top-left corner -->
                <BoxView Color="White" WidthRequest="30" HeightRequest="5" HorizontalOptions="Start" VerticalOptions="Start"/>
                <BoxView Color="White" WidthRequest="5" HeightRequest="30" HorizontalOptions="Start" VerticalOptions="Start"/>
                
                <!-- Top-right corner -->
                <BoxView Color="White" WidthRequest="30" HeightRequest="5" HorizontalOptions="End" VerticalOptions="Start"/>
                <BoxView Color="White" WidthRequest="5" HeightRequest="30" HorizontalOptions="End" VerticalOptions="Start"/>
                
                <!-- Bottom-left corner -->
                <BoxView Color="White" WidthRequest="30" HeightRequest="5" HorizontalOptions="Start" VerticalOptions="End"/>
                <BoxView Color="White" WidthRequest="5" HeightRequest="30" HorizontalOptions="Start" VerticalOptions="End"/>
                
                <!-- Bottom-right corner -->
                <BoxView Color="White" WidthRequest="30" HeightRequest="5" HorizontalOptions="End" VerticalOptions="End"/>
                <BoxView Color="White" WidthRequest="5" HeightRequest="30" HorizontalOptions="End" VerticalOptions="End"/>
            </Grid>
        </Frame>
        
        <!-- Instruction text -->
        <Label Text="Align barcode within the frame"
               TextColor="White"
               FontSize="16"
               HorizontalOptions="Center"
               VerticalOptions="End"
               Margin="0,0,0,40"/>
    </Grid>
</Grid>

Option 2: Animated Viewfinder (Code-Behind)

For a more dynamic effect, add this to your page's code-behind:

csharp
// Add to your page class
private BoxView _scanLine;
private bool _isAnimating;

protected override void OnAppearing()
{
    base.OnAppearing();
    StartScanLineAnimation();
}

protected override void OnDisappearing()
{
    base.OnDisappearing();
    _isAnimating = false;
}

private void StartScanLineAnimation()
{
    _scanLine = new BoxView
    {
        Color = Colors.Red,
        WidthRequest = 250,
        HeightRequest = 2,
        HorizontalOptions = LayoutOptions.Center,
        VerticalOptions = LayoutOptions.Center,
        TranslationY = -125 // Start at top of viewfinder
    };
    
    if (this.FindByName<Grid>("overlayGrid") is Grid overlayGrid)
    {
        overlayGrid.Children.Add(_scanLine);
    }
    
    _isAnimating = true;
    Device.StartTimer(TimeSpan.FromMilliseconds(16), () =>
    {
        if (!_isAnimating) return false;
        
        _scanLine.TranslationY += 2;
        if (_scanLine.TranslationY >= 125)
        {
            _scanLine.TranslationY = -125;
        }
        return true;
    });
}

Option 3: Custom GraphicsView (Advanced)

For complete control over the drawing:

xaml
<GraphicsView x:Name="viewfinderOverlay" 
              Drawable="{StaticResource ViewfinderDrawable}"
              HorizontalOptions="Fill"
              VerticalOptions="Fill"/>

Create a custom drawable class:

csharp
public class ViewfinderDrawable : IDrawable
{
    public void Draw(ICanvas canvas, RectF dirtyRect)
    {
        // Draw semi-transparent overlay
        canvas.FillColor = Colors.Black.WithAlpha(0.6f);
        canvas.FillRectangle(dirtyRect);
        
        // Clear center area
        var centerWidth = 250;
        var centerHeight = 250;
        var centerX = (dirtyRect.Width - centerWidth) / 2;
        var centerY = (dirtyRect.Height - centerHeight) / 2;
        
        canvas.BlendMode = BlendMode.Clear;
        canvas.FillRectangle(centerX, centerY, centerWidth, centerHeight);
        canvas.BlendMode = BlendMode.Normal;
        
        // Draw border
        canvas.StrokeColor = Colors.White;
        canvas.StrokeSize = 3;
        canvas.DrawRectangle(centerX, centerY, centerWidth, centerHeight);
        
        // Draw corner marks
        var cornerSize = 20;
        var lineThickness = 5;
        
        // Top-left
        canvas.DrawLine(centerX, centerY, centerX + cornerSize, centerY);
        canvas.DrawLine(centerX, centerY, centerX, centerY + cornerSize);
        
        // Top-right
        canvas.DrawLine(centerX + centerWidth - cornerSize, centerY, 
                        centerX + centerWidth, centerY);
        canvas.DrawLine(centerX + centerWidth, centerY, 
                        centerX + centerWidth, centerY + cornerSize);
        
        // Bottom-left
        canvas.DrawLine(centerX, centerY + centerHeight - cornerSize, 
                        centerX, centerY + centerHeight);
        canvas.DrawLine(centerX, centerY + centerHeight, 
                        centerX + cornerSize, centerY + centerHeight);
        
        // Bottom-right
        canvas.DrawLine(centerX + centerWidth - cornerSize, centerY + centerHeight, 
                        centerX + centerWidth, centerY + centerHeight);
        canvas.DrawLine(centerX + centerWidth, centerY + centerHeight - cornerSize, 
                        centerX + centerWidth, centerY + centerHeight);
    }
}

Additional Enhancements

  1. Torch/Toggle Flash Button:

    xaml
    <Button Text="Toggle Flash" 
            Clicked="ToggleFlashClicked"
            HorizontalOptions="End"
            VerticalOptions="Start"
            Margin="20"/>
    csharp
    private void ToggleFlashClicked(object sender, EventArgs e)
    {
        barcodeReader.IsTorchOn = !barcodeReader.IsTorchOn;
    }
  2. Vibration on Successful Scan:

    csharp
    private async void BarcodesDetected(object sender, BarcodeDetectionEventArgs e)
    {
        if (e.Results.Any())
        {
            try 
            {
                // Vibrate for 200ms
                await Vibration.Default.Vibrate(TimeSpan.FromMilliseconds(200));
            }
            catch { }
            
            // Process result...
        }
    }


No comments:

Post a Comment

Complete Guide: Building a Live Cricket Streaming App for 100M Users

Comprehensive guide to building a scalable live cricket streaming platform for 100M users, covering backend infrastructure, streaming techno...