diff --git a/.gitignore b/.gitignore
index 4cfbd6e..d316997 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,5 +5,7 @@
/buildSrc/build/*
.DS_Store
/build
+*/build/
/captures
.externalNativeBuild
+.kotlin
diff --git a/build.gradle.kts b/build.gradle.kts
index b6ffcdc..b11da72 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -6,6 +6,8 @@ plugins {
alias(libs.plugins.android.library) apply false
alias(libs.plugins.kotlin.android) apply false
alias(libs.plugins.kotlin.compose) apply false
+ alias(libs.plugins.kotlin.multiplatform) apply false
+ alias(libs.plugins.compose.multiplatform) apply false
alias(libs.plugins.maven.publish) apply false
alias(libs.plugins.detekt)
signing
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index a5f5405..cd52a5c 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -19,6 +19,9 @@ material = "1.12.0"
# Compose
androidxComposeBom = "2025.08.00"
+# Compose Multiplatform
+composeMultiplatform = "1.6.10"
+
[libraries]
# Gradle plugins
@@ -46,6 +49,13 @@ androidx-compose-animation = { group = "androidx.compose.animation", name = "ani
androidx-compose-layout = { group = "androidx.compose.foundation", name = "foundation-layout" }
androidx-compose-runtime = { group = "androidx.compose.runtime", name = "runtime" }
+# Compose Multiplatform
+compose-mpp-runtime = { group = "org.jetbrains.compose.runtime", name = "runtime", version.ref = "composeMultiplatform" }
+compose-mpp-ui = { group = "org.jetbrains.compose.ui", name = "ui", version.ref = "composeMultiplatform" }
+compose-mpp-foundation = { group = "org.jetbrains.compose.foundation", name = "foundation", version.ref = "composeMultiplatform" }
+compose-mpp-animation = { group = "org.jetbrains.compose.animation", name = "animation", version.ref = "composeMultiplatform" }
+compose-mpp-material3 = { group = "org.jetbrains.compose.material3", name = "material3", version.ref = "composeMultiplatform" }
+
[plugins]
# Build plugins
android-application = { id = "com.android.application", version.ref = "agp" }
@@ -53,6 +63,10 @@ android-library = { id = "com.android.library", version.ref = "agp" }
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
+# Compose Multiplatform
+kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
+compose-multiplatform = { id = "org.jetbrains.compose", version.ref = "composeMultiplatform" }
+
# Quality plugins
detekt = { id = "io.gitlab.arturbosch.detekt", version.ref = "detektGradlePlugin" }
@@ -72,4 +86,12 @@ compose = [
"androidx-compose-material2",
"androidx-compose-animation",
"androidx-compose-layout"
-]
\ No newline at end of file
+]
+
+compose-mpp = [
+ "compose-mpp-runtime",
+ "compose-mpp-ui",
+ "compose-mpp-foundation",
+ "compose-mpp-animation",
+ "compose-mpp-material3",
+]
diff --git a/library-compose-multiplatform/build.gradle.kts b/library-compose-multiplatform/build.gradle.kts
new file mode 100644
index 0000000..ea78887
--- /dev/null
+++ b/library-compose-multiplatform/build.gradle.kts
@@ -0,0 +1,66 @@
+plugins {
+ alias(libs.plugins.kotlin.multiplatform)
+ alias(libs.plugins.android.library)
+ alias(libs.plugins.compose.multiplatform)
+ alias(libs.plugins.kotlin.compose)
+
+ id(libs.plugins.conventions.lint.get().pluginId)
+}
+
+kotlin {
+ jvmToolchain(ProjectSettings.Kotlin.JvmToolchainVersion)
+
+ // Android target
+ androidTarget {
+ compilations.all {
+ compileTaskProvider.configure {
+ compilerOptions {
+ jvmTarget.set(org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17)
+ }
+ }
+ }
+ }
+
+ // iOS target
+ listOf(
+ iosX64(),
+ iosArm64(),
+ iosSimulatorArm64()
+ ).forEach {
+ it.binaries.framework {
+ baseName = "DonutCompose"
+ isStatic = true
+ }
+ }
+
+ sourceSets {
+ val commonMain by getting {
+ dependencies {
+ implementation(libs.bundles.compose.mpp)
+ }
+ }
+
+ val commonTest by getting {
+ dependencies {
+ implementation(kotlin("test"))
+ }
+ }
+ }
+}
+
+android {
+ namespace = "app.futured.donut.cmp"
+ compileSdk = ProjectSettings.targetSdk
+
+ defaultConfig {
+ minSdk = ProjectSettings.minSdkLibraryCompose
+ }
+
+ testOptions {
+ targetSdk = ProjectSettings.targetSdk
+ }
+
+ lint {
+ targetSdk = ProjectSettings.targetSdk
+ }
+}
diff --git a/library-compose-multiplatform/gradle.properties b/library-compose-multiplatform/gradle.properties
new file mode 100644
index 0000000..dabc816
--- /dev/null
+++ b/library-compose-multiplatform/gradle.properties
@@ -0,0 +1,11 @@
+# Gradle
+org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
+
+# Kotlin
+kotlin.code.style=official
+kotlin.mpp.androidSourceSetLayoutV2AndroidStyleDirs.nowarn=true
+kotlin.mpp.applyDefaultHierarchyTemplate=false
+
+# Android
+android.useAndroidX=true
+android.nonTransitiveRClass=true
diff --git a/library-compose-multiplatform/src/commonMain/kotlin/app/futured/donut/cmp/HelloWorld.kt b/library-compose-multiplatform/src/commonMain/kotlin/app/futured/donut/cmp/HelloWorld.kt
new file mode 100644
index 0000000..00c048b
--- /dev/null
+++ b/library-compose-multiplatform/src/commonMain/kotlin/app/futured/donut/cmp/HelloWorld.kt
@@ -0,0 +1,22 @@
+package app.futured.donut.cmp
+
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+
+/**
+ * Simple Hello World composable for testing Compose Multiplatform setup.
+ * This will work on both Android and iOS.
+ */
+@Composable
+fun HelloWorld() {
+ Box(
+ modifier = Modifier.fillMaxSize(),
+ contentAlignment = Alignment.Center
+ ) {
+ Text(text = "Hello World from Compose Multiplatform! 🍩")
+ }
+}
diff --git a/sample/build.gradle.kts b/sample/build.gradle.kts
index a9ee359..7b713bc 100644
--- a/sample/build.gradle.kts
+++ b/sample/build.gradle.kts
@@ -29,6 +29,7 @@ android {
dependencies {
implementation(project(":library"))
implementation(project(":library-compose"))
+ implementation(project(":library-compose-multiplatform"))
implementation(platform(libs.androidx.compose.bom))
implementation(libs.bundles.compose)
diff --git a/sample/src/main/AndroidManifest.xml b/sample/src/main/AndroidManifest.xml
index d691742..f274f1f 100644
--- a/sample/src/main/AndroidManifest.xml
+++ b/sample/src/main/AndroidManifest.xml
@@ -30,6 +30,10 @@
+
+
diff --git a/sample/src/main/kotlin/app/futured/donutsample/ui/helloworld/HelloWorldActivity.kt b/sample/src/main/kotlin/app/futured/donutsample/ui/helloworld/HelloWorldActivity.kt
new file mode 100644
index 0000000..041ca90
--- /dev/null
+++ b/sample/src/main/kotlin/app/futured/donutsample/ui/helloworld/HelloWorldActivity.kt
@@ -0,0 +1,30 @@
+package app.futured.donutsample.ui.helloworld
+
+import android.os.Bundle
+import androidx.appcompat.app.AppCompatActivity
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.material.MaterialTheme
+import androidx.compose.material.Surface
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.platform.ComposeView
+import app.futured.donut.cmp.HelloWorld
+
+class HelloWorldActivity : AppCompatActivity() {
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ val composeView = ComposeView(this)
+ setContentView(composeView)
+
+ composeView.setContent {
+ MaterialTheme {
+ Surface(
+ modifier = Modifier.fillMaxSize(),
+ color = MaterialTheme.colors.background
+ ) {
+ HelloWorld()
+ }
+ }
+ }
+ }
+}
diff --git a/sample/src/main/kotlin/app/futured/donutsample/ui/main/MainActivity.kt b/sample/src/main/kotlin/app/futured/donutsample/ui/main/MainActivity.kt
index a5cdb66..59fc0e9 100644
--- a/sample/src/main/kotlin/app/futured/donutsample/ui/main/MainActivity.kt
+++ b/sample/src/main/kotlin/app/futured/donutsample/ui/main/MainActivity.kt
@@ -7,6 +7,7 @@ import androidx.appcompat.app.AppCompatActivity
import app.futured.donutsample.R
import app.futured.donutsample.ui.playground.PlaygroundActivity
import app.futured.donutsample.ui.playground.compose.PlaygroundComposeActivity
+import app.futured.donutsample.ui.helloworld.HelloWorldActivity
class MainActivity : AppCompatActivity() {
@@ -21,5 +22,9 @@ class MainActivity : AppCompatActivity() {
findViewById(R.id.compose_sample_button).setOnClickListener {
startActivity(Intent(this, PlaygroundComposeActivity::class.java))
}
+
+ findViewById(R.id.helloworld_sample_button).setOnClickListener {
+ startActivity(Intent(this, HelloWorldActivity::class.java))
+ }
}
}
diff --git a/sample/src/main/res/layout/activity_main.xml b/sample/src/main/res/layout/activity_main.xml
index 39769f1..6a4bfaf 100644
--- a/sample/src/main/res/layout/activity_main.xml
+++ b/sample/src/main/res/layout/activity_main.xml
@@ -28,10 +28,21 @@
android:id="@+id/compose_sample_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
+ android:layout_marginBottom="16dp"
android:text="@string/navigate_to_compose_view"
- app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintBottom_toTopOf="@+id/helloworld_sample_button"
app:layout_constraintTop_toBottomOf="@+id/android_view_sample_button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
+
+
diff --git a/sample/src/main/res/values/strings.xml b/sample/src/main/res/values/strings.xml
index 4eac77f..962a866 100644
--- a/sample/src/main/res/values/strings.xml
+++ b/sample/src/main/res/values/strings.xml
@@ -45,4 +45,5 @@
Android View Sample
Jetpack Compose Sample
+ Hello World CMP
diff --git a/settings.gradle.kts b/settings.gradle.kts
index 09f0633..f46eccd 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -1,15 +1,18 @@
pluginManagement {
repositories {
- gradlePluginPortal()
- mavenCentral()
google()
+ mavenCentral()
+ gradlePluginPortal()
+ maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
}
}
dependencyResolutionManagement {
+ repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
- mavenCentral()
google()
+ mavenCentral()
+ maven("https://maven.pkg.jetbrains.space/public/p/compose/dev")
}
}
@@ -17,6 +20,7 @@ rootProject.buildFileName = "build.gradle.kts"
include(":library")
include(":library-compose")
+include(":library-compose-multiplatform")
include(":sample")
-includeBuild("convention-plugins")
\ No newline at end of file
+includeBuild("convention-plugins")