Flash and Torch Control¶
Control camera flash for photos and torch for continuous light.
Flash Modes¶
Flash fires when capturing photos.
Set Flash Mode¶
controller.setFlashMode(FlashMode.ON)
Options:
- FlashMode.OFF — Flash disabled
- FlashMode.ON — Flash always fires
- FlashMode.AUTO — Flash fires in low light
Toggle Flash Mode¶
Cycle through modes: OFF → ON → AUTO → OFF
controller.toggleFlashMode()
Get Current Mode¶
val currentMode = controller.getFlashMode()
when (currentMode) {
FlashMode.ON -> println("Flash is enabled")
FlashMode.OFF -> println("Flash is disabled")
FlashMode.AUTO -> println("Flash is automatic")
null -> println("Flash not available")
}
Flash UI Example¶
@Composable
fun CameraWithFlash() {
val permissions = providePermissions()
val scope = rememberCoroutineScope()
val stateHolder = rememberCameraKState(permissions = permissions)
val cameraState by stateHolder.cameraState.collectAsStateWithLifecycle()
var flashMode by remember { mutableStateOf(FlashMode.OFF) }
Box(modifier = Modifier.fillMaxSize()) {
when (cameraState) {
is CameraKState.Ready -> {
val controller = (cameraState as CameraKState.Ready).controller
CameraPreviewComposable(
controller = controller,
modifier = Modifier.fillMaxSize()
)
// Flash toggle button
IconButton(
onClick = {
controller.toggleFlashMode()
flashMode = controller.getFlashMode() ?: FlashMode.OFF
},
modifier = Modifier
.align(Alignment.TopEnd)
.padding(16.dp)
.background(Color.Black.copy(alpha = 0.5f), CircleShape)
) {
Icon(
imageVector = when (flashMode) {
FlashMode.ON -> Icons.Default.FlashOn
FlashMode.OFF -> Icons.Default.FlashOff
FlashMode.AUTO -> Icons.Default.FlashAuto
},
contentDescription = "Flash: $flashMode",
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")
CameraKState.Initializing -> CircularProgressIndicator()
}
}
}
Torch Mode¶
Torch provides continuous light (flashlight mode).
Toggle Torch¶
controller.toggleTorchMode() // ON ↔ OFF
Set Torch Mode¶
controller.setTorchMode(TorchMode.ON)
Options:
- TorchMode.ON — Torch enabled
- TorchMode.OFF — Torch disabled
Get Torch State¶
val torchState = controller.getTorchMode()
when (torchState) {
TorchMode.ON -> println("Torch is on")
TorchMode.OFF -> println("Torch is off")
null -> println("Torch not available")
}
Torch UI Example¶
@Composable
fun CameraWithTorch() {
val permissions = providePermissions()
val stateHolder = rememberCameraKState(permissions = permissions)
val cameraState by stateHolder.cameraState.collectAsStateWithLifecycle()
var isTorchOn by remember { mutableStateOf(false) }
Box(modifier = Modifier.fillMaxSize()) {
when (cameraState) {
is CameraKState.Ready -> {
val controller = (cameraState as CameraKState.Ready).controller
CameraPreviewComposable(
controller = controller,
modifier = Modifier.fillMaxSize()
)
// Torch toggle
IconButton(
onClick = {
controller.toggleTorchMode()
isTorchOn = controller.getTorchMode() == TorchMode.ON
},
modifier = Modifier
.align(Alignment.TopStart)
.padding(16.dp)
.background(
if (isTorchOn) Color.Yellow.copy(alpha = 0.7f)
else Color.Black.copy(alpha = 0.5f),
CircleShape
)
) {
Icon(
imageVector = if (isTorchOn) Icons.Default.FlashlightOn
else Icons.Default.FlashlightOff,
contentDescription = if (isTorchOn) "Turn off torch" else "Turn on torch",
tint = if (isTorchOn) Color.Black else Color.White
)
}
}
is CameraKState.Error -> Text("Camera error")
CameraKState.Initializing -> CircularProgressIndicator()
}
}
}
Flash vs Torch¶
| Feature | Flash | Torch |
|---|---|---|
| Use case | Photo capture | Continuous light |
| Activation | Fires during capture | Manual toggle |
| Duration | Brief burst | Stays on until disabled |
| Battery impact | Minimal | High (use sparingly) |
| API | setFlashMode() |
setTorchMode() |
Best practices: - Use flash for taking photos - Use torch for video recording or low-light navigation - Turn off torch when not needed to save battery
Combined Flash and Torch UI¶
@Composable
fun CameraWithLighting() {
val permissions = providePermissions()
val scope = rememberCoroutineScope()
val stateHolder = rememberCameraKState(permissions = permissions)
val cameraState by stateHolder.cameraState.collectAsStateWithLifecycle()
var flashMode by remember { mutableStateOf(FlashMode.AUTO) }
var isTorchOn by remember { mutableStateOf(false) }
Box(modifier = Modifier.fillMaxSize()) {
when (cameraState) {
is CameraKState.Ready -> {
val controller = (cameraState as CameraKState.Ready).controller
CameraPreviewComposable(
controller = controller,
modifier = Modifier.fillMaxSize()
)
// Controls at top
Row(
modifier = Modifier
.align(Alignment.TopCenter)
.padding(16.dp)
.background(Color.Black.copy(alpha = 0.5f), RoundedCornerShape(24.dp))
.padding(horizontal = 8.dp),
horizontalArrangement = Arrangement.spacedBy(8.dp)
) {
// Flash mode
IconButton(onClick = {
controller.toggleFlashMode()
flashMode = controller.getFlashMode() ?: FlashMode.AUTO
}) {
Icon(
imageVector = when (flashMode) {
FlashMode.ON -> Icons.Default.FlashOn
FlashMode.OFF -> Icons.Default.FlashOff
FlashMode.AUTO -> Icons.Default.FlashAuto
},
contentDescription = "Flash: $flashMode",
tint = Color.White
)
}
// Torch toggle
IconButton(onClick = {
controller.toggleTorchMode()
isTorchOn = controller.getTorchMode() == TorchMode.ON
}) {
Icon(
imageVector = if (isTorchOn) Icons.Default.FlashlightOn
else Icons.Default.FlashlightOff,
contentDescription = "Torch",
tint = if (isTorchOn) Color.Yellow else 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")
CameraKState.Initializing -> CircularProgressIndicator()
}
}
}
Configuration: Set Default Flash Mode¶
Set initial flash mode during setup:
val stateHolder = rememberCameraKState(
permissions = permissions,
cameraConfiguration = {
setFlashMode(FlashMode.OFF) // Start with flash disabled
}
)
Platform Availability¶
Android¶
- ✅ Flash: Available on rear cameras
- ✅ Torch: Available on rear cameras
- ❌ Front camera: Usually no flash/torch
iOS¶
- ✅ Flash: Available on rear cameras
- ✅ Torch: Available on rear cameras
- ❌ Front camera: iPhone 12+ has "Retina Flash" (screen flash)
Desktop¶
- ❌ Flash: Not available
- ❌ Torch: Not available
Check availability:
val flashMode = controller.getFlashMode()
if (flashMode != null) {
// Flash is available
} else {
// No flash on this camera
}
Common Issues¶
Flash Not Working¶
Cause: Front camera selected (no flash hardware).
Solution: Switch to rear camera:
controller.setCameraLens(CameraLens.BACK)
Torch Stays On After Closing App¶
Cause: Torch not disabled in cleanup.
Solution: Disable torch when leaving camera:
DisposableEffect(Unit) {
onDispose {
controller.setTorchMode(TorchMode.OFF)
controller.cleanup()
}
}
Flash Mode Resets When Switching Cameras¶
Cause: Each camera has independent flash settings.
Solution: Re-apply flash mode after switching:
controller.toggleCameraLens()
controller.setFlashMode(FlashMode.ON) // Re-apply
Best Practices¶
- Save battery — Turn off torch when not actively needed
- User feedback — Show visual indicator when torch is on
- Cleanup — Always disable torch in
onDisposeor app background - Test on device — Emulators don't have flash/torch
- Front camera — Disable flash UI when front camera active
Next Steps¶
- Zoom Control — Implement zoom functionality
- Camera Switching — Switch between cameras
- Configuration — Default flash settings