Kotlin Multiplatform Development stable Help

What's new in Compose Multiplatform 1.7.0-beta01

Here are the highlights for this feature release:

See the full list of changes for this release on GitHub.

Dependencies

Breaking changes

Minimum AGP version raised to 8.1.0

Neither Jetpack Compose 1.7.0 nor Lifecycle 2.8.0, which are used by Compose Multiplatform 1.7.0, supports AGP 7. So when you update to Compose Multiplatform 1.7.0-beta01, you may have to upgrade your AGP dependency as well.

New default behavior for processing touch in iOS native elements

Before 1.7.0-beta01, Compose Multiplatform could not respond to touch events that landed in interop UI views. Therefore, interop views handled these touch sequences entirely.

In 1.7.0-beta01, Compose Multiplatform implements more sophisticated logic for handling interop touch sequences. By default, there is a delay after the initial touch that helps the parent composable understand whether the touch sequence was meant to interact with the native view and react accordingly.

See the more detailed explanation in the iOS section of this page or read the documentation for this feature.

Disabling minimum frame duration on iOS is mandatory

Developers often failed to notice the printed warning about the high refresh rate displays, and users were deprived of smooth animations on their 120-Hz-enabled devices. So we are enforcing this check to be strict: apps built with Compose Multiplatform will now crash if the CADisableMinimumFrameDurationOnPhone property in the Info.plist file is absent or set to false.

You can disable this behavior by setting the ComposeUIViewControllerConfiguration.enforceStrictPlistSanityCheck property to false.

Across platforms

Shared element transitions

Compose Multiplatform implements an API for seamless transitions between composables that share consistent elements. These transitions are often useful in navigation, helping users follow their trajectory in the UI.

For a deep dive into the API, see the Jetpack Compose documentation.

Type-safe Navigation

The type-safe Jetpack Compose approach to passing objects along a navigation route is implemented in Compose Multiplatform as well. New APIs implemented in Navigation 2.8.0 allow Compose to provide compile-time safety for your navigation graph. These APIs achieve the same result as the Safe Args plugin for XML-based navigation.

For details, see the Google’s Navigation docs about type safety.

Multiplatform resources

Resources packed into Android assets

All multiplatform resources are now packed into Android assets. This enables Android Studio to generate previews for Compose Multiplatform composables in Android source sets.

This also allows direct access to multiplatform resources from WebViews and media player components on Android, since resources can be reached by a simple path, for example Res.getUri(“files/index.html”)

An example of an Android composable displaying a resource HTML page with a link to a resource image:

// androidMain/kotlin/com/example/webview/App.kt @OptIn(ExperimentalResourceApi::class) @Composable @Preview fun App() { MaterialTheme { val uri = Res.getUri("files/webview/index.html") // Adding a WebView inside AndroidView with layout as full screen. AndroidView(factory = { WebView(it).apply { layoutParams = ViewGroup.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT ) } }, update = { it.loadUrl(uri) }) } }

The example works with this simple HTML file:

<html> <header> <title> Cat Resource </title> </header> <body> <img src="cat.jpg"> </body> </html>

Both resource files in this example are located in the commonMain source set:

File structure of the composeResources directory

Custom resource directories

With the new customDirectory setting in the configuration DSL you can associate a custom directory with a specific source set. This allows, for example, using downloaded files as resources.

Multiplatform font cache

Compose Multiplatform brings the Android font cache functionality to other platforms, too, to avoid excessive byte-reading of Font resources.

Support for test multiplatform resources

Now you can:

  • Add resources to test source sets.

  • Use generated accessors that are available only in the corresponding source sets.

  • Pack test resources into the app only for test runs.

Resources mapped to string IDs for easy access

Resources of each type are mapped with their filenames. For example, you can use the Res.allDrawableResources property to get the map of all drawable resources and access the necessary resource by passing the string ID:

Image(painterResource(Res.allDrawableResources["compose_multiplatform"]!!), null)

Functions for converting byte arrays into ImageBitmap or ImageVector

There are new functions for converting a ByteArray into an image resource:

  • decodeToImageBitmap() for turning a JPEG, PNG, BMP, or WEBP file into an ImageBitmap object.

  • decodeToImageVector() for turning an XML vector file into an ImageVector object.

  • decodeToSvgPainter() for turning an SVG file into a Painter object. This function is not available on Android.

See the documentation for details.

New common modules

material3.adaptive:adaptive*

Material3 adaptive modules are available in common code with Compose Multiplatform. You need to explicitly add the corresponding dependencies to use them:

