Camera Switching¶
Switch between front and back cameras.
Toggle Camera Lens¶
Switch between front and back cameras:
controller.toggleCameraLens() // BACK <-> FRONT
Set Initial Camera¶
The initial camera lens is set via CameraConfiguration. At runtime, use toggleCameraLens() to switch:
val cameraState by rememberCameraKState(
config = CameraConfiguration(cameraLens = CameraLens.FRONT) // Start with selfie camera
)
Get Current Camera¶
val currentLens = controller.getCameraLens()
when (currentLens) {
CameraLens.FRONT -> println("Using front camera")
CameraLens.BACK -> println("Using back camera")
null -> println("Camera not initialized")
}
UI Example¶
@Composable
fun CameraWithSwitching() {
val scope = rememberCoroutineScope()
val cameraState by rememberCameraKState(config = CameraConfiguration())
Box(modifier = Modifier.fillMaxSize()) {
when (val state = cameraState) {
is CameraKState.Ready -> {
val controller = state.controller
CameraPreviewView(
controller = controller,
modifier = Modifier.fillMaxSize()
)
// Camera switch button
IconButton(
onClick = { controller.toggleCameraLens() },
modifier = Modifier
.align(Alignment.TopEnd)
.padding(16.dp)
.background(Color.Black.copy(alpha = 0.5f), CircleShape)
) {
Icon(
imageVector = Icons.Default.Cameraswitch,
contentDescription = "Switch Camera",
tint = Color.White
)
}
// Capture button
FloatingActionButton(
onClick = {
scope.launch {
controller.takePictureToFile()
}
},
modifier = Modifier
.align(Alignment.BottomCenter)
.padding(32.dp)
) {
Icon(Icons.Default.CameraAlt, "Capture")
}
}
is CameraKState.Error -> Text("Camera error: ${state.message}")
CameraKState.Initializing -> CircularProgressIndicator()
}
}
}
Smooth Camera Switch¶
Add loading indicator during switch:
@Composable
fun CameraWithSmoothSwitch() {
val scope = rememberCoroutineScope()
val cameraState by rememberCameraKState(config = CameraConfiguration())
var isSwitching by remember { mutableStateOf(false) }
Box(modifier = Modifier.fillMaxSize()) {
when (val state = cameraState) {
is CameraKState.Ready -> {
val controller = state.controller
CameraPreviewView(
controller = controller,
modifier = Modifier.fillMaxSize()
)
// Switch button
IconButton(
onClick = {
scope.launch {
isSwitching = true
delay(100) // Brief delay for smooth animation
controller.toggleCameraLens()
delay(300) // Wait for camera switch
isSwitching = false
}
},
enabled = !isSwitching,
modifier = Modifier
.align(Alignment.TopEnd)
.padding(16.dp)
.background(Color.Black.copy(alpha = 0.5f), CircleShape)
) {
if (isSwitching) {
CircularProgressIndicator(
modifier = Modifier.size(24.dp),
color = Color.White,
strokeWidth = 2.dp
)
} else {
Icon(
imageVector = Icons.Default.Cameraswitch,
contentDescription = "Switch Camera",
tint = Color.White
)
}
}
}
is CameraKState.Error -> Text("Camera error: ${state.message}")
CameraKState.Initializing -> CircularProgressIndicator()
}
}
}
Platform-Specific Behavior¶
Android¶
- Seamless switching via CameraX
- Preview may pause briefly (<100ms)
- Flash settings reset per camera
iOS¶
- Swift AVFoundation switch
- Preview updates smoothly
- Flash/torch settings persist per camera
Desktop¶
- Requires multiple webcams
- Switching cycles through available devices
- Single webcam: no effect
Preserve Settings After Switch¶
Save and restore settings:
fun switchCameraPreserveSettings(controller: CameraController) {
// Save current settings
val savedFlashMode = controller.getFlashMode()
val savedZoom = controller.getZoom()
// Switch camera
controller.toggleCameraLens()
// Wait for switch to complete
scope.launch {
delay(200)
// Restore settings (if supported on new camera)
savedFlashMode?.let { controller.setFlashMode(it) }
controller.setZoom(savedZoom.coerceIn(1f, controller.getMaxZoom()))
}
}
Disable Flash When Switching to Front¶
Most front cameras don't have flash:
fun switchAndAdjustFlash(controller: CameraController) {
controller.toggleCameraLens()
// After switching, check the current lens and adjust flash
val currentLens = controller.getCameraLens()
if (currentLens == CameraLens.FRONT) {
controller.setFlashMode(FlashMode.OFF) // Disable flash for front camera
} else {
controller.setFlashMode(FlashMode.AUTO) // Re-enable flash for back camera
}
}
Animated Camera Icon¶
Show which camera is active:
@Composable
fun AnimatedCameraSwitch() {
val cameraState by rememberCameraKState(config = CameraConfiguration())
var isFrontCamera by remember { mutableStateOf(false) }
val rotation by animateFloatAsState(
targetValue = if (isFrontCamera) 180f else 0f,
animationSpec = tween(durationMillis = 300)
)
Box(modifier = Modifier.fillMaxSize()) {
when (val state = cameraState) {
is CameraKState.Ready -> {
val controller = state.controller
CameraPreviewView(
controller = controller,
modifier = Modifier.fillMaxSize()
)
IconButton(
onClick = {
controller.toggleCameraLens()
isFrontCamera = !isFrontCamera
},
modifier = Modifier
.align(Alignment.TopEnd)
.padding(16.dp)
.background(Color.Black.copy(alpha = 0.5f), CircleShape)
) {
Icon(
imageVector = Icons.Default.Cameraswitch,
contentDescription = "Switch Camera",
tint = Color.White,
modifier = Modifier.graphicsLayer { rotationY = rotation }
)
}
}
is CameraKState.Error -> Text("Camera error: ${state.message}")
CameraKState.Initializing -> CircularProgressIndicator()
}
}
}
Common Issues¶
Preview Freezes After Switch¶
Cause: Camera needs time to reinitialize.
Solution: Add small delay after switch:
controller.toggleCameraLens()
delay(300)
// Camera ready
Flash Doesn't Work After Switching¶
Cause: Front cameras usually lack flash.
Solution: Disable flash UI for front camera:
val currentLens = controller.getCameraLens()
val showFlashButton = currentLens == CameraLens.BACK
Settings Don't Persist¶
Cause: Each camera has independent settings.
Solution: Store settings externally and reapply after switch.
Best Practices¶
- Disable button during switch — Prevent multiple rapid switches
- Show loading indicator — Provide visual feedback
- Reset zoom — Front camera may have different zoom range
- Disable flash for front camera — Avoid confusion
- Test on real devices — Emulators have limited camera support
Next Steps¶
- Flash and Torch — Control lighting per camera
- Zoom Control — Handle different zoom ranges
- Configuration — Set initial camera