The CameraView component is the core camera interface that renders a live camera preview and provides comprehensive camera control functionality across iOS, Android, and Web platforms.
The main React component for camera functionality.
/**
* React component that renders a camera preview with full camera controls
*/
declare const CameraView: React.ForwardRefExoticComponent<
CameraViewProps & React.RefAttributes<CameraViewRef>
>;Complete configuration interface for the camera component.
interface CameraViewProps extends ViewProps {
/**
* Camera facing direction
* @default 'back'
*/
facing?: CameraType;
/**
* Flash mode setting
* @default 'off'
*/
flash?: FlashMode;
/**
* Zoom level (0 to 1, where 1 is maximum zoom)
* @default 0
*/
zoom?: number;
/**
* Camera mode for capture
* @default 'picture'
*/
mode?: CameraMode;
/**
* Whether to mute video recording
* @default false
*/
mute?: boolean;
/**
* Whether to mirror the image (front camera)
* @default false
*/
mirror?: boolean;
/**
* Auto focus mode (iOS only)
* @default 'off'
*/
autofocus?: FocusMode;
/**
* Whether camera should be active (iOS only)
* @default true
*/
active?: boolean;
/**
* Video quality setting
*/
videoQuality?: VideoQuality;
/**
* Video bitrate in bits per second
*/
videoBitrate?: number;
/**
* Whether to animate shutter
* @default true
*/
animateShutter?: boolean;
/**
* Picture size string (use getAvailablePictureSizes to get options)
*/
pictureSize?: string;
/**
* Selected lens identifier (iOS only)
* @default 'builtInWideAngleCamera'
*/
selectedLens?: string;
/**
* Whether to enable torch
* @default false
*/
enableTorch?: boolean;
/**
* Video stabilization mode (iOS only)
*/
videoStabilizationMode?: VideoStabilization;
/**
* Barcode scanner configuration
*/
barcodeScannerSettings?: BarcodeSettings;
/**
* Loading poster image URL (Web only)
*/
poster?: string;
/**
* Allow responsive orientation when locked (iOS only)
*/
responsiveOrientationWhenOrientationLocked?: boolean;
/**
* Camera preview aspect ratio (Android only)
*/
ratio?: CameraRatio;
/**
* Callback when camera is ready
*/
onCameraReady?: () => void;
/**
* Callback when camera mount fails
*/
onMountError?: (event: CameraMountError) => void;
/**
* Callback when barcode is scanned
*/
onBarcodeScanned?: (result: BarcodeScanningResult) => void;
/**
* Callback when orientation changes (iOS only)
*/
onResponsiveOrientationChanged?: (event: ResponsiveOrientationChanged) => void;
/**
* Callback when available lenses change (iOS only)
*/
onAvailableLensesChanged?: (event: AvailableLenses) => void;
}Static methods and properties available on the CameraView class.
/**
* Check whether the current device has a camera
* This is useful for web and simulators cases
* @platform web
* @returns Promise resolving to boolean indicating camera availability
*/
static isAvailableAsync(): Promise<boolean>;
/**
* Get available video codecs for the current device
* @platform ios
* @returns Promise resolving to array of supported video codecs
*/
static getAvailableVideoCodecsAsync(): Promise<VideoCodec[]>;
/**
* Property indicating if modern barcode scanner is available
* @platform ios
*/
static readonly isModernBarcodeScannerAvailable: boolean;
/**
* Launch the modern barcode scanner with options
* @platform ios
* @param options Scanner configuration options
* @returns Promise resolving when scanner launches
*/
static launchScanner(options?: ScanningOptions): Promise<void>;
/**
* Dismiss the modern barcode scanner
* @platform ios
* @returns Promise resolving when scanner dismisses
*/
static dismissScanner(): Promise<void>;
/**
* Listen for modern barcode scanner events
* @platform ios
* @param listener Event listener function
* @returns Event subscription object
*/
static onModernBarcodeScanned(listener: (event: ScanningResult) => void): EventSubscription;Methods available through the component ref for programmatic camera control.
interface CameraViewRef {
/**
* Take a picture with the specified options
* @param options Picture capture configuration
* @returns Promise resolving to captured picture data
*/
readonly takePicture: (options?: CameraPictureOptions) => Promise<CameraCapturedPicture>;
/**
* Take a picture and return a PictureRef for native image handling
* @param options Picture capture configuration
* @returns Promise resolving to picture reference
*/
readonly takePictureRef?: (options?: CameraPictureOptions) => Promise<PictureRef>;
/**
* Get available picture sizes for the current camera
* @returns Promise resolving to array of size strings
*/
readonly getAvailablePictureSizes: () => Promise<string[]>;
/**
* Get available camera lenses (iOS only)
* @returns Promise resolving to array of lens identifiers
*/
readonly getAvailableLenses: () => Promise<string[]>;
/**
* Start video recording
* @param options Recording configuration options
* @returns Promise resolving to video file info
*/
readonly record: (options?: CameraRecordingOptions) => Promise<{ uri: string }>;
/**
* Toggle video recording state (iOS 18+ only)
* @platform ios
* @returns Promise resolving when toggle completes
*/
readonly toggleRecording: () => Promise<void>;
/**
* Stop video recording
* @returns Promise resolving when recording stops
*/
readonly stopRecording: () => Promise<void>;
/**
* Launch modern barcode scanner (iOS only)
* @returns Promise resolving when scanner launches
*/
readonly launchModernScanner: () => Promise<void>;
/**
* Resume camera preview
* @returns Promise resolving when preview resumes
*/
readonly resumePreview: () => Promise<void>;
/**
* Pause camera preview
* @returns Promise resolving when preview pauses
*/
readonly pausePreview: () => Promise<void>;
}Core types used by the camera component.
type CameraType = 'front' | 'back';
type FlashMode = 'off' | 'on' | 'auto';
type CameraMode = 'picture' | 'video';
type CameraRatio = '4:3' | '16:9' | '1:1';
type FocusMode = 'on' | 'off';
type VideoQuality = '2160p' | '1080p' | '720p' | '480p' | '4:3';
type VideoCodec = 'avc1' | 'hvc1' | 'jpeg' | 'apcn' | 'ap4h';
type VideoStabilization = 'off' | 'standard' | 'cinematic' | 'auto';
type CameraOrientation = 'portrait' | 'portraitUpsideDown' | 'landscapeLeft' | 'landscapeRight';
interface CameraMountError {
message: string;
}
interface ResponsiveOrientationChanged {
orientation: CameraOrientation;
}
interface AvailableLenses {
lenses: string[];
}
interface BarcodeSettings {
barcodeTypes: BarcodeType[];
}
interface ScanningOptions {
/**
* Array of barcode types to scan for
*/
barcodeTypes: BarcodeType[];
/**
* Whether pinch-to-zoom gesture is enabled (iOS only)
* @default true
*/
isPinchToZoomEnabled?: boolean;
/**
* Whether guidance text appears over video (iOS only)
* @default true
*/
isGuidanceEnabled?: boolean;
/**
* Whether highlights appear around recognized items (iOS only)
* @default false
*/
isHighlightingEnabled?: boolean;
}
interface ScanningResult {
/**
* The barcode type
*/
type: string;
/**
* The parsed information encoded in the barcode
*/
data: string;
/**
* The raw information encoded in the barcode (Android only)
*/
raw?: string;
}import React, { useRef } from 'react';
import { View, StyleSheet } from 'react-native';
import { CameraView, CameraType } from 'expo-camera';
export function BasicCamera() {
const cameraRef = useRef<CameraView>(null);
return (
<View style={styles.container}>
<CameraView
ref={cameraRef}
style={styles.camera}
facing="back"
flash="off"
mode="picture"
/>
</View>
);
}
const styles = StyleSheet.create({
container: { flex: 1 },
camera: { flex: 1 },
});import React, { useState, useRef } from 'react';
import { View, StyleSheet } from 'react-native';
import { CameraView, CameraType, FlashMode, VideoQuality } from 'expo-camera';
export function AdvancedCamera() {
const [facing, setFacing] = useState<CameraType>('back');
const [flash, setFlash] = useState<FlashMode>('off');
const [zoom, setZoom] = useState(0);
const cameraRef = useRef<CameraView>(null);
const handleCameraReady = () => {
console.log('Camera is ready');
};
const handleMountError = (error: { message: string }) => {
console.error('Camera mount error:', error.message);
};
return (
<View style={styles.container}>
<CameraView
ref={cameraRef}
style={styles.camera}
facing={facing}
flash={flash}
zoom={zoom}
mode="picture"
animateShutter={true}
enableTorch={false}
mirror={facing === 'front'}
videoQuality="1080p"
videoBitrate={10000000}
onCameraReady={handleCameraReady}
onMountError={handleMountError}
barcodeScannerSettings={{
barcodeTypes: ['qr', 'ean13', 'code128']
}}
/>
</View>
);
}
const styles = StyleSheet.create({
container: { flex: 1 },
camera: { flex: 1 },
});import React, { useRef } from 'react';
import { View, TouchableOpacity, Text } from 'react-native';
import { CameraView } from 'expo-camera';
export function CameraWithControls() {
const cameraRef = useRef<CameraView>(null);
const getAvailableSizes = async () => {
if (cameraRef.current) {
const sizes = await cameraRef.current.getAvailablePictureSizes();
console.log('Available picture sizes:', sizes);
}
};
const getAvailableLenses = async () => {
if (cameraRef.current) {
try {
const lenses = await cameraRef.current.getAvailableLenses();
console.log('Available lenses:', lenses);
} catch (error) {
console.log('Lenses not supported on this platform');
}
}
};
const togglePreview = async () => {
if (cameraRef.current) {
// Example: pause and resume preview
await cameraRef.current.pausePreview();
setTimeout(async () => {
await cameraRef.current?.resumePreview();
}, 2000);
}
};
return (
<View style={{ flex: 1 }}>
<CameraView
ref={cameraRef}
style={{ flex: 1 }}
facing="back"
/>
<View style={{ flexDirection: 'row', justifyContent: 'space-around', padding: 20 }}>
<TouchableOpacity onPress={getAvailableSizes}>
<Text>Get Sizes</Text>
</TouchableOpacity>
<TouchableOpacity onPress={getAvailableLenses}>
<Text>Get Lenses</Text>
</TouchableOpacity>
<TouchableOpacity onPress={togglePreview}>
<Text>Toggle Preview</Text>
</TouchableOpacity>
</View>
</View>
);
}import React, { useEffect, useState } from 'react';
import { View, Text, TouchableOpacity, Platform } from 'react-native';
import { CameraView, VideoCodec, ScanningResult } from 'expo-camera';
export function CameraCapabilities() {
const [isCameraAvailable, setIsCameraAvailable] = useState<boolean | null>(null);
const [videoCodecs, setVideoCodecs] = useState<VideoCodec[]>([]);
const [isModernScannerAvailable, setIsModernScannerAvailable] = useState(false);
useEffect(() => {
checkCameraCapabilities();
}, []);
const checkCameraCapabilities = async () => {
// Check camera availability (Web only)
if (Platform.OS === 'web') {
try {
const available = await CameraView.isAvailableAsync();
setIsCameraAvailable(available);
} catch (error) {
console.log('Camera availability check not supported');
}
}
// Check available video codecs (iOS only)
if (Platform.OS === 'ios') {
try {
const codecs = await CameraView.getAvailableVideoCodecsAsync();
setVideoCodecs(codecs);
} catch (error) {
console.log('Video codecs not available');
}
}
// Check modern scanner availability
setIsModernScannerAvailable(CameraView.isModernBarcodeScannerAvailable);
};
const launchScanner = async () => {
if (Platform.OS === 'ios' && CameraView.isModernBarcodeScannerAvailable) {
try {
// Listen for scan results
const subscription = CameraView.onModernBarcodeScanned((result: ScanningResult) => {
console.log('Scanned:', result.data);
subscription.remove();
});
// Launch the scanner
await CameraView.launchScanner({
barcodeTypes: ['qr', 'ean13'],
isPinchToZoomEnabled: true,
isGuidanceEnabled: true,
isHighlightingEnabled: true,
});
} catch (error) {
console.error('Failed to launch scanner:', error);
}
}
};
return (
<View style={{ flex: 1, padding: 20 }}>
<Text>Camera Available: {isCameraAvailable?.toString() ?? 'N/A'}</Text>
<Text>Video Codecs: {videoCodecs.join(', ') || 'N/A'}</Text>
<Text>Modern Scanner: {isModernScannerAvailable.toString()}</Text>
{isModernScannerAvailable && (
<TouchableOpacity onPress={launchScanner} style={{ marginTop: 20, padding: 10, backgroundColor: 'blue' }}>
<Text style={{ color: 'white' }}>Launch Scanner</Text>
</TouchableOpacity>
)}
<CameraView style={{ flex: 1, marginTop: 20 }} facing="back" />
</View>
);
}import React, { useRef } from 'react';
import { Platform } from 'react-native';
import { CameraView, VideoStabilization } from 'expo-camera';
export function PlatformSpecificCamera() {
const cameraRef = useRef<CameraView>(null);
const iosSpecificProps = Platform.OS === 'ios' ? {
autofocus: 'on' as const,
active: true,
selectedLens: 'builtInWideAngleCamera',
videoStabilizationMode: 'standard' as VideoStabilization,
responsiveOrientationWhenOrientationLocked: true,
} : {};
const androidSpecificProps = Platform.OS === 'android' ? {
ratio: '16:9' as const,
} : {};
const webSpecificProps = Platform.OS === 'web' ? {
poster: 'https://example.com/camera-loading.png',
} : {};
return (
<CameraView
ref={cameraRef}
style={{ flex: 1 }}
facing="back"
{...iosSpecificProps}
{...androidSpecificProps}
{...webSpecificProps}
/>
);
}