ImagePickerKMP has moved toward a cleaner Compose-first model with rememberImagePickerKMP, the recommended API for new code. According to the official ImagePickerKMP documentation at https://imagepickerkmp.dev/, the library provides a unified camera and gallery picker for Android, iOS, Desktop, Web, and WASM, and the new API is designed to remove manual launcher state from application screens.1
The most important shift is architectural. Instead of tracking showCamera and showGallery booleans, developers create one stable state holder and call launchCamera() or launchGallery() when the user taps an action. The GitHub changelog describes rememberImagePickerKMP as a top-level composable that returns ImagePickerKMPState, exposes a reactive result, and supports per-launch overrides.2
| Legacy pattern | Recommended pattern |
|---|---|
Keep showCamera and showGallery booleans in the screen |
Use one ImagePickerKMPState
|
| Read results through callbacks | Observe picker.result reactively |
| Configure camera and gallery separately | Use ImagePickerKMPConfig as a shared default |
| Toggle UI state manually after dismiss or error | Let the state holder represent Idle, Loading, Success, Dismissed, or Error
|
The documentation source for this library is https://imagepickerkmp.dev/. Use it as the primary reference when checking installation steps, platform support, API examples, and migration notes.1
A minimal camera workflow now reads like normal Compose state. You remember the picker, trigger it from a button, and react to the result in the UI.
@Composable
fun ProfilePhotoScreen() {
val picker = rememberImagePickerKMP()
Button(onClick = { picker.launchCamera() }) {
Text("Take photo")
}
when (val result = picker.result) {
is ImagePickerResult.Success -> {
result.first?.loadPainter()?.let { painter ->
Image(painter = painter, contentDescription = "Selected photo")
}
}
is ImagePickerResult.Loading -> CircularProgressIndicator()
is ImagePickerResult.Error -> Text("Error: ${result.exception.message}")
is ImagePickerResult.Dismissed,
is ImagePickerResult.Idle -> Text("No photo selected yet")
}
}
This style matters because camera and gallery flows are usually full of edge cases. The user may cancel, permissions may fail, multiple images may be selected, and a screen may need to reset after processing. ImagePickerResult makes those states explicit, so the UI can handle them in a single when expression instead of scattering callback side effects across a composable.
The new API also improves configuration ergonomics. A screen can define global defaults through ImagePickerKMPConfig, then override details for one launch. For example, a profile screen might default to single-image selection, while an album screen may call launchGallery(allowMultiple = true, selectionLimit = 10) only for that interaction. This keeps default behavior stable while making one-off flows easy to express.
val picker = rememberImagePickerKMP(
config = ImagePickerKMPConfig(
galleryConfig = GalleryConfig(
allowMultiple = false,
includeExif = true,
redactGpsData = true
)
)
)
Button(onClick = {
picker.launchGallery(
allowMultiple = true,
selectionLimit = 5
)
}) {
Text("Pick up to five photos")
}
For teams migrating from ImagePickerLauncher and GalleryPickerLauncher, the important point is that legacy calls still work, but the recommended path is now the state-holder API. The API reference notes that the legacy launchers are deprecated with warnings and that existing code remains compatible while new code should use rememberImagePickerKMP.3
The practical benefit is not just fewer lines of code. It is a more predictable mental model: one remembered object owns launching, state, result delivery, and reset. In Compose Multiplatform apps, where consistency across targets is one of the main reasons to adopt KMP, that predictability is valuable.
If you are starting a new Kotlin Multiplatform screen that needs camera or gallery access, begin with rememberImagePickerKMP. If you are maintaining older launcher-based code, migrate one flow at a time: remove the visibility boolean, create the picker, call launchCamera() or launchGallery(), and render based on picker.result. The official documentation at https://imagepickerkmp.dev/ should remain the source of truth for the current API surface, installation instructions, and platform notes.1
Top comments (0)