Custom QR Code Scanner UI for Mobile Apps
Imagine this: a delivery driver scans a QR code on a package, but the app shows a black screen — the camera is inaccessible. Or a user on an older iOS version experiences a crash due to a missing check for DataScannerViewController. Such issues lead to negative reviews and lost clients. We've encountered this many times and know how to avoid them.
Note: When a client asks to add a QR code scanner, it seems trivial — on iOS 16+, DataScannerViewController solves it in 20 lines. But in a real project, there are plenty of pitfalls: custom UI, permission handling, legacy OS support. We solve these tasks, ensuring smooth operation on all target devices. For each project, we select the optimal stack: on iOS — DataScanner for 16+, for backward compatibility — AVCaptureMetadataOutput; on Android — ML Kit with CameraX or ZXing for exotic formats. Development time savings can reduce costs by 30% compared to building from scratch.
A QR code scanner is a whole module: permission requests, custom overlay, animation, payload processing, integration with navigation and backend. Each stage has its pitfalls, but we've already solved them in dozens of projects. Below are proven architectural solutions and code you can adapt.
What problems we solve
Custom overlay and animation. The standard scanner rectangle doesn't fit the app's design. We implement a custom overlay with a cutout: on iOS using CAShapeLayer with evenOdd fill rule or SwiftUI Canvas, on Android — a custom View with PorterDuff.Mode.CLEAR. The scanning line animation — CABasicAnimation on iOS, ObjectAnimator on Android — gives the user feedback that scanning is in progress.
Camera access errors. The user may deny permission. We show a "Open Settings" button, directing them to the system menu. On Android, we additionally explain the reason using ActivityCompat.shouldShowRequestPermissionRationale(). According to Google ML Kit documentation, this increases the likelihood of re-granting access.
Legacy OS support. Not all devices are updated to iOS 16. For iOS 14–15, we use AVCaptureMetadataOutput with metadataObjectTypes = [.qr] — tested on thousands of devices. On Android, ML Kit works with API 21+, and for older devices, ZXing can be used, albeit with slower speed.
How we do it
Stack: Swift 5.9, SwiftUI + Combine for iOS; Kotlin + Jetpack Compose for Android. For backend integration, we use GraphQL (Apollo) or REST with Codable. For analytics — Firebase.
Case study: delivery app with QR scanning. The task was to recognize a QR code, extract a URL, and open it in a WebView with custom headers. We implemented the scanner with overlay, handled deep linking via Universal Links. As a result, the time from tap to page load was less than 1 second. Processing a single QR code takes about 50 ms on average, confirmed by profiling on real devices.
Work process
- Analysis — discuss UX, target OS versions, QR code types.
- Design — module architecture, payload processing scheme.
- Implementation — scanner code, custom UI, navigation integration.
- Testing — verification on real devices, including older versions.
- Deployment — submission to App Store and Google Play, TestFlight and Firebase Distribution setup.
What's included
- Source code of the module (Swift/Kotlin) with comments.
- Integration with your navigation and backend.
- Handling of all permissions and edge cases.
- Custom UI matching your design.
- Documentation and post-launch support.
Estimated timeline
Basic implementation — from 1 day. With custom UI — 2 to 3 days. Pricing is calculated individually.
Comparison of approaches
| Parameter | iOS (DataScanner) | Android (ML Kit) |
|---|---|---|
| Minimum version | 16.0 | API 21 (Android 5.0) |
| Lines of code | ~20 | ~10 (with CameraX) |
| Supported formats | QR, PDF417, Aztec | QR, Code128, EAN, DataMatrix |
| Custom UI | Yes (overlay) | Yes (overlay) |
| Multiple codes | recognizesMultipleItems: true |
setBarcodeFormats with mask |
ML Kit recognizes QR codes 2x faster than a universal scanner when the specific format Barcode.FORMAT_QR_CODE is specified.
Additional comparison: scanning libraries
| Library | Platform | Recognition speed | Format support | Custom UI |
|---|---|---|---|---|
| DataScanner (iOS) | iOS 16+ | ~30 ms avg | QR, PDF417, Aztec | Yes |
| AVCaptureMetadataOutput | iOS 7+ | ~100 ms | QR | Yes |
| ML Kit (Android) | API 21+ | ~50 ms | QR, Code128, EAN, DataMatrix | Yes |
| ZXing (Android) | API 15+ | ~200 ms | QR, DataMatrix, Code128 | Yes |
Our projects typically use DataScanner for iOS 16+ and ML Kit for Android — the optimal combination of speed and flexibility.
Why is it important to handle camera access errors?
If the user denies the request, the app may crash or hang with a black screen. We check the status: on iOS — AVCaptureDevice.authorizationStatus(for: .video), on Android — ContextCompat.checkSelfPermission(). On denial, we show a screen saying "Allow camera in settings". Apple Human Interface Guidelines recommend explaining why the camera is needed. Investment in development pays off after the first releases — a 40% reduction in negative reviews directly impacts retention.
How to implement a custom scanner UI?
An overlay with a transparent cutout is standard. On iOS:
let path = UIBezierPath(rect: view.bounds) let cutout = UIBezierPath(roundedRect: scanRect, cornerRadius: 8) path.append(cutout) path.usesEvenOddFillRule = true let layer = CAShapeLayer() layer.path = path.cgPath layer.fillRule = .evenOdd On Android:
val paint = Paint(Paint.ANTI_ALIAS_FLAG).apply { xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR) } Line animation — CABasicAnimation moving scanLine.frame.origin.y on iOS, ObjectAnimator on translationY on Android.
Common development mistakes
- Forgot to check
isSupportedon iOS — crash on devices without authentication. - Missing
NSCameraUsageDescriptionkey in info.plist — App Store rejection. - On Android, not handling
onRequestPermissionsResult— app crashes. - Overlay size not adapted for different screens — breaks on tablets.
We guarantee the scanner will work on all target devices and pass App Store and Google Play review. Contact us to discuss your project. Order a turnkey QR scanner development — get a ready module with documentation and support.







