compose-multiplatform

Maven CentralAndroid Min SDK

This is a dependency for Jetpack Compose's multi-platform features.

Currently supported platforms: Android, iOS, Desktop (JVM).

Notice

This module is still under development and testing, and the API may change before the 1.0.0 version is officially released.

We are welcome you to make suggestions to us at GitHub Issuesopen in new window.

Configure Dependency

You can add this module to your project using the following method.

This is a Kotlin Multiplatform dependency, you need the org.jetbrains.kotlin.multiplatform plugin to apply the relevant dependencies.

Add dependencies to your project SweetDependency configuration file.

libraries:
  com.highcapable.betterandroid:
    # commonMain
    compose-multiplatform:
      version: +
    # androidMain
    compose-multiplatform-android:
      version-ref: <this>::compose-multiplatform
    # iosArm64Main
    compose-multiplatform-iosarm64:
      version-ref: <this>::compose-multiplatform
    # iosX64Main
    compose-multiplatform-iosx64:
      version-ref: <this>::compose-multiplatform
    # iosSimulatorArm64Main
    compose-multiplatform-iossimulatorarm64:
      version-ref: <this>::compose-multiplatform
    # desktopMain
    compose-multiplatform-desktop:
      version-ref: <this>::compose-multiplatform

Configure dependencies in your project build.gradle.kts.

If you use multi-platform dependencies in a regular project, you only need to deploy the corresponding platform suffix dependencies as needed.

implementation(com.highcapable.betterandroid.compose.multiplatform.android)
implementation(com.highcapable.betterandroid.compose.multiplatform.iosarm64)
implementation(com.highcapable.betterandroid.compose.multiplatform.iosx64)
implementation(com.highcapable.betterandroid.compose.multiplatform.iossimulatorarm64)
implementation(com.highcapable.betterandroid.compose.multiplatform.desktop)

If you use multi-platform dependencies in a multi-platform project, you need to add the compose-multiplatform dependency in commonMain.

kotlin {
    sourceSets {
        val commonMain by getting {
            dependencies {
                implementation(com.highcapable.betterandroid.compose.extension)
            }
        }
    }
}

Traditional Method

Configure dependencies in your project build.gradle.kts.

If you use multi-platform dependencies in a regular project, you only need to deploy the corresponding platform suffix dependencies as needed.

implementation("com.highcapable.betterandroid:compose-multiplatform-android:<version>")
implementation("com.highcapable.betterandroid:compose-multiplatform-iosarm64:<version>")
implementation("com.highcapable.betterandroid:compose-multiplatform-iosx64:<version>")
implementation("com.highcapable.betterandroid:compose-multiplatform-iossimulatorarm64:<version>")
implementation("com.highcapable.betterandroid:compose-multiplatform-desktop:<version>")

If you use multi-platform dependencies in a multi-platform project, you need to add the compose-multiplatform dependency in commonMain.

kotlin {
    sourceSets {
        val commonMain by getting {
            dependencies {
                implementation("com.highcapable.betterandroid:compose-multiplatform:<version>")
            }
        }
    }
}

Please change <version> to the version displayed at the top of this document.

Function Introduction

You can view the KDoc click hereopen in new window.

In order to allow developers who are adapted to native Android development to adapt to various platforms faster, BetterAndroid seamlessly provides multi-platform support with the help of the cross-platform features of Kotlin Multiplatform and Jetpack Compose.

The following are the functions currently being developed and completed.

We welcome more developers to participate in the development, if possible, you are welcome to submit a PR to contribute to this project or make suggestions to us through GitHub Issuesopen in new window.

Features marked with "✅" indicate available, "❎" indicates not supported by the platform, "🚧" indicates preparation or under development (WIP), and "🔨" indicates planned development.

Feature NameDescriptionAndroidiOSDesktop
BackHandlerSystem back pressed event for Android.
PlatformWindowInsetsWindow insets for mobile platforms.🚧🚧
PlatformNotificationManagerNotifications post & management to the system.🔨🔨🔨
PlatformSystemBarsControllerSystem bar-related controller for mobile platforms.
PlatformDisplayControllerScreen rotation & brightness controller for mobile platforms.🚧🚧
PlatformHwSensorControllerHardware sensors (such as vibration) for mobile platforms.🔨🔨

The features that have been developed will be described in detail below.

Initial Configuration

Contents of This Section

iosMain

AppComponentUIViewControlleropen in new window

Basic component UIViewController.

UIViewController → AppComponentUIViewControlleropen in new window

Extensions for UIViewController to creating a starting point for Compose.

Before starting, we recommend that you configure your project structure as follows.

Tips

We recommend and refer to Quick Start → Project Template to create a project without manual configuration.

You can also use the Kotlin Multiplatform Wizardopen in new window to automatically help you complete the Gradle script compilation configuration of the iOS project.

General Section

Please create an App.kt in commonMain which will serve as the starting point for Compose.

The following example

@Composable
fun App() {
    // Your composables content here.
}

Android Platform

First, please import the ui-component module in the corresponding Android project.

Then, please refer to ui-component → Activity to use AppComponentActivty as the starting point for Compose.

The following example

class MainActivity : AppComponentActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            App()
        }
    }
}

iOS Platform

Notice

You need to have a computer or virtual machine that can run macOS and have the Xcode environment configured correctly.

First, you need to manually create an iOS App Xcode project, select Swift as the language, and select Storyboard in the Interface column.

Then, create an AppComponentUIViewController in the MainViewController.kt file in iosMain using the following method.

The following example

fun createMainViewController() = AppComponentUIViewController {
    App()
}

Then, determine the shared module name you set in build.gradle.kts for your iOS project.

The following example

kotlin {
    listOf(
        iosX64(),
        iosArm64(),
        iosSimulatorArm64()
    ).forEach { iosTarget ->
        iosTarget.binaries.framework {
            // Set the shared module name.
            baseName = "ComposeApp"
            // It is recommended to set it as a static library.
            isStatic = true
        }
    }
}

Next, make the following configurations to the AppDelegate.swift file in your iOS project.

If your iOS project was created using Swift UI, please create this file manually and remove the SwiftApp.swift related files created using Swift UI.

The following example

import UIKit
import ComposeApp // Here is your shared module name.

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions:
        [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Create a new UIWindow.
        window = UIWindow(frame: UIScreen.main.bounds)
        // Set the controller of the root view.
        // MainViewControllerKt is the automatically generated Kotlin code in ComposeApp.h.
        window?.rootViewController = MainViewControllerKt.createMainViewController()
        // Make it visible.
        window?.makeKeyAndVisible()
        return true
    }
}

Notice

Do not use UIViewControllerRepresentable to create UIViewController for Swift UI, although this is currently the code that the Kotlin Multiplatform Wizard automatically generates for you.

But this will cause the related functions of System Bars (Status Bars, Navigation Bars, Home Indicator, etc) to fail, because Swift UI will take over the state of the entire view, at this time, you can only control system bars in Swift UI.

Desktop Platform

Please use the following method to create the starting point of Compose in the corresponding Java project Main.kt.

The following example

fun main() = application {
    Window(
        onCloseRequest = ::exitApplication,
        // Set window title.
        title = "My App",
        // Set window size.
        state = rememberWindowState(width = 300.dp, height = 500.dp)
    ) {
        App()
    }
}

System Event

Contents of This Section

commonMain

BackHandler → BackHandleropen in new window

Extensions for system back pressed event.

Although androidx.activity:activity-compose provides BackHandler, it can only be used in Android.

BetterAndroid provides multi-platform distribution support for BackHandler, you can use it directly in commonMain, but it will only take effect on the Android platform.

BackHandler is implemented in Android using BackPressedController in ui-component → System Event, you can refer to ui-component → Activity to use AppComponentActivty or manually implement the IBackPressedController interface for your Activity.

Below is a usage example that is identical to the BackHandler usage provided in androidx.activity:activity-compose.

The following example

// Create enabled state.
var enabled by remember { mutableStateOf(true) }
// Create BackHandler.
BackHandler(enabled) {
    // Handle back pressed event.
}

System Bars (Status Bars, Navigation Bars, Home Indicator, etc)

Contents of This Section

commonMain

PlatformSystemBarsControlleropen in new window

System bars controller for Android and iOS.

NativeSystemBarsControlleropen in new window

Native system bars controller corresponding to Android and iOS.

PlatformSystemBarStyleopen in new window

System bars style.

PlatformSystemBarsopen in new window

System bars type.

PlatformSystemBarBehavioropen in new window

System bars behavior.

SystemBars → rememberSystemBarsControlleropen in new window

SystemBars → nativeControlleropen in new window

Extensions for system bars.

iosMain

SystemBarsControlleropen in new window

System bars controller.

SystemBarStyleopen in new window

System bars style.

SystemBarsopen in new window

System bars type.

SystemBarBehavioropen in new window

System bars behavior.

In both Android and iOS, you need to control and adjust the status bars and navigation bars (home indicator) provided by the system to give users a better experience.

For this purpose, BetterAndroid provides you with PlatformSystemBarsController, which can easily control the system bars of each platform through a common API.

The working principle of PlatformSystemBarsController is to distribute it to the corresponding native controller according to different platforms through NativeSystemBarsController.

Before starting to use it, make sure you have read Initial Configuration and completed the relevant configuration for the current project.

PlatformSystemBarsController uses SystemBarsController in ui-component → System bars (Status bars, Navigation bars, etc) in Android accomplish, you can refer to ui-component → Activity to use AppComponentActivty or manually implement the ISystemBarsController interface for your Activity.

You can get the PlatformSystemBarsController object globally in Compose in the following way.

The following example

// Get PlatformSystemBarsController through state management.
val systemBars = rememberSystemBarsController()

Notice

When using rememberSystemBarsController, if the native SystemBarsController has not been initialized, it will automatically call init for initialization.

To avoid problems with interface performance, you should ensure that initialization operations are completed during the configuration phase of each platform, otherwise you should ensure that rememberSystemBarsController is called before all content starts to be drawn.

The following is a detailed usage introduction of PlatformSystemBarsController.

Most of the usage here will be consistent with ui-component → System Bars (Status Bars, Navigation Bars, etc).

Set the behavior of system bars.

This determines the system-controlled behavior when showing or hiding system bars.

The following example

systemBars.behavior = PlatformSystemBarBehavior.Immersive

The following are all behaviors provided in PlatformSystemBarBehavior, those marked with * are the default behaviors.

BehaviorPlatformDescription
DefaultAllDefault behavior controlled by the system.
*ImmersiveAndroidA system bar that can be popped up by gesture sliding in full screen and displayed as a translucent system bar, and continues to hide after a period of time.
iOSThe system bars can be revealed temporarily with system gestures when the status bars hide, but disappears after a period of time.

Show, hide system bars.

The following example

// Enter immersive mode (full screen mode).
// Hide status bars and navigation bars, home indicator at the same time.
systemBars.hide(PlatformSystemBars.All)
// Separately control the status bars and navigation bars, home indicator.
systemBars.hide(PlatformSystemBars.StatusBars)
systemBars.hide(PlatformSystemBars.NavigationBars)
// Exit immersive mode (full screen mode).
// Show status bars and navigation bars, home indicator at the same time.
systemBars.show(PlatformSystemBars.ALL)
// Separately control the status bars and navigation bars, home indicator.
systemBars.show(PlatformSystemBars.StatusBars)
systemBars.show(PlatformSystemBars.NavigationBars)

Set the style of the system bars.

You can customize the appearance of the status bars and navigation bars, home indicator.

Notice

In systems below Android 6.0, the content of the status bars does not support inversion, if you set a bright color, it will be automatically processed as a semi-transparent mask.

However, for MIUI and Flyme systems that have added the inverse color function themselves, they will use their own private solutions to achieve the inverse color effect.

In systems below Android 8, the content of the navigation bars does not support inversion, and the processing method is the same as above.

In iOS, home indicator does not support setting darkContent, its color is controlled by the system, but you can set the background color for it.

The following example

// Set the style of the status bars.
systemBars.statusBarStyle = PlatformSystemBarStyle(
    // Set background color.
    color = Color.White,
    // Set content color.
    darkContent = true
)
// Set the style of the navigation bars, home indicator.
systemBars.navigationBarStyle = PlatformSystemBarStyle(
    // Set background color.
    color = Color.White,
    // Set content color.
    darkContent = true
)
// You can set the style of the status bars and navigation bars, home indicator at once.
systemBars.setStyle(
    statusBar = PlatformSystemBarStyle(
        color = Color.White,
        darkContent = true
    ),
    navigationBar = PlatformSystemBarStyle(
        color = Color.White,
        darkContent = true
    )
)
// You can also set the style of the status bars and navigation bars,
// home indicator at the same time.
systemBars.setStyle(
    style = PlatformSystemBarStyle(
        color = Color.White,
        darkContent = true
    )
)

The following are the preset styles provided in PlatformSystemBarStyle, the ones marked with * are the default styles.

StyleDescription
AutoThe system dark mode is a pure black background + light content color, and the light mode is a pure white background + dark content color.
*AutoTransparentThe light content color is used in the system dark mode, and the dark content color is used in the light mode, with a transparent background.
LightPure white background + dark content color.
LightScrimTranslucent pure white background + dark content color.
LightTransparentTransparent background + dark content color.
DarkPure black background + light content color.
DarkScrimTranslucent solid black background + light content color.
DarkTransparentTransparent background + light content color.

Get the native controller.

You can obtain the native controller in the corresponding platform through the following methods, using commonMain or in unsupported platforms will always return null.

The following example

// Get the native controller.
val nativeController = systemBars.nativeController

Tips

BetterAndroid also provides a native SystemBarsController for iOS, its usage is basically the same as ui-component → System Bars (Status Bars, Navigation Bars, etc) except for the initialization function, normally you should not need to use it directly, and it will not be introduced in detail here.