commonMain.dependencies { implementation("org.jetbrains.compose.material3.adaptive:adaptive:1.0.0-rc01") implementation("org.jetbrains.compose.material3.adaptive:adaptive-layout:1.0.0-rc01") implementation("org.jetbrains.compose.material3.adaptive:adaptive-navigation:1.0.0-rc01") }

material3:material3-window-size-class

The material3-window-size-class dependency should be explicitly added to the list of common dependencies:

commonMain.dependencies { implementation("org.jetbrains.compose.material3:material3-window-size-class:1.7.0-beta01") }

The calculateWindowSizeClass() function is not available in common code yet. However, you can import and call it in platform-specific code, for example:

// desktopMain/kotlin/main.kt import androidx.compose.material3.windowsizeclass.calculateWindowSizeClass // ... val size = calculateWindowSizeClass()

material-navigation

The material-navigation library is available in common code alongside Compose Multiplatform navigation. To use it, add these explicit dependencies to your common source set:

commonMain.dependencies { implementation("org.jetbrains.androidx.navigation:navigation-compose:2.8.0-alpha09") implementation("org.jetbrains.compose.material:material-navigation:1.7.0-beta01") }

Skia updated to Milestone 126

The version of Skia, used by Compose Multiplatform via Skiko, has been updated to Milestone 126.

The previous version of Skia used was Milestone 116. You can see the changes made between these versions in the release notes.

GraphicsLayer: new drawing API

The new drawing layer added in Jetpack Compose 1.7.0 is now available in Compose Multiplatform.

Unlike Modifier.graphicsLayer, the new GraphicsLayer class allows for the rendering of Composable content anywhere and is useful in animated use cases where content is expected to be rendered in different scenes.

See the reference documentation for a more detailed description and example usage.

LocalLifecycleOwner moved out of Compose UI

The LocalLifecycleOwner class has been moved from the Compose UI package to the Lifecycle package.

This change allows you to access the class and call its Compose-based helper APIs independently of a Compose UI. However, keep in mind that without the Compose UI bindings, a LocalLifecycleOwner instance will have no platform integration and thus no platform-specific events to listen to.

iOS

Touch interop between Compose Multiplatform and native iOS is improved

In this release, the touch handling on iOS interop views becomes more sophisticated: Compose Multiplatform now tries to detect whether a touch is meant for an interop view or should be processed by Compose. This gives you a chance to process a touch event that happens in a UIKit or a SwiftUI area inside your Compose Multiplatform app.

By default, Compose Multiplatform will delay transmitting touch events to interop views by 150 ms:

  • If within this time frame there is movement over a minor distance threshold, the parent composable will intercept the touch sequence and not forward it to the interop view.

  • If there is no noticeable movement, Compose will resign from processing the rest of the touch sequence. The rest of the sequence will be processed solely by the interop view.

This behavior aligns with how native UIScrollView works. It helps to avoid situations where a touch sequence that starts in the interop view is intercepted without a chance for Compose Multiplatform to process it. This can lead to frustrating user experience. For example, imagine a large interop video player used in a scrollable context such as lazy list: it is tricky to scroll the list when most of the screen is taken by the video that intercepts all touches without Compose Multiplatform being aware of them.

Desktop

Drag and drop implemented

The drag and drop mechanism, which enables users to drag content into or out of your Compose application, has been implemented in Compose Multiplatform for desktop. To specify potential sources and destinations for dragging and dropping, use the dragAndDropSource and dragAndDropTarget modifiers.

For common use cases, see the Drag and drop article in the Jetpack Compose documentation.

BasicTextField, renamed from BasicTextField2, is adopted on desktop

Jetpack Compose stabilized and renamed the BasicTextField2 component to BasicTextField. In this release, Compose Multiplatform has adopted the change for desktop targets, planning to cover iOS as well in the stable 1.7.0 version.

The new BasicTextField:

  • Allows managing state more reliably.

  • Offers the new TextFieldBuffer API for programmatic changes to the text field content.

  • Includes several new APIs for visual transformations and styling.

  • Provides access to UndoState with the ability to return to previous states of the field.

Render settings for ComposePanel

By specifying the new RenderSettings.isVsyncEnabled parameter in the ComposePanel constructor, you can hint to the backend rendering implementation to disable vertical synchronization. This can reduce visual latency between input and changes in the UI but can also lead to screen tearing.

The default behavior stays the same: attempt to synchronize drawable presentations with VSync.

Last modified: 05 September 2024