Memento is a powerful and customizable image editor library for Kotlin Multiplatform, inspired by Instagram Stories. It allows you to effortlessly add, edit, and manipulate text and images on a canvas, all with intuitive gestures.
Built with Jetpack Compose for Multiplatform, Memento provides a seamless experience on both Android and iOS.
- Multiplatform: Write your UI logic once and run it on both Android and iOS.
- Gesture-driven: Easily move, scale, and rotate elements with familiar touch gestures.
- Text Editing: Add and customize text with various colors and styles.
- Image Overlays: Add images or stickers on top of your main content.
- Layer Management: Control the stacking order of different elements.
- State Management: A robust
MementoControllerto manage the state of your creations. - Capture & Export: Capture the final edited canvas as an
ImageBitmap.
Memento is available on Maven Central.
-
Make sure you have
mavenCentral()in your top-levelbuild.gradle.ktsfile:repositories { mavenCentral() } -
Add the desired dependency to your module's
build.gradle.ktsfile:dependencies { // For the full UI editor experience (includes core) implementation("my.takealook.memento:memento-ui:<latest-version>") // Or if you only need the core logic implementation("my.takealook.memento:memento-core:<latest-version>") }Always check for the latest version on Maven Central.
Getting started with the MementoEditor is simple. Just add the composable to your UI:
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import my.takealook.memento.MementoEditor
import my.takealook.memento.rememberMementoController
@Composable
fun MyEditorScreen() {
val mementoController = rememberMementoController()
MementoEditor(
modifier = Modifier.fillMaxSize(),
controller = mementoController,
onImageCaptured = { imageBitmap ->
// Handle the captured image
},
mainContent = {
// Your main content goes here, e.g., an Image
Image(
painter = painterResource(Res.drawable.my_background_image),
contentDescription = "Background"
)
}
)
// You can control the editor externally
Button(onClick = { mementoController.requestCapture() }) {
Text("Save Image")
}
}memento-core: Contains the core logic, state management (MementoController,MementoState), and data classes. It's UI-agnostic.memento-ui: Provides theMementoEditorComposable and other UI components built onmemento-corefor a ready-to-use editor experience.
Memento is also available on Swift Package Manager.
You can add MementoUI to your Xcode project as a Swift Package.
- In Xcode, go to
File > Add Packages... - Enter the repository URL:
https://github.com/easternkite/memento.git - Choose the
MementoUiproduct.
Here's a basic example of how to integrate MementoUI into your SwiftUI application.
First, ensure you import MementoUi in your Swift files:
import SwiftUI
import UIKit
import MementoUi
struct ComposeView: UIViewControllerRepresentable {
var controller : MementoController!
init(_ controller: MementoController) {
self.controller = controller
}
func makeUIViewController(context: Context) -> UIViewController {
return MementoEditorViewControllerKt.MementoEditorViewController(
mainContent: UIImage(named: "ic_milk")!,
controller: controller,
onImageCaptured: { image in saveImageToGallery(image) }
)
}
func updateUIViewController(_ uiViewController: UIViewController, context: Context) {}
}
struct ContentView: View {
@State var controller: MementoController = MementoController()
var body: some View {
ZStack(alignment: .topTrailing) {
ComposeView(controller)
.ignoresSafeArea(.all) // Compose has own keyboard handler
//...
}
}
}For optimal performance and smooth animations, especially on iOS devices, it is crucial to add the CADisableMinimumFrameDurationOnPhone key to your application's Info.plist file and set its value to YES (Boolean).
This setting disables a system-imposed minimum frame duration, allowing your app to render at higher frame rates when possible, which is particularly beneficial for UI-intensive applications like image editors.
How to add it:
- Open your
Info.plistfile in Xcode. - Right-click on an empty area in the property list editor and choose
Add Row. - For the
Key, enterCADisableMinimumFrameDurationOnPhone. - For the
Type, selectBoolean. - For the
Value, set it toYES.
Alternatively, you can add the following XML snippet directly to your Info.plist file:
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>This project is licensed under the Apache License, Version 2.0. See the LICENSE.txt file for details.
