Freeze Frame
Pause the camera after a successful scan, play a short animation, then resume. Makes scanning feel deliberate and smooth.
What is freeze frame?
When enableFreezeFrame is on, the scanner doesn't just fire the callback and keep going. Instead, it:
- Detects a stable code (3 consistent frames)
- Freezes the camera preview
- Plays a short animation (a flash or scanning band, depending on whether
proScanneris also on) - Fires
onCodeScannedwith the result - Auto-resumes scanning after about 500–800ms
This makes the scan feel intentional rather than just silently triggering. Users get a clear visual confirmation that something was scanned.
Enabling it
<Scanner
style={StyleSheet.absoluteFill}
enableFreezeFrame={true}
onCodeScanned={(result) => {
console.log('Scanned:', result.data);
}}
/>Resuming manually with a ref
If you want to stay paused after the scan (for example, to show a confirmation screen), you can call resumeScanning() yourself:
import React, { useRef, useState } from 'react';
import { View, Text, Button, StyleSheet } from 'react-native';
import { Scanner } from 'react-native-scanner-pro';
export default function ScanScreen() {
const scannerRef = useRef(null);
const [lastScan, setLastScan] = useState(null);
function handleScan(result) {
setLastScan(result.data);
// The camera is currently frozen here
// Call resumeScanning() whenever you're ready
}
return (
<View style={{ flex: 1 }}>
<Scanner
ref={scannerRef}
style={StyleSheet.absoluteFill}
enableFreezeFrame={true}
onCodeScanned={handleScan}
/>
{lastScan && (
<View style={styles.resultCard}>
<Text style={styles.resultText}>{lastScan}</Text>
<Button
title="Scan another"
onPress={() => {
setLastScan(null);
scannerRef.current?.resumeScanning();
}}
/>
</View>
)}
</View>
);
}
const styles = StyleSheet.create({
resultCard: {
position: 'absolute',
bottom: 40,
left: 20,
right: 20,
backgroundColor: '#fff',
borderRadius: 12,
padding: 16,
alignItems: 'center',
},
resultText: {
fontSize: 16,
marginBottom: 12,
},
});How stability detection works
Both on iOS and Android, the scanner requires 3 consecutive camera frames to contain the same code before it considers a scan "stable". Only then does the freeze frame trigger and the callback fire.
This is by design. Without stability gating, a camera that picks up a code for even one frame could trigger the callback — which leads to inconsistent behavior when the camera is moving fast or lighting is poor.
Tips
- Freeze frame works best in flows where the user scans one code at a time (checkout, ticket validation, package scanning)
- If you're building a bulk scan flow (scan many codes quickly), don't use freeze frame — let the scanner run continuously and debounce the results in JavaScript instead
- The freeze duration is about 500–800ms. It's intentionally short so the experience stays snappy.