A Kotlin library to use Jetpack Compose in Android and iOS. Allow to write UI for both in Kotin. Still experimental as many compose features are not yet available.

Overview

Kotlin Multiplatform

Multiplatform Compose

A Kotlin library to use Jetpack Compose in Android and iOS. Allow to write UI for both in Kotin. Still experimental as many compose features are not yet available.

Table of contents

Requirements

  • Android Studio Canary
  • cocoapods (gem install cocoapods)
  • cocoapods-generate (gem install cocoapods-generate)

Installation

The library is not yet published to Maven Central as it is still experimental.

Usage

The simpliest code is :

@Composable
fun Content(resources: Resources) {
    Text("Hello world!")
}

A better start would be :

@Composable
fun Content(resources: Resources) {
    HelloPlatform()
}

@Composable
fun HelloPlatform() {
    Column(
        modifier = Modifier.fillMaxSize(),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally) {
            Text("Hello, ${Platform().platform}!")
    }
}

Hello Platform Screenshot

More advance sample are in the demos directory of the test library.

Image

The image composable allow url loading

Image(url = "https://loremflickr.com/320/240/ocean", modifier = Modifier.preferredSize(200.dp))

iOS Composables

HumanAppearance

Allow iOS styling such as font or global tintColor.

HumanAppearance(tintColor: Color, backgroundColor: Color?, style: TextStyle) {
    // ...
}

SafeArea

Add safe area insets to the view, works in root, TabView and NavigationView

SafeArea {
    // ...
}

Safe Area Screenshot Layout without the safe area, with the safe area and on android

TabView

UITabBarController for Compose

TabView {
    Tab(title = "First", image = UIImage.systemImageNamed("a.circle.fill")) {
      // ...
    }
    Tab(title = "Second", image = UIImage.systemImageNamed("a.circle.fill")) {
      // ...
    }
}

NavigationView

UINavigationController for Compose, renamed to NavHost but as additional parameter title, leadingButton and trailingButton in composable

val navController = rememberNavController()
NavHost(navController = navController, startDestination = "first") {
    composable("first", title = "First", trailingButton = Button(onClick = {}) { Text ("Edit") }) {
			SafeArea {
	    Button(onClick = { navController.navigate("second") }) { 
                // ...
            }
        }
    }
    composable("second", title = "Second") {
        SafeArea {
	    // ...
        }
    }
}

Known issues

  • Jetpack Compose require Android Studio Canary and an alpha build of Gradle. There is some workaround in build.gradle.kts to make it work (testApi).
  • Jetpack Compose is not supported in Kotlin Multiplatform Mobile library (KT-38694). Unfortunatly, the workaround was messing with actual/expect function and prevent the use of expect function with default value. The library now use @Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") to workaround this problem. If you use an expect function with default value and without the suppress, you will get an error function not found or java.lang.IllegalStateException: 2. expected value parameter count to be higher.
  • Jetpack Compose dependencies can not be used in commonMain because they have a dependency on kotlinx-coroutines-android.
  • Android Studio does not autocomplete cocoapods imported library in iosMain. Thus it is in iosx64Main and symlinked to iosArm64Main.
  • Images needs currently to be included in the android and ios resources separately.
  • Navigation is currently not shared in the library
  • Latest Android Studio Canary shows many undefined error but everthing compile fine. It was not the case before.

Troubleshooting

cinteropYogaKitIosArm64 FAILED YogaKit module not found

You did not read the requirements. Install cocoapods-generate "gem install cocoapods-generate", invalid cache and restat Android Studio

Roadmap

  • More Jetpack Compose feature support
  • Better images/resources support
  • UI Test with Github Actions
  • Performance improvement/optimisation
  • Use Compose compiler and runtime on iOS

Sponsors

No one yet, be the first sponsor!

Contributing

All development (both new features and bug fixes) is performed in the develop branch. This way master always contains the sources of the most recently released version. Use git-flow if possible.

You can start a PR with incomplete implementation to shows what you are working on. Please send PRs with bug fixes or new features to the develop branch. Documentation fixes in the markdown files are an exception to this rule. They are updated directly in master.

The develop branch is pushed to master on release.

License

Copyright 2021 Clément Beffa

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

   http://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.
Comments
  • Builds for iOS fail when using material3

    Builds for iOS fail when using material3

    If I add compose.material3 to my project and use any of its classes in my code, it works fine on Android, but on iOS it fails with the following error message:

    e: java.lang.RuntimeException: Failed to compute the detailed error message. See the root cause exception.
    
    Shortly: The required symbol androidx.compose.material3/Surface|-7040802471905007841[0] is missing in the module or module dependencies. This could happen if the required dependency is missing in the project. Or if there is a dependency that has a different version (without the required symbol) in the project than the version (with the required symbol) that the module was initially compiled with.
    
    opened by Tiebe 1
  • Fix missing secondaryVariant in darkColors and Color space crash

    Fix missing secondaryVariant in darkColors and Color space crash

    Fix a missing reference to the secondaryVariant (value from default reference)

    Also references issue #7 where starting the app from the checked out repository will instantly crash due to the ColorSpace management from (If I'm not wrong the unsigned forced definition will trigger this out of bounds inside Android x getColorSpace applied with value and 0x3fUL)

    opened by codlab 1
  • java.lang.ArrayIndexOutOfBoundsException on start

    java.lang.ArrayIndexOutOfBoundsException on start

    I'm having an AOB when using the latest version when starting the application on Android (100% reproducible, repository clean)

    I'm creating this issue in parallel from testing few things as well

    Some contextual information :

    • Android version : 12
    • Model : Fold 3 / SM-F926B
    • commit d9236ff345
    • Android Studio 2021.1.1 Patch 2
    java.lang.ArrayIndexOutOfBoundsException: length=18; index=18
    at androidx.compose.ui.graphics.Color.getColorSpace-impl(Color.kt:670)
    at androidx.compose.ui.graphics.ColorKt.compositeOver--OWjLjI(Color.kt:559)
    at androidx.compose.material.MaterialTextSelectionColorsKt.calculateContrastRatio-nb2GgbA(MaterialTextSelectionColors.kt:199)
    at androidx.compose.material.MaterialTextSelectionColorsKt.calculateSelectionBackgroundColor-ysEtTa8(MaterialTextSelectionColors.kt:83)
    at androidx.compose.material.MaterialTextSelectionColorsKt.rememberTextSelectionColors(MaterialTextSelectionColors.kt:51)
    at androidx.compose.material.MaterialThemeKt.MaterialTheme(MaterialTheme.kt:71)
    at com.rouge41.kmm.compose.material.MaterialThemeKt.MaterialTheme(MaterialTheme.kt:14)
    at com.rouge41.kmm.compose.test.ThemeKt.Theme(Theme.kt:20)
    at com.rouge41.kmm.compose.test.ContentKt.Content(Content.kt:13)
    at com.rouge41.kmm.compose.androidApp.MainActivity$onCreate$1.invoke(MainActivity.kt:26)
    at com.rouge41.kmm.compose.androidApp.MainActivity$onCreate$1.invoke(MainActivity.kt:25)
    

    Fullstack here : fullstack.txt

    opened by codlab 1
  • Execution failed for task ':multiplatform-compose:cinteropYogaKitIosArm64' finished with non-zero exit value 1

    Execution failed for task ':multiplatform-compose:cinteropYogaKitIosArm64' finished with non-zero exit value 1

    I have installed cocoapod and cocoapod-generator, but get blow error.

    MAC: ​

    ​MacBook Pro (13-inch, M1, 2020).   
    

    Android Studio:

    Android Studio Chipmunk | 2021.2.1 Canary 7
    Build #AI-212.5457.46.2112.8043657, built on January 5, 2022
    Runtime version: 11.0.12+0-b1504.28-7817840 aarch64
    VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o.
    macOS 12.1
    GC: G1 Young Generation, G1 Old Generation
    Memory: 4096M
    Cores: 8
    Registry: external.system.auto.import.disabled=true, ide.instant.shutdown=false
    Non-Bundled Plugins: com.intellij.lang.jsgraphql (3.1.2), com.jetbrains.kmm (0.3.0(212-1.6.0-release-795-IJ)-132)
    

    Error:

    Execution failed for task ':multiplatform-compose:cinteropYogaKitIosArm64'.
    > Process 'command '/Applications/Android Studio Preview C.app/Contents/jre/Contents/Home/bin/java'' finished with non-zero exit value 1
    
    * Try:
    Run with --info or --debug option to get more log output. Run with --scan to get full insights.
    
    * Exception is:
    org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':multiplatform-compose:cinteropYogaKitIosArm64'.
    	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.lambda$executeIfValid$3(ExecuteActionsTaskExecuter.java:186)
    	at org.gradle.internal.Try$Failure.ifSuccessfulOrElse(Try.java:268)
    	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeIfValid(ExecuteActionsTaskExecuter.java:184)
    	at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:173)
    	at org.gradle.api.internal.tasks.execution.CleanupStaleOutputsExecuter.execute(CleanupStaleOutputsExecuter.java:109)
    	at org.gradle.api.internal.tasks.execution.FinalizePropertiesTaskExecuter.execute(FinalizePropertiesTaskExecuter.java:46)
    	at org.gradle.api.internal.tasks.execution.ResolveTaskExecutionModeExecuter.execute(ResolveTaskExecutionModeExecuter.java:62)
    	at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:57)
    	at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:56)
    	at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:36)
    	at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.executeTask(EventFiringTaskExecuter.java:77)
    	at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:55)
    	at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:52)
    	at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:200)
    	at org.gradle.internal.operations.DefaultBuildOperationRunner$CallableBuildOperationWorker.execute(DefaultBuildOperationRunner.java:195)
    	at org.gradle.internal.operations.DefaultBuildOperationRunner$3.execute(DefaultBuildOperationRunner.java:75)
    	at org.gradle.internal.operations.DefaultBuildOperationRunner$3.execute(DefaultBuildOperationRunner.java:68)
    	at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:153)
    	at org.gradle.internal.operations.DefaultBuildOperationRunner.execute(DefaultBuildOperationRunner.java:68)
    	at org.gradle.internal.operations.DefaultBuildOperationRunner.call(DefaultBuildOperationRunner.java:62)
    	at org.gradle.internal.operations.DefaultBuildOperationExecutor.lambda$call$2(DefaultBuildOperationExecutor.java:76)
    	at org.gradle.internal.operations.UnmanagedBuildOperationWrapper.callWithUnmanagedSupport(UnmanagedBuildOperationWrapper.java:54)
    	at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:76)
    	at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:52)
    	at org.gradle.execution.plan.LocalTaskNodeExecutor.execute(LocalTaskNodeExecutor.java:41)
    	at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:411)
    	at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:398)
    	at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:391)
    	at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:377)
    	at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.lambda$run$0(DefaultPlanExecutor.java:127)
    	at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.execute(DefaultPlanExecutor.java:191)
    	at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.executeNextNode(DefaultPlanExecutor.java:182)
    	at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.run(DefaultPlanExecutor.java:124)
    	at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
    	at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
    	at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56)
    Caused by: org.gradle.process.internal.ExecException: Process 'command '/Applications/Android Studio Preview C.app/Contents/jre/Contents/Home/bin/java'' finished with non-zero exit value 1
    	at org.gradle.process.internal.DefaultExecHandle$ExecResultImpl.assertNormalExitValue(DefaultExecHandle.java:414)
    	at org.gradle.process.internal.DefaultJavaExecAction.execute(DefaultJavaExecAction.java:42)
    	at org.gradle.process.internal.DefaultExecActionFactory.javaexec(DefaultExecActionFactory.java:168)
    	at org.gradle.api.internal.project.DefaultProject.javaexec(DefaultProject.java:1156)
    	at org.jetbrains.kotlin.compilerRunner.KotlinToolRunner.runViaExec(KotlinToolRunner.kt:77)
    	at org.jetbrains.kotlin.compilerRunner.KotlinToolRunner.run(KotlinToolRunner.kt:73)
    	at org.jetbrains.kotlin.gradle.tasks.CInteropProcess.processInterop(KotlinNativeTasks.kt:981)
    ``
    opened by Tans5 1
  • Jetpack Canvas Graphics API

    Jetpack Canvas Graphics API

    Have you considered implementing the new Canvas API for iOS? It does seem like a big project but it would be a pretty amazing API. Multi-platform drawing with a modern declarative style! I guess it could be nice to wait for Swift interop to write it in the new similar Paths and Shapes API in SwiftUI.

    opened by CarsonRedeye 1
  • Fitting in SwiftUI

    Fitting in SwiftUI

    Would it be possible to fit Swift UI into the current implementation? From what it seems, current components are fully based on UI Kit

    Although Swift UI is only supported by the newer platforms, it seems very interesting to use: it is simple yet powerful. Would it be a match?

    opened by RdeWilde 1
Owner
Clément Beffa
Mobile Developer
Clément Beffa
Experimental Graphviz code generation POC built with Jetpack Compose compiler/runtime.

Compose Dot Experimental proof of concept to generate GraphViz dot code via Jetpack Compose's tree management. Valid dot file content can be generated

Arunkumar 29 Sep 14, 2022
An application that i developed with a aim of learning Jetpack compose and many other jetpack libraries

An application that i developed with a aim of learning Jetpack compose and many other jetpack libraries, The application make use of jikan Api which displays a list of animations,there more details and even trailers of the animations.

Odhiambo Brandy 10 Nov 23, 2022
Highly experimental routing feature for Compose Web

RoutingCompose Highly experimental routing feature for Compose Web Install This package is uploaded to GitHub Packages. repositories { maven {

Philip Wedemann 86 Dec 20, 2022
Pokedex Compose is an independent re-write of a demo application by the name of Pokedex, but written in jetpack compose.

Pokedex Compose Pokedex Compose is an independent re-write of a similar project by the name of Pokedex. I am recreating the UI but I am doing it using

Jose Patino 4 May 1, 2022
Yet another ToDo app, but the UI completely written in Jetpack Compose!

Yet another ToDo app, but the UI completely written in Jetpack Compose!

Wisnu Kurniawan 134 Dec 31, 2022
🔥 Yet another Tinder like swipeable cards, built for Jetpack Compose

twyper Yet another Tinder like swipeable card library, built for Jetpack Compose ✨ Demo Screen.Recording.2022-02-20.at.10.46.59.PM.mov ⌨️ Usage 1. Add

theapache64 88 Dec 24, 2022
Make your device sip only small amounts of battery when not in use.

trickle Make your device sip only small amounts of battery when not in use. What Automatically place your device into battery-saver mode when the scre

pyamsoft 3 Dec 21, 2022
Yet another awesome Intro screen library 🔥

Compose-Intro ✅ Yes, I'm too bad in naming my libraries : ) Yet another Intro Screen library made with the love of Kotlin and Jetpack compose : ) ❤️ ✨

Kapil Yadav 13 Aug 14, 2022
Jetpack Compose based project, used to stress-testing compose features / integrations and explore non-trivial functionality

Project containing Jetpack Compose samples For pagination & network images it uses CATAAS. Known issues Navigation-Compose Issue with fast tapping on

Denis Rudenko 59 Dec 14, 2022
An android library to highlight different features of the app built using Jetpack Compose.

An android library to highlight different features of the app built using Jetpack Compose.

Canopas Software 230 Dec 23, 2022
Dynamic Badge with customizable features as max number before displaying with +, color, shadow, border, corner radius, font properties and more written with Jetpack Compose

✏️?? Dynamic Badge with customizable features as max number before displaying with +, color, shadow, border, corner radius, font properties and more written with Jetpack Compose. Displays numbers either in circle or rounded rectangle shape based on badge count and selected threshold to transform from circle to rounded rectangle.

Smart Tool Factory 4 Jul 27, 2022
Learn Jetpack Compose for Android by Examples. Learn how to use Jetpack Compose for Android App Development. Android’s modern toolkit for building native UI.

Learn Jetpack Compose for Android by Examples. Learn how to use Jetpack Compose for Android App Development. Android’s modern toolkit for building native UI.

MindOrks 382 Jan 5, 2023
Recreated iOS Calculator UI and functionality for android with Jetpack Compose

Compose-iOS-Calculator Recreated iOS Calculator UI and functionality for android with Jetpack Compose Currently using Regex to do the math, but when I

Ikechukwu Eze 6 Oct 11, 2022
A library that adds useful features for Compose Desktop apps

Desktopose This is a set of utilities and components meant to help with developing desktop apps that use Compose for Desktop library. It contains the

Szeweq 3 Nov 21, 2022
A simple authentication application using Jetpack compose to illustrate signin and sign up using Mvvm, Kotlin and jetpack compose

Authentication A simple authentication application using Jetpack compose to illustrate signin and sign up using Mvvm, Kotlin and jetpack compose Scree

Felix Kariuki 5 Dec 29, 2022
A library that you can use in 4 different types toast written with Jetpack Compose

Composable Sweet Toast A library that you can use in 4 different types(Success, Error, Warning, Info) written with Jetpack Compose. You can use this t

Talha Fakıoğlu 67 Dec 19, 2022
A library that you can use in 4 different types(Success, Error, Warning, Info) written with Jetpack Compose.

Composable Sweet Toast A library that you can use in 4 different types(Success, Error, Warning, Info) written with Jetpack Compose. You can use this t

Talha Fakıoğlu 67 Dec 19, 2022
A playground to showcase cool IDE features.

Let the IDE do that for you It's not being lazy if it makes you more productive ??️ Sebastiano Poggi Lead on Package Search at JetBrains Android, Flut

Sebastiano Poggi 13 Oct 7, 2022
ToDo-Task-App - An Android App built to demonstrate the use of Jetpack Compose, Material You, Room Database, and MVVM

ToDo Task App ToDo Task App is a sample Android app built with Jetpack Compose.

null 0 Jan 17, 2022