{"id":13407057,"url":"https://github.com/qamarelsafadi/ComposeMultiplatform","last_synced_at":"2025-03-14T11:31:00.581Z","repository":{"id":85288193,"uuid":"606167313","full_name":"qamarelsafadi/ComposeMultiplatform","owner":"qamarelsafadi","description":"This repository will contain instructors how you could start your first compose mutltiplatform project ","archived":false,"fork":false,"pushed_at":"2023-08-26T07:42:44.000Z","size":4676,"stargazers_count":141,"open_issues_count":0,"forks_count":11,"subscribers_count":4,"default_branch":"main","last_synced_at":"2024-07-31T20:26:42.426Z","etag":null,"topics":["android","compose","ios","jetpack-compose","kmm","kmm-app","kmm-sample","kotlin","kotlin-multiplatform","kotlin-multiplatform-mobile","kotlin-native","main","maintainermarch"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/qamarelsafadi.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2023-02-24T18:52:34.000Z","updated_at":"2024-07-25T19:40:59.000Z","dependencies_parsed_at":"2024-01-18T11:13:45.018Z","dependency_job_id":"2fe67a4d-c8db-4e7b-8ba6-e489f8c834ea","html_url":"https://github.com/qamarelsafadi/ComposeMultiplatform","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/qamarelsafadi%2FComposeMultiplatform","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/qamarelsafadi%2FComposeMultiplatform/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/qamarelsafadi%2FComposeMultiplatform/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/qamarelsafadi%2FComposeMultiplatform/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/qamarelsafadi","download_url":"https://codeload.github.com/qamarelsafadi/ComposeMultiplatform/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243569302,"owners_count":20312395,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","compose","ios","jetpack-compose","kmm","kmm-app","kmm-sample","kotlin","kotlin-multiplatform","kotlin-multiplatform-mobile","kotlin-native","main","maintainermarch"],"created_at":"2024-07-30T20:00:18.788Z","updated_at":"2025-03-14T11:30:58.644Z","avatar_url":"https://github.com/qamarelsafadi.png","language":"Kotlin","funding_links":[],"categories":["Templates"],"sub_categories":[],"readme":"\n![Logo](https://user-images.githubusercontent.com/30949634/221370655-d88d6aa4-73b8-448c-8834-79a34cabdec8.svg)\n\n\n# Compose Multiplatform \n\nCompose \n\nhttps://user-images.githubusercontent.com/30949634/236697673-dbf52629-9809-41a9-b9fd-8363ea527b99.mov\n\nMultiplatform simplifies and accelerates UI and share it between Android, IOS, Desktop and Web.\n\n\n\u003cbr/\u003e\n\n# Repositroy \n\nThis repository will contain instructions to start your first Compose Multiplatform Project. \n\n\n\n\n## Plugin\n\nInstall \n[KMM](https://plugins.jetbrains.com/plugin/14936-kotlin-multiplatform-mobile)\n plugin in Android Studio \n\n ## Instructions\n - Create a new KMM project using the plugin above\n \n \u003cimg width=\"995\" alt=\"Screenshot 2023-02-25 at 6 58 46 PM\" src=\n\"https://user-images.githubusercontent.com/30949634/221369743-8512eb59-5c5e-4aee-8acb-575856b14ad0.png\"\u003e\n\u003cimg width=\"1440\" alt=\"Screenshot 2023-05-08 at 9 17 35 PM\" src=\"https://user-images.githubusercontent.com/30949634/236900376-f1fc7f3b-8ed3-46f5-a30e-58c5f1ec28ba.png\"\u003e\n\n ### Setup Compose for KMM \n \n in your `settings.gradle` file add the following dependency\n \n```kotlin\npluginManagement {\n    repositories {\n        google()\n        gradlePluginPortal()\n        mavenCentral()\n        maven(\"https://maven.pkg.jetbrains.space/public/p/compose/dev\") // this one\n    }\n    \n   plugins {\n        kotlin(\"jvm\").version(\"1.8.21\")\n        kotlin(\"multiplatform\").version(\"1.8.21\")\n        kotlin(\"android\").version(\"1.8.21\")\n        id(\"com.android.application\").version(\"7.4.2\")\n        id(\"com.android.library\").version(\"7.4.2\")\n        id(\"org.jetbrains.compose\").version(\"1.4.3\")\n    }\n}\n```\n\nin your `build.gradle.kts` add compose plugin\n```kotlin\nplugins {\n    //trick: for the same plugin versions in all sub-modules\n    id(\"com.android.application\").version(\"8.2.0-alpha06\").apply(false)\n    id(\"com.android.library\").version(\"8.2.0-alpha06\").apply(false)\n    kotlin(\"android\").version(\"1.8.21\").apply(false)\n    kotlin(\"multiplatform\").version(\"1.8.21\").apply(false)\n}\n\n\n\n```\n\nnow inside `shared module` `build.gradle.kts` add these two plugins \n```kotlin\nplugins {\n    kotlin(\"multiplatform\")\n    id(\"com.android.library\")\n    kotlin(\"native.cocoapods\") // this \n    id(\"org.jetbrains.compose\") // and this\n}\n\n```\n\nin your `kotlin` block add the following lines \n```kotlin\n  iosX64()\n  iosArm64()\n  iosSimulatorArm64()\n  cocoapods {\n        version = \"1.0.0\"\n        summary = \"Some description for the Shared Module\"\n        homepage = \"Link to the Shared Module homepage\"\n        ios.deploymentTarget = \"14.1\"\n        podfile = project.file(\"../iosApp/Podfile\")\n        framework {\n            baseName = \"shared\"\n            isStatic = true\n        }\n        extraSpecAttributes[\"resources\"] = \"['src/commonMain/resources/**', 'src/iosMain/resources/**']\" // this is for images \n    }\n    \n    // in android block add these lines to support common resources\n    \n    sourceSets[\"main\"].manifest.srcFile(\"src/androidMain/AndroidManifest.xml\")\n    sourceSets[\"main\"].res.srcDirs(\"src/androidMain/res\")\n    sourceSets[\"main\"].resources.srcDirs(\"src/commonMain/resources\")\n    \n```\n\nnow BEFORE you sync you need to make sure about the following: \n\n- Install cocoapods  \n```termial\nbrew install cocoapods\n\n```\n- cd to iosApp and init pod \n```terminal\n pod init\n```\n- install your pods\n```terminal\npod install\n```\n\nIn `sourceSets`\n\n```kotlin\n    sourceSets {\n        val commonMain by getting {\n           dependencies {\n                implementation(compose.runtime)\n                implementation(compose.foundation)\n                implementation(compose.material)\n                @OptIn(org.jetbrains.compose.ExperimentalComposeLibrary::class)\n                implementation(compose.components.resources)\n            }\n        }\n       val androidMain by getting {\n            dependencies {\n                api(\"androidx.activity:activity-compose:1.6.1\")\n                api(\"androidx.appcompat:appcompat:1.6.1\")\n                api(\"androidx.core:core-ktx:1.9.0\")\n            }\n        }\n        val iosX64Main by getting\n        val iosArm64Main by getting\n        val iosSimulatorArm64Main by getting\n        val iosMain by getting {\n            dependsOn(commonMain)\n            iosX64Main.dependsOn(this)\n            iosArm64Main.dependsOn(this)\n            iosSimulatorArm64Main.dependsOn(this)\n        }\n    }\n```\n\nand to avoid Compose targets '[uikit]' are experimental and may have bugs! Error add this in `gradle.properties`\n```groovy\norg.jetbrains.compose.experimental.uikit.enabled=true\n\n```\n\nSync now !\n\n## Let the magic begin \n\nInside your `shared module` commonMain directory create your first Composable function to use it for Android and IOS\n\n```kotlin\n@Composable\ninternal fun App(){\n    Text(Greeting().greet())\n}\n```\n\nIn your `AndroidMain` make `main.android` class to use your App function \n```kotlin\n@Composable\nfun Application(){\n    App()\n}\n```\n\n\nIn your `IosMain` make `main.ios` class to use your App function \n```kotlin\nimport androidx.compose.ui.window.ComposeUIViewController\n\nfun MainViewController() = ComposeUIViewController { App() }\n\n```\n\nNow go to `AndoroidApp` module to use the function we made in main.android class\n```kotlin\n     Surface(\n                    modifier = Modifier.fillMaxSize(),\n                    color = MaterialTheme.colors.background\n                ) {\n                    Application()\n                }\n```\n\nNext go to `IosApp`  module to use the function we made in main.ios class\n\n\n```swift\nimport shared // this important to import don't forget it! \n\n@main\nstruct iOSApp: App {\n    var body: some Scene {\n        WindowGroup {\n            ContentView()\n        }\n     }\n  }\n  \n // inside your ContentView class  \n \nimport SwiftUI\nimport shared\n\nstruct ComposeView: UIViewControllerRepresentable {\n    func makeUIViewController(context: Context) -\u003e UIViewController {\n        Main_iosKt.MainViewController()\n    }\n\n    func updateUIViewController(_ uiViewController: UIViewController, context: Context) {}\n}\n\nstruct ContentView: View {\n    var body: some View {\n        ComposeView()\n                .ignoresSafeArea(.keyboard) // Compose has own keyboard handler\n    }\n}\n\n```\n\n## Run \n\nAdd this to solve dependencies conflicts in `gradle.properties` \n```groovy\nkotlin.native.cacheKind=none\n```\n\nnow you can run your android normally, for `IOS` you need to run the following command first \n\n```terminal\n ./gradlew build\n ./gradlew :shared:linkPodDebugFrameworkIosSimulatorArm64\n\n```\n\nNow open `iosApp.xcworkspace` inside xcode and run the app! or Run it inside Android Studio itself\n\n\n\n## Resources \n\n[JetBrains Compose](https://github.com/JetBrains/compose-jb/tree/master/tutorials/Getting_Started)\n\n[Compose Mutliplatofrom Examples](https://github.com/JetBrains/compose-jb/tree/master/experimental/examples)\n\n[Compose Mutliplatofrom Template](https://github.com/JetBrains/compose-multiplatform-ios-android-template)\n\n\n\n\u003cbr/\u003e\n\u003cbr/\u003e\n\nHappy Kotlin 🚀!\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fqamarelsafadi%2FComposeMultiplatform","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fqamarelsafadi%2FComposeMultiplatform","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fqamarelsafadi%2FComposeMultiplatform/lists"}