📂 Kotlin Multiplatform library for Compose Multiplatform, designed for seamless integration of an image picker feature in iOS and Android applications.
peekaboo
is based on Compose Multiplatform
, currently targeting only iOS
and Android
.
Please note that it primarily focuses on these platforms, and additional platforms may be considered in the future.
When using peekaboo
on Android, ensure that Google's Jetpack Compose version is compatible with peekaboo
's Compose Multiplatform version.
The minimum supported Android SDK is 24 (Android 7.0).
In your commonMain
configuration, add the desired dependency, either peekaboo-ui
or peekaboo-image-picker
, to your project. Both are available on Maven Central.
commonMain {
dependencies {
// peekaboo-ui
implementation("io.github.team-preat:peekaboo-ui:$latest_version")
// peekaboo-image-picker
implementation("io.github.team-preat:peekaboo-image-picker:$latest_version")
}
}
First, define the version in libs.versions.toml
:
[versions]
peekaboo = "0.3.0"
[libraries]
peekaboo-ui = { module = "io.github.team-preat:peekaboo-ui", version.ref = "peekaboo" }
peekaboo-image-picker = { module = "io.github.team-preat:peekaboo-image-picker", version.ref = "peekaboo" }
Then, in your commonMain
configuration, reference the defined version:
commonMain {
dependencies {
// peekaboo-ui
implementation(libs.peekaboo.ui)
// peekaboo-image-picker
implementation(libs.peekaboo.image.picker)
}
}
Name | Description |
---|---|
peekaboo-ui |
Provides user-friendly UI elements, including a custom camera view for easy image capture, suitable for both iOS and Android platforms. |
peekaboo-image-picker |
Simplifies the process of selecting single or multiple images both in iOS and Android platforms. |
In order to access the camera on iOS devices, it's essential to include a specific key-value pair in the Info.plist
file of your iOS project. This key-value pair comprises a key that identifies the type of permission being requested and a value that provides a user-friendly description explaining why the app needs access to the camera.
Here's the key-value pair you should add to your Info.plist
:
<key>Privacy - Camera Usage Description</key>
<string>This app uses camera for capturing photos.</string>
PeekabooCamera
is a composable
function that provides a customizable camera UI within a Compose Multiplatform
application.
@Composable
fun CustomCameraView() {
PeekabooCamera(
modifier = Modifier.fillMaxSize(),
cameraMode = CameraMode.Back, // or CameraMode.Front
captureIcon = { onClick -> /* Custom Capture Button UI */ },
convertIcon = { onClick -> /* Custom Convert Button UI */ },
progressIndicator = { /* Custom Progress Indicator UI */ },
onCapture = { byteArray ->
// Handle the captured image
},
permissionDeniedContent = {
// Custom UI content for permission denied scenario
}
)
}
cameraMode
: The initial camera mode (front or back). Default isCameraMode.Back
.captureIcon
: Acomposable
lambda for the capture button. It takes anonClick
lambda that triggers the image capture process.convertIcon
: An optionalcomposable
lambda for a button to toggle the camera mode (front or back). It takes anonClick
lambda for switching the camera.progressIndicator
: An optionalcomposable
lambda displayed during photo capture processing.onCapture
: A lambda called when a photo is captured, providing the photo as aByteArray
ornull
if the capture fails.permissionDeniedContent
: An optionalcomposable
lambda that provides content to be displayed when camera permission is denied. This allows users to define a custom UI to inform or guide the user when camera access has been denied. The content can be informative text, an image, a button to redirect the user to settings, or any othercomposable
content. This lambda will be invoked within thePeekabooCamera
composable scope, replacing the camera preview with the user-defined UI.
💡 Note: It's recommended to handle camera permission checks before rendering
PeekabooCamera
. This preemptive check ensures the camera UI is displayed only when permissions are granted, avoiding empty views or unexpected user experiences.
Android | iOS |
---|---|
Android | iOS |
---|---|
Android | iOS |
---|---|
val scope = rememberCoroutineScope()
val singleImagePicker = rememberImagePickerLauncher(
selectionMode = SelectionMode.Single,
scope = scope,
onResult = { byteArrays ->
byteArrays.firstOrNull()?.let {
// Process the selected images' ByteArrays.
println(it)
}
}
)
Button(
onClick = {
singleImagePicker.launch()
}
) {
Text("Pick Single Image")
}
Android | iOS |
---|---|
Simply select the desired image with an intuitive interface.
If you want to select multiple images, you can use SelectionMode.Multiple()
. And you can set the maximum number of images to select.
If you didn't set max selection, the default value is maximum number that the system supports.
val scope = rememberCoroutineScope()
val multipleImagePicker = rememberImagePickerLauncher(
// Optional: Set a maximum selection limit, e.g., SelectionMode.Multiple(maxSelection = 5).
// Default: No limit, depends on system's maximum capacity.
selectionMode = SelectionMode.Multiple(maxSelection = 5),
scope = scope,
onResult = { byteArrays ->
byteArrays.forEach {
// Process the selected images' ByteArrays.
println(it)
}
}
)
Button(
onClick = {
multipleImagePicker.launch()
}
) {
Text("Pick Multiple Images")
}
Android | iOS |
---|---|
We've added a new extension function toImageBitmap()
to convert a ByteArray
into an ImageBitmap
.
This function simplifies the process of converting image data into a displayable format, enhancing the app's capability to handle image processing efficiently.
val imageBitmap = byteArray.toImageBitmap()
Contributions are always welcome!
If you'd like to contribute, please feel free to create a PR or open an issue. 👍
Support it by joining stargazers for this repository. ⭐
Copyright 2023 onseok
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.