Compose Multiplatform 1.6.0 – Resources, UI Testing, iOS Accessibility, and Preview Annotation

Compose Multiplatform is a declarative UI framework built by JetBrains that allows developers to share UI implementations across different platforms. The 1.6.0 release brings several powerful features, as well as compatibility with the latest Kotlin version and changes from Google’s latest Jetpack Compose update.

Get Started with Compose Multiplatform

This release of Compose Multiplatform:

  • Revamps the resource management library.
  • Introduces a UI testing API.
  • Adds iOS accessibility support.
  • Brings a host of other features and improvements.

For a description of all notable changes, see our What’s new in Compose Multiplatform 1.6.0 page or check the release notes on GitHub.

Common resources API

The biggest and most anticipated change in Compose Multiplatform 1.6.0 is the improvement of the API for sharing and accessing resources in common Kotlin code. This API now allows you to include and access more types of resources in your Compose Multiplatform applications.

The resources are organized in a number of directories as part of the commonMain source set:

  • composeResources/drawable contains images
  • composeResources/font contains fonts
  • composeResources/values contains strings (in the format of strings.xml)
  • composeResources/files contains any other files.

Compose Multiplatform generates type-safe accessors for all of these resource types (excluding the files directory). For example, after placing a vector image compose-multiplatform.xml in the composeResources/drawable directory, you can access it in your Compose Multiplatform code using the generated Res object:

import androidx.compose.foundation.Image
import androidx.compose.runtime.Composable
import kotlinproject.composeapp.generated.resources.*
import org.jetbrains.compose.resources.ExperimentalResourceApi
import org.jetbrains.compose.resources.painterResource

@OptIn(ExperimentalResourceApi::class)
@Composable
fun Logo() {
    Image(
        painterResource(Res.drawable.compose_multiplatform),
        contentDescription = "CMP Logo"
    )
}

The new resources API also allows you to provide variations of the same resource for different use cases, including locale, screen density, or theme. Whether you’re localizing text, changing the colors of your icons in dark mode, or providing alternative images based on screen resolution, you can express these constraints by adding qualifiers to the directory names.

For a closer look at qualifiers for resources, as well as an in-depth overview of the new resources API in Compose Multiplatform 1.6.0, take a look at the official documentation!

Common API for UI testing

UI testing helps you make sure that your application behaves the way it is supposed to. With Compose Multiplatform 1.6.0, we’re introducing an experimental API that allows you to write common UI tests for Compose Multiplatform that validate the behavior of your application’s user interface across the different platforms supported by the framework.

For example, you may want to ensure that a custom component correctly shows an informative string with the proper prefix:

@Composable
fun MyInfoComposable(info: String, modifier: Modifier) {
    Text(modifier = modifier, text = "[IFNO] $info")
}

In the latest version of Compose Multiplatform, you can now use UI tests to validate that the component does indeed correctly prefix the text when rendered. To do so, you can use the same finders, assertions, actions, and matchers as you would with Jetpack Compose on Android. After following the setup instructions from the documentation you can write a test that ensures the prefix is added properly:

import androidx.compose.ui.test.ExperimentalTestApi
import androidx.compose.ui.test.runComposeUiTest
...

class InformationTest {
    @OptIn(ExperimentalTestApi::class)
    @Test
    fun shouldPrefixWithInfoTag() = runComposeUiTest {
        setContent {
            MyInfoComposable("Important things!", modifier = Modifier.testTag("info"))
        }
        onNodeWithTag("info").assertTextContains("[INFO]", substring = true)
    }
}

Running this test on any of your target platforms will show you the test results (and in this case, help you spot and correct a typo!):

iOS accessibility support

Compose Multiplatform for iOS now allows people with disabilities to interact with the Compose UI with the same level of comfort as with the native UI:

  • Screen readers and VoiceOver can access the content of the Compose Multiplatform UI.
  • Compose Multiplatform UI supports the same gestures as the native UIs for navigation and interaction.

This is possible because the Compose Multiplatform semantic data is automatically mapped into an accessibility tree. You can also make this data available to Accessibility Services and use it for testing with the XCTest framework.

For details on the implementation and limitations of the current accessibility support, see the documentation page.

@Preview annotation for Fleet

With 1.6.0, Compose Multiplatform introduces the common @Preview annotation (previously available only for Android and Desktop). This annotation is supported by JetBrains Fleet (starting with Fleet 1.31). Add @Preview to your @Composable function, and you’ll be able to open the preview via the gutter icon:

Try it out with a project generated by the Kotlin Multiplatform wizard!

Fleet currently supports the @Preview annotation for @Composable functions without parameters. To use this common annotation, add the experimental compose.components.uiToolingPreview library to your dependencies (as opposed to compose.uiTooling, used for desktop and Android).

Separate platform views for popups, dialogs, and dropdown menus

When mixing Compose Multiplatform with SwiftUI, you may only want to have some widgets of a given screen rendered using Compose. Starting with version 1.6, when you create Dialog, Popup, or Dropdown composables in these scenarios, they can expand beyond the bounds of the individual widget and even expand across the entire screen!

This is also possible for desktop targets, although as an experimental feature for now.

Dialog, Popup, or Dropdown in Compose Multiplatform

Other notable changes

To learn about the rest of the changes included in this release:

What else to read and watch

Continue ReadingCompose Multiplatform 1.6.0 – Resources, UI Testing, iOS Accessibility, and Preview Annotation

Kotlin Multiplatform Development Roadmap for 2024

With the recently achieved stability of Kotlin Multiplatform, development teams worldwide can now seamlessly and confidently adopt it in production. However, this is just the beginning for KMP and its ecosystem. To equip you with the best cross-platform development experience, JetBrains aims to deliver a host of further improvements to the core Kotlin Multiplatform technology, Compose Multiplatform, KMP tooling, and KMP libraries in 2024. Read on to learn what we’re planning and our priorities in these areas.

Compose Multiplatform

We’re dedicated to making Compose Multiplatform a framework that allows creating beautiful and performant applications that look the same way on all supported platforms. Right now, our main focus is to get Compose for iOS to Beta, but we’re also working on other things. Here’s what we plan to do:

  • Make all Jetpack Compose core APIs and components multiplatform.
  • Improve rendering performance on iOS.
  • Make scrolling and text editing in Compose for iOS apps behave the same as in iOS native apps.
  • Implement a common API for sharing all types of resources.
  • Integrate with iOS and Desktop accessibility APIs.
  • Provide a solution for multiplatform navigation.

Many of the aforementioned improvements benefit Compose for Desktop, as well. In addition, we’re working on improving its stability and evolving it according to the feedback from those who use it in production.

We’ll also continue to explore what’s possible with Compose for Web, specifically with Wasm. Our nearest goal is to promote it to Alpha, which includes:

  • Allowing you to port your existing apps and reuse all of your common code.
  • Supporting different screen sizes, orientations, and densities.
  • Supporting input from a mouse, touchscreen, physical keyboard, or onscreen keyboard.
  • Improving performance and binary size.

Tooling

We’re committed to providing a great IDE experience for Kotlin Multiplatform. That means not only investing in the core platform and, for example, migrating Kotlin IDE plugin to K2 compiler frontend, but also providing a single tool (Fleet) for all Kotlin Multiplatform targets and codebases where you integrate it, eliminating the need to constantly switch between different IDEs.

We plan to quickly iterate over your feedback about using Fleet for Kotlin Multiplatform development  to make sure that we have everything you need for your development experience to be great. Among other things, we’re going to deliver in the following areas:

  • Enhanced support for Compose Multiplatform, including live preview for common code and visual debugging tools.
  • The IDE helping you with project configuration.
  • Unified and enhanced debugging experience for all parts of your Multiplatform project.

Multiplatform core

One of the popular Kotlin Multiplatform scenarios is sharing code with the iOS target. We want to focus on the development experience of iOS developers who work with Kotlin Multiplatform frameworks in their codebases.

The main initiative in this area is a direct Kotlin-to-Swift export. It will eliminate the Objective-C bottleneck, allowing for broader Swift language support and more natural exporting of APIs. Additionally, we are creating tools specifically for Kotlin library authors. These tools are designed to improve the compatibility and user-friendliness of Kotlin APIs when exported to Swift. We’re also paying close attention to tooling. The IDE and build systems are essential parts of the developer experience, and our goal is to ensure that the Swift Export integrates smoothly.

Our other initiatives include speeding up Kotlin/Native compilation, enhancing CocoaPods integration, and introducing support for exporting your framework with SwiftPM.

We also plan to continue exploring ways to improve the build setup of Kotlin Multiplatform applications. With Kotlin 1.9.20, we released huge improvements in the Gradle Multiplatform DSL, making it easier to read and write. We will continue to gradually improve it. In addition, we’re experimenting with Amper, a new project configuration tool focused on usability, onboarding, and IDE support.

Library ecosystem

As the Kotlin Multiplatform ecosystem is growing fast, the backward compatibility of the libraries becomes crucial. To ensure it, the JetBrains team and library creators must work together. Here’s our plan:

  • Improve the klib format so library creators can leverage their knowledge of building JVM libraries.
  • Implement the same code-inlining behavior in Kotlin Multiplatform libraries as for the JVM.
  • Provide a tool that ensures that your multiplatform library public API hasn’t changed in an incompatible way.

We’re also going to improve the publishing process for KMP libraries. Specifically, we plan to:

  • Make it possible to build and publish a KMP library without having a Mac machine.
  • Provide templates and extensive guidelines for creating and publishing a KMP library.

Even though Kotlin Multiplatform is now stable, we’re planning significant updates. But don’t worry: Libraries built with the current format will still work with newer Kotlin versions.

Read more

Continue ReadingKotlin Multiplatform Development Roadmap for 2024

Welcome Fleet with Kotlin Multiplatform Tooling

Kotlin Multiplatform (KMP) is an open-source technology built by JetBrains that allows you to share code across multiple platforms while retaining the benefits of native programming. Supported platforms include iOS, Android, desktop, web, and others.

Today, we’re launching a preview for Kotlin Multiplatform support in Fleet, which simplifies the development of multiplatform applications, adding to the already extensive Kotlin support in Fleet. Please note that if you’re targeting iOS and macOS, you will need Xcode.

Get Started

Let’s take a look at some of the features.

Simplicity

When you open a multiplatform project, Fleet will automatically create Run Configurations for the Android and/or iOS platforms, as declared in the project build file. You can use these to execute your application on an Android Virtual Device or the iOS Simulator.

Kotlin Multiplatform Tooling in Fleet: Auto-generated Run Configurations for Android and/or iOS

Polyglot Programming

Because Fleet is a polyglot IDE, you don’t have to switch to a different editor or compromise usability when working with the native code in your multiplatform project. When editing Swift code, you have the same rich functionality you would expect in Kotlin and Java, as well as full support for Xcode projects.

Kotlin Multiplatform Tooling in Fleet: Polyglot programming

Code navigation

Fleet supports cross-language navigation between Swift and Kotlin. For example, when you use the Show Usages action on a Kotlin function, any invocations from Swift code will feature in the results. If there is a single match, then the associated file is displayed.

Swift-Kotlin cross-language navigation

Refactoring

Refactoring in Fleet is also cross-language. In the example below, if we use Rename Refactoring on the MainViewController type, then the refactoring will apply across both Kotlin and Swift modules.

Swift-Kotlin cross-language refactoring

Debugging

Debugging in Fleet is also cross-language. You can set a breakpoint in Swift code, view values and the call stack in that environment, step into a Kotlin call, and then continue as required.

Swift-Kotlin cross-language refactoring

A single IDE

As you may be aware or have experienced, creating Kotlin Multiplatform applications has oftentimes involved needing to use multiple IDEs in combination. This is still the case when targeting mobile, as Android Studio and Xcode are required. However, our goal with Fleet is to provide a single IDE where you can develop applications without needing to switch tools (Xcode will still be required to be installed when targeting Apple devices, but will not be necessary for daily work).

Pricing model

During the Preview period, Fleet, including the Kotlin Multiplatform Tooling, will remain free. Once we release the tooling, we anticipate the pricing model will be in line with that of Fleet itself. We’ll provide more information closer to the release date.

Our commitment to IntelliJ IDEA and the IntelliJ Platform

Fleet uses the IntelliJ code-processing engine for Swift and all of our Kotlin support, and consequently, we will continue to provide support for Kotlin in IntelliJ IDEA and on the IntelliJ Platform (thus also Android Studio). In addition, we have an ever-increasing base of developers using Kotlin in IntelliJ IDEA, and we want to assure you that innovation and support will continue on this platform.

Having said that, the target audience for IntelliJ IDEA will primarily remain that of server-side developers targeting the JVM. While it will be possible to open, navigate, and build Kotlin Multiplatform projects in IntelliJ IDEA and Android Studio, other features such as platform-specific run configurations, Compose Multiplatform features, and many other things that facilitate multiplatform development will be supported in Fleet only.

How to get started

To get started with Kotlin Multiplatform development and try out all of the cool features we have been working on, you can install the latest version of Fleet via the JetBrains Toolbox App. We also have a brand new online Web Wizard for creating Kotlin Multiplatform projects.

Make sure you check out the Fleet for Kotlin Multiplatform Development tutorial for a step-by-step guide on creating your first application. You can also take a look at some of the KMP sample applications  we’ve prepared.

Get Started

We need your feedback

It’s still very early days for Kotlin Multiplatform Tooling in Fleet, and we would love to hear your feedback. Let us know what works, what doesn’t, what is missing, and what you just can’t do without. Leave us a comment on this blog post or use our issue tracker. You can also share any feedback you have on Kotlin Multiplatform, including the tooling, on the #fleet channel on the Kotlin Slack.

Thank you!

Continue ReadingWelcome Fleet with Kotlin Multiplatform Tooling

Compose Multiplatform 1.5.10 – The Perfect Time To Get Started

Compose Multiplatform is a declarative UI framework built by JetBrains that allows developers to share their applications’ UIs across different platforms. It enables you to reuse up to 100% of your codebase across Android, iOS, desktop, and web. The framework leverages the code-sharing capabilities of the core Kotlin Multiplatform technology, which just became Stable in Kotlin 1.9.20.

Get Started with Compose Multiplatform

This 1.5.10 release of Compose Multiplatform provides support for Kotlin 1.9.20, offers simplified onboarding, introduces a new portal for documentation, and provides the features listed below:

With these across-the-board improvements, it has never been easier to adopt Compose Multiplatform. Now is a great time for you to start using Compose Multiplatform for cross-platform development, and if you are an existing user, these improvements will make your work more effective than ever.

Easier to get started

If you want to dive into Compose Multiplatform and Kotlin Multiplatform, then we have some great news for you:

  • The Kotlin Multiplatform Web Wizard lets you easily create new projects in a few clicks. The project contains both shared logic and a Compose Multiplatform UI for multiple platforms.
  • New onboarding tutorials are available for Android, iOS, and desktop. These will bring you up to speed on the core concepts of Kotlin Multiplatform and Compose Multiplatform.
  • The Compose Multiplatform documentation has been integrated into the Kotlin Multiplatform Development portal, making it easier and simpler for you to find the information you need.

You can also register for our webinar about getting started with Compose Multiplatform, scheduled for November 28.

New Material 3 components in common code

All Compose Material 3 components are now available in common code. The ModalBottomSheet, ExposedDropdownMenuBox, SearchBar, and DockedSearchBar components were added in this release, which completes the set of components defined in the 1.1.2 version of Compose Material 3.

This is how it will appear on desktop:

New Components on Desktop

And this is how it will look on iOS and Android:

New Components on iOS
                            
New Components on Android

Enhanced TextFields on iOS

This release features multiple enhancements to TextFields on iOS. A new Fast Delete mode is available, handling of double and triple taps has been improved, scroll physics includes the ‘rubber band effect’, and a crossfade animation improves interoperability.

  • Starting with this release, when you hold down Backspace, a new Fast Delete mode activates after the first 21 characters. In this mode each deletion removes two words. This aligns with the default iOS behavior and is what users expect.

Fast Delete mode on iOS

  • Starting with this release, double and triple taps in a TextField are always handled consistently. Double-tapping will always select the current word, while triple-tapping always selects the entire text.

Double and Triple Taps on iOS

  • Compose Multiplatform 1.5.0 introduced support for native scroll physics. This release adds support for overscroll (the “rubber band effect”) within large text fields. Your Compose Multiplatform UI will now provide the bounciness that iOS users expect.

Rubber Band Effect on iOS

Crossfade animation for UIKit interoperability

When you target iOS, Compose Multiplatform allows you to embed composables within a UIKit component hierarchy. This enables you to combine your Kotlin UI components with existing Swift or Objective-C widgets.

Starting with this release, when embedding composables within a UIKit hierarchy, a crossfade animation is applied to the screen as the orientation transitions. This prevents components from temporarily appearing stretched.

Increased compilation speed

In Kotlin 1.9.20, compiler caching and Compose Multiplatform are compatible. So, starting from this release, compiler caching is automatically enabled for Compose Multiplatform applications that use the Kotlin 1.9.20 compiler. Compilation is much faster for all compilations after the initial one.

Caching remains disabled when you use Compose Multiplatform with an earlier version of the Kotlin compiler. Manually setting  kotlin.native.cacheKind to none causes the Gradle compiler plugin to produce an error, so please remove this if present.

Basic support for the K2 compiler

In this release, we introduce partial support for the K2 compiler in Compose Multiplatform. You can use the Compose Compiler and K2 in combination to build basic applications. Full support for K2 is scheduled for the next CMP release, so stay tuned.

Enhanced rendering performance on iOS

In this release, we’ve improved performance on iOS by eliminating any instances of redundant or overly eager processing. In addition, the commands to be run on the GPU for rendering are prepared in a separate thread.

These changes mean that Compose Multiplatform apps running on iOS will have fewer missed frames. Any stutters or lags caused by missed frames will be reduced or removed.

New documentation portal

The new Kotlin Multiplatform Development Portal features tutorials, a FAQ, brand new samples, and other helpful documentation. This means getting started with Compose Multiplatform is easier than ever!

Topics covered include:

Grouping Compose Multiplatform materials with other multiplatform documentation, on a dedicated portal, makes them easier to find and consume. While some documentation remains on the Compose Multiplatform GitHub, our aim is to transfer it to the new portal soon.

Get Started with Compose Multiplatform

Wrapping up

There has never been a better time to get started with Compose Multiplatform! You can use the Compose Material 3 widgets to build beautiful user interfaces that behave consistently on Android, iOS, desktop, and web. Using the Kotlin Multiplatform Web Wizard you can be up and running in minutes, with the new onboarding tutorials to guide you as you build your first Compose Multiplatform applications.

We hope you’ll find building applications with Compose Multiplatform a fun and rewarding experience. Please provide feedback on how you get on. We invite you to join the discussion on the Kotlin Slack in the #compose channel, where you can discuss general topics related to Compose Multiplatform and Jetpack Compose.

What else to read and watch

Continue ReadingCompose Multiplatform 1.5.10 – The Perfect Time To Get Started

Kotlin Multiplatform Is Stable and Production-Ready

In a highly anticipated move, Kotlin Multiplatform, an open-source technology built by JetBrains that allows developers to share code across platforms while retaining the benefits of native programming, has become Stable and is now 100% ready for use in production.

Read on to learn about the evolution of Kotlin Multiplatform (KMP), how it can streamline your development process, and what educational resources are available for you to get the most out of the technology.

Get Started

Share code on your terms, with confidence

Designed with a core focus on flexibility and adaptability, Kotlin Multiplatform (KMP) blurs the boundaries between cross-platform and native development. It allows developers to reuse as much code as they want, write native code if and as needed, and seamlessly integrate shared Kotlin code into any project.

Since the first release of KMP, its flexibility has attracted many prominent companies, such as Netflix, Philips, McDonald’s, 9GAG, and Baidu. Many teams have already been capitalizing on KMP’s ability to be gradually integrated, as well as its low adoption risk. Some of them share isolated critical parts of their existing Kotlin code to improve the stability of their apps. Others, aiming to reuse as much code as possible without compromising app quality, share all application logic across mobile, desktop, web, and TV while maintaining native UIs.

With KMP being widely used in production since its Alpha release, JetBrains has been able to gather extensive feedback and refine the technology to provide a better multiplatform development experience in the Stable version, including the following.

Strict compatibility guarantees

The core of the Kotlin Multiplatform technology consists of many parts, such as compiler support, language features, the libraries API, IDEs, build tooling, and more. All of these cover the most popular code-sharing use-cases and are stable in Kotlin 1.9.20. “Stable” means that we will evolve those parts following strict compatibility rules, so you can confidently use them in your code.

Going beyond the core, KMP also has some more advanced parts that we’re still continuing to work on. Expect/actual classes are an example of such functionality (not to be confused with expect/actual functions, which are fully stable in Kotlin 1.9.20). Such features are explicitly marked as non-stable, and Kotlin will inform you when you’re using them. Please pay attention to the experimentality warnings and the corresponding documentation to make an informed decision about using or not using such features in your projects.

Better build setup user experience

To simplify project setup and maintenance, we’ve introduced the default hierarchy template. This new feature of the Kotlin Gradle plugin automatically configures Kotlin Source Sets for popular scenarios and reduces the amount of boilerplate in typical build scripts.

To help you diagnose build misconfigurations and errors, KMP delivers a couple of improvements in Stable:

  • Approximately 50 diagnostics were added to the Kotlin Gradle plugin, helping to detect common build issues and providing quick tips on how to fix them.
  • Improved output for Gradle errors in Xcode makes build issues in native parts of your project more discoverable.

Build and runtime performance improvements

In addition to other stability and robustness improvements, we’re continuing to improve the performance of KMP:

Thanks to all of these advancements, Kotlin Multiplatform can be used without hesitation for sharing code in production across Android, iOS, desktop (JVM), server-Side (JVM), and web, even in the most conservative usage scenarios.

Get Started

Use the power of the growing Kotlin Multiplatform ecosystem

The evolution of Kotlin Multiplatform isn’t limited to the technology itself, but extends to its thriving ecosystem cultivated by thousands of Kotlin developers worldwide. Since Beta, the number of KMP libraries has multiplied, offering diverse tools for networking, data storage, arithmetics, analytics, and more, enabling swift and confident app development.

The Android team at Google is continuing to support KMP users by providing the experimental multiplatform versions of Jetpack libraries, and they’ve already made the Collections, DataStore, Annotations, and Paging libraries compatible with Kotlin Multiplatform.

The KMP ecosystem also offers a range of tools for the iOS developer experience, with SKIE by Touchlab standing out. It generates Swift code that provides a Swift-friendly API layer, which bridges important Kotlin types, and implements seamless Coroutines interoperability.

Get even more code-sharing freedom with Compose Multiplatform

Compose Multiplatform, a modern declarative cross-platform UI framework by JetBrains, is a significant part of the ever-expanding KMP ecosystem. With Compose Multiplatform, you now have full code-sharing flexibility. Share just one piece of logic, all application logic, or both the logic and the UI, depending on your project’s and team’s requirements:

Compose Multiplatform for Android and desktop (JVM) is already Stable, while support for iOS is currently in Alpha and support for web (Wasm) is Experimental.

Explore the future of Kotlin Multiplatform

JetBrains continues to enhance multiplatform development with Kotlin, aiming to make it the ultimate choice for sharing code across platforms:

  • Future updates for the core Kotlin Multiplatform technology will improve the iOS developer experience, including direct Kotlin-to-Swift interoperability and SwiftPM support.
  • The next milestone for Compose Multiplatform for iOS is Beta support in 2024.
  • JetBrains is actively developing Kotlin/Wasm to facilitate modern web development with KMP, aiming to deliver the Alpha version of Compose Multiplatform for Web (Wasm) next year.

And that’s not all. In the upcoming weeks, get ready for some thrilling announcements regarding the evolution of Kotlin Multiplatform tooling!

Get started with Kotlin Multiplatform

Begin your journey with our extensive, user-friendly educational resources.

Participate in our Kotlin Multiplatform Webinar November Series to get insights directly from JetBrains experts! Explore Kotlin Multiplatform features, build KMP apps with both native and shared UIs, and uncover iOS development tips and tricks:

Register

The new Kotlin Multiplatform Development Portal offers detailed documentation, getting-started guides, and step-by-step tutorials covering all aspects of building apps with Kotlin Multiplatform and Compose Multiplatform:

Get Started

Continue ReadingKotlin Multiplatform Is Stable and Production-Ready

Shining a Spotlight on Kotlin Multiplatform Content Creators

As the Kotlin Multiplatform stable release emerges on the horizon, its ecosystem continues to evolve and flourish, thanks in no small part to the enthusiastic Kotlin community. What’s more, the Compose Multiplatform 1.5.10 release is around the corner, which has only added to the excitement surrounding this technology’s capabilities. With that said, we want to announce the new round of the Kotlin Multiplatform Content Creators Recognition Campaign, highlighting the contributions of those passionate individuals who have been instrumental in keeping the community informed, engaged, and inspired.

Kotlin Multiplatform has captured the imagination of developers worldwide and has motivated content creators to share their how-tos, various articles packed with actionable tips, video tutorials, and sample projects. We want to shine a spotlight on this content that provides valuable insights, guidance, and inspiration to learners, enthusiasts, and professionals in the field.

Let’s introduce the latest round of finalists whose work has stood out in this Recognition Campaign.

Whether you’re a seasoned developer looking to expand your skillset or a newcomer eager to learn more about the Kotlin Multiplatform technology, we encourage you to explore this content, which provides a treasure trove of information.

And if you also have ideas to share, seize the opportunity to become a part of the Kotlin Multiplatform community of content creators! We choose our favorite new content once every three months and highlight it in the official Kotlin resources:

Are you struggling to come up with ideas for content? Use the following list of the most requested Kotlin Multiplatform topics for inspiration:

  • Use cases of what you have shared with Kotlin Multiplatform.
  • Experiments with cutting-edge Kotlin Multiplatform tools and libraries
  • Experience with Compose Multiplatform for iOS.
  • Migrating large projects to Kotlin Multiplatform.

Don’t limit yourself to these topics! Feel free to share your expertise and experience on another subject. Just don’t forget to add the #kotlinmultiplatform tag if the media platform you’re using allows it.

We’re excited to see how our community will continue to shape the Kotlin Multiplatform landscape in the future. Cheers to the creators who keep our community vibrant and thriving!

Continue ReadingShining a Spotlight on Kotlin Multiplatform Content Creators

Compose Multiplatform 1.5.0 Release

As of today, Compose Multiplatform 1.5.0 is available for you to use. It takes the Jetpack Compose declarative UI framework for Kotlin and extends it beyond Android to desktop, iOS, and web. The desktop version is stable, iOS is in Alpha, and support for web is experimental. For a full introduction, see the Compose Multiplatform website

Some highlights from this release are:

  1. The Dialog, Popup, and WindowInsets APIs are now in common code.
  2. On iOS scrolling, resource management and text fields have been improved.
  3. The UI testing framework has been stabilized on desktop.

This release is based on Jetpack Compose 1.5, which focuses on performance improvements. It also builds on the 1.1 release of Material Design 3. This includes new components such as date pickers and time pickers.

Try Compose Multiplatform 1.5.0

Compose Multiplatform supports Dialogs, Popups, and WindowInsets

As of version 1.5, dialogs and popups are available in Compose Multiplatform. Dialogs are used for modal events, where the user makes a choice or enters some data. Popups, meanwhile, are for non-modal behavior, such as offering optional functionality.

In this release, the base types Dialog and Popup, as well as DropdownMenu and AlertDialog, are accessible from within common code. This avoids the need to provide platform-specific functionality.

For example, the Composable below is written entirely in common code:

@Composable
fun CommonDialog() {
   var isDialogOpen by remember { mutableStateOf(false) }
   Button(onClick = { isDialogOpen = true }) {
       Text("Open")
   }
   if (isDialogOpen) {
       AlertDialog(
           onDismissRequest = { },
           confirmButton = {
               Button(onClick = { isDialogOpen = false }) {
                   Text("OK")
               }
           },
           title = { Text("Alert Dialog") },
           text = { Text("Lore ipsum") },
       )
   }
}

This is how it will appear on desktop:

Demonstration of the Dialog Boxes on Desktop

And this is how it will look on Android and iOS:

Demonstration of the Dialog Boxes on Android
            
Demonstration of the Dialog Boxes on iOS

A third feature, available in this release, is the WindowInsets API, which describes how much adjustment is required to prevent your content overlapping with the system UI. From version 1.5, this functionality is included with Compose Multiplatform, and so can be used on both Android and iOS. 

Using the WindowInsets API, you can draw background content via Compose Multiplatform behind the notch. This is done without adding a white line on top of the application. The screenshots below illustrate the difference this makes:

WindowInsets API Before and After in Compose Multiplatform

Improvements on iOS

The iOS platform was the focus of this release, and includes a wide variety of improvements. Scrolling mimics the platform’s look and feel, resource management has been simplified, and text handling is enhanced.

Natural scrolling

In this release, iOS scrolling is adapted to mimic native scrolling. Let’s say we have code where the number and/or size of items to be displayed exceeds the available space:

@Composable
fun NaturalScrolling() {
   val items = (1..30).map { "Item $it" }
   LazyColumn {
       items(items) {
           Text(
               text = it,
               fontSize = 30.sp,
               modifier = Modifier.padding(start = 20.dp)
           )
       }
   }
}

When scrolling, items spring from the edges of the screen, as with native iPhone applications:

Scrolling Springs on iOS

Support for Dynamic Type

The Dynamic Type feature on iOS allows a user to set their preferred font size – larger for ease of viewing or smaller to fit in more content. The text sizing used within an app should be relative to this system setting. 

This feature is now supported in Compose Multiplatform. The increments used in scaling the text are the same as those used in native applications, so the behavior will be identical.

For example, given the following Composable:

@Composable
fun DynamicType() {
   Text("This is some sample text", fontSize = 30.sp)
}

This is what will be displayed when the preferred reading size is set to the minimum:

Dynamic Type feature on iOS in Compose Multiplatform (small text)

Whereas, this is the result when the preferred reading size is at the maximum:

Dynamic Type feature on iOS in Compose Multiplatform (large text)

Support for high-refresh rate displays

In previous versions, the maximum frame rate was 60 FPS. This could result in the UI being slow and laggy on devices with 120Hz screens. From this release, frame rates of up to 120 FPS are supported.

Simplified resource management

From 1.5.0 onwards, any assets in the resources folder of an iOS source set are copied into the application bundle by default. So, for example, if you place an image file into src/commonMain/resources/, it will be copied to the bundle and is usable from your code.

If you are using CocoaPods, you no longer need to configure this behavior in the Gradle build file. You also don’t need to reinvoke podInstall to ensure assets are copied after modification. 

From this release, if you try to configure the behavior explicitly in build scripts (as shown below), then you will receive an error:

kotlin {
    cocoapods {
        extraSpecAttributes["resources"] = "..."
    }
}

For full details, and a guide to migrating existing code, please see this document.

Improved TextField

In earlier releases, there were two situations where entering text could cause unwanted behavior. From this release, TextField has been enhanced to overcome these issues.

Capitalization issues

Firstly, TextField now recognizes when the automatic capitalization of the first letter has been disabled. This is important, for example, when entering passwords. You control this behavior via the keyboardOptions argument.

To illustrate this, examine the Composable below: 

fun TextFieldCapitalization() {
   var text by remember { mutableStateOf("") }
   TextField(
       value = text,
       onValueChange = { text = it },
       keyboardOptions = KeyboardOptions(
           capitalization = KeyboardCapitalization.Sentences,
           autoCorrect = false,
           keyboardType = KeyboardType.Ascii,
       ),
   )
}

The image on the left shows what happens when the capitalization property is set to KeyboardCapitalization.None, whereas the image on the right shows what happens when the value is KeyboardCapitalization.Sentences.

Keyboard Capitalization Sentences with TextField
            
Keyboard Capitalization None

Hardware keyboards

The second situation relates to hardware keyboards. In previous versions, when using a hardware keyboard, pressing Enter resulted in multiple newlines, and pressing Backspace triggered multiple deletions. From this release, these events are now processed correctly.

Improvements on desktop

Stabilized test framework

This release stabilizes support for testing on Compose for desktop. Jetpack Compose provides a set of testing APIs to verify the behavior of your Compose code. These APIs were ported to desktop and available in previous releases, but with limitations. These limitations have now been removed, making it possible to write comprehensive UI tests for your application.

In order to provide an overview of the testing functionality, let’s create and test a simple UI. Here’s our example Composable:

@Composable
fun App() {
   var searchText by remember { mutableStateOf("cats") }
   val searchHistory = remember { mutableStateListOf<String>() }


   Column(modifier = Modifier.padding(30.dp)) {
       TextField(
           modifier = Modifier.testTag("searchText"),
           value = searchText,
           onValueChange = {
               searchText = it
           }
       )
       Button(
           modifier = Modifier.testTag("search"),
           onClick = {
               searchHistory.add("You searched for: $searchText")
           }
       ) {
           Text("Search")
       }
       LazyColumn {
           items(searchHistory) {
               Text(
                   text = it,
                   fontSize = 20.sp,
                   modifier = Modifier.padding(start = 10.dp).testTag("attempt")
               )
           }
       }
   }
}

This creates a simple UI that records search attempts:

Search App Used for Testing

Notice that Modifier.testTag has been used to assign names to TextField, Button and the items in LazyColumn

We can then manipulate the UI within a JUnit test:

class SearchAppTest {
   @get:Rule
   val compose = createComposeRule()


   @Test
   fun `Should display search attempts`() {
       compose.setContent {
           App()
       }


       val testSearches = listOf("cats", "dogs", "fish", "birds")


       for (text in testSearches) {
           compose.onNodeWithTag("searchText").performTextReplacement(text)
           compose.onNodeWithTag("search").performClick()
       }


       val lastAttempt = compose
           .onAllNodesWithTag("attempt")
           .assertCountEquals(testSearches.size)
           .onLast()


       val expectedText = "You searched for: ${testSearches.last()}"
       lastAttempt.assert(hasText(expectedText))
   }
}

Using the Compose-specific JUnit rule we:

  1. Set the content of the UI as the App Composable.
  2. Locate the text field and button via onNodeWithTag
  3. Repeatedly enter sample values into the text field and click the button.
  4. Find all the text nodes that were generated via onAllNodesWithTag.
  5. Assert that the current number of text nodes were created, and acquire the last.
  6. Assert that this last attempt contains the expected message.

Enhanced Swing interop

This release introduces experimental support for improved rendering of compose panels inside Swing components. This prevents transitional rendering issues when panels are being shown, hidden, or resized. It also enables proper layering when combining Swing components and compose panels. A Swing component can now be shown above or beneath a ComposePanel.

To illustrate this, examine the example below:

fun main() {
   System.setProperty("compose.swing.render.on.graphics", "true")
   SwingUtilities.invokeLater {
       val composePanel = ComposePanel().apply {
           setContent {
               Box(modifier = Modifier.background(Color.Black).fillMaxSize())
           }
       }


       val popup = object : JComponent() { ... }


       val rightPanel = JLayeredPane().apply {
           add(composePanel)
           add(popup)
           ...
       }


       val leftPanel = JPanel().apply { background = CYAN }


       val splitter = JSplitPane(..., leftPanel,rightPanel)


       JFrame().apply {
           add(splitter)
           setSize(600, 600)
           isVisible = true
       }
   }
}

In this code, we create and display a Swing JFrame, with the following content:

  1. The JFrame contains a JSplitPane with a vertical divider.
  2. On the left of the split pane is a standard JPanel, colored cyan.
  3. On the right is a JLayeredPane, made up of two layers:
    • A ComposePanel containing a Box composable, colored black
    • A custom Swing component, where the text “Popup” appears within a white rectangle. This is achieved by overriding the paintComponent method.

When the property compose.swing.render.on.graphics is set to true then: 

  • The custom Swing component is displayed on top of the Box Composable. 
  • There are no transitional graphical artifacts as the slider is moved.

Swing Interop Demo Working

If this flag had not been set, the custom component would not be visible, and there could be transitional artifacts as the slider was moved:

Swing Interop Demo Not Working

Please share your feedback about Compose Multiplatform. We invite you to join the discussion on the Kotlin Slack in the #compose channel, where you can discuss general topics related to Compose Multiplatform and Jetpack Compose. In #compose-ios, you can find discussions about Compose Multiplatform for iOS.

Try Compose Multiplatform 1.5.0

What else to read and watch

Continue ReadingCompose Multiplatform 1.5.0 Release

Help Us Improve the Performance of Your Compose Multiplatform Apps

The performance of Compose Multiplatform apps is one of our key priorities at JetBrains. Improving performance includes optimizing start-up time, rendering performance, and binary size, among other things. 

Currently, we’re focusing on enhancing rendering performance and providing smooth, glitchless, and jank-free animation on iOS. Our goal is to ensure that all different Compose apps work on iOS as smoothly as native iOS apps and Android apps. We’ve just released a number of performance improvements in the preview version of Compose Multiplatform 1.5.0, including improved rendering performance on modern 120Hz Apple devices and iOS-like scrolling. We need your feedback in order to keep making this already powerful UI framework even better!

In addition to better performance, this version of Compose Multiplatform also brings other functional enhancements that you may want to try, such as:

  • Support for iOS-specific insets in the WindowInsets API, which can be used from common code.
  • The ability to create Dialog and Popup composables in common code.
  • Support for the Dynamic Type feature that allows choosing the size of visible text in the global settings of Apple operating systems.

We would appreciate it if you could test 1.5.0-beta01 in your projects targeting iOS and share information about any performance issues that still exist.

Why your help is crucial

We have only a very limited number of sample apps, and they don’t cover all real-life cases. As a result, your help is extremely important and will allow us to make sure the technology meets the true performance expectations of your projects, as opposed to just meeting some generic benchmarks.

How to update to Compose Multiplatform 1.5.0-beta01

In the build.gradle.kts of your project, update the version of org.jetbrains.compose to 1.5.0-beta01 and load the Gradle changes.

What is a performance issue

If you notice that a Compose Multiplatform app doesn’t perform on iOS as it does on Android or as if it was a native iOS app, please report the issue, even if you consider it minor. Every issue matters to us!

How to report a performance issue

To help us effectively resolve the issue you encountered, please report a GitHub issue using the template below.

Report a performance issue

Learn more about Compose Multiplatform

Continue ReadingHelp Us Improve the Performance of Your Compose Multiplatform Apps

Update on the Name of Kotlin Multiplatform

TL;DR: To resolve the long-standing issues of naming inconsistency and abbreviation confusion that have puzzled many Kotlin developers over the past two years, we are deprecating the “Kotlin Multiplatform Mobile” (KMM) product name. From now on, “Kotlin Multiplatform” (KMP) is the preferred term when referring to the Kotlin technology for sharing code across different platforms, regardless of the combination of targets being discussed.

The origin of Kotlin Multiplatform

Kotlin Multiplatform was announced at KotlinConf 2017 under the name “Kotlin Multiplatform Projects”, and it originally supported the JVM, Native, and JS targets. We quickly garnered a number of early adopters who began using the abbreviations “KMP” and, less frequently, “MPP”. Until 2020, the technology was in the experimental stage, and the team was shaping it based on feedback from these early adopters.

In 2020, we shifted our focus to code-sharing between iOS and Android, the most common use case. We aimed to attract more mobile developers to Kotlin Multiplatform, use their feedback to enhance the technology, and prepare it for future improvements, including better support for other targets. To reflect this focus, we split everything in Kotlin Multiplatform related to code-sharing between iOS and Android into a separate product called “Kotlin Multiplatform Mobile”, introduced the abbreviation KMM for it, and announced its Alpha release. Along with that, we also released the Kotlin Multiplatform Mobile plugin for Android Studio.

The problem

While the Alpha release with the new Kotlin Multiplatform Mobile name garnered attention, it also led to confusion, as developers were uncertain about how to refer to technology that shared code beyond iOS and Android. This confusion was compounded by existing community content and libraries with names that included “KMP”, resulting in an ecosystem with multiple names – Kotlin Multiplatform and Kotlin Multiplatform Mobile – and the abbreviations KMP, KMM, and MPP. This not only complicated content discovery but also led to the misunderstanding that Kotlin Multiplatform was primarily for mobile code sharing.

The solution

To resolve the long-standing issues of naming inconsistency and abbreviation confusion that have puzzled many Kotlin developers over the past two years, we are deprecating the “Kotlin Multiplatform Mobile” product name.

From now on, “Kotlin Multiplatform” is the preferred term when referring to the Kotlin technology for sharing code, regardless of the combination of platforms being discussed.

KMP is excellent for sharing code across multiple platforms, not just iOS and Android. It enables you to share code with desktop and server-side as well. Moreover, we are actively developing Kotlin/Wasm to facilitate modern web development with Kotlin Multiplatform. When used alongside Compose Multiplatform, which now supports Android, desktop, iOS (Alpha), and web (Experimental), you gain more freedom and can opt to share 100% of your codebase – all in Kotlin. JetBrains aims to deliver further improvements for Kotlin Multiplatform and Compose Multiplatform, making this combo the ultimate choice for sharing code between platforms.

Moving forward together

We want to thank every content creator and library author in the Kotlin Multiplatform ecosystem. The hard work you put into building content and libraries is integral to KMP’s development and growth.

We encourage you to adopt the name “Kotlin Multiplatform” (KMP) in your existing and future content and libraries. This unified terminology will streamline the onboarding process for new users and help KMP evolve further. We value your efforts and thank you for your continued commitment.

Continue ReadingUpdate on the Name of Kotlin Multiplatform

Kudos to New Kotlin Multiplatform Content Creators!

In today’s ever evolving technology landscape, the power of community-driven content cannot be overstated. Kotlin Multiplatform is making steady progress towards stability, and its ecosystem is growing and evolving. Meanwhile, Compose Multiplatform is developing at a rapid pace with the development of Compose for iOS currently in its Alpha stage. This advancement and expansion owe a great deal to the ideas, perspectives, and passions of our community contributors.

To acknowledge and appreciate the efforts of content makers, we regularly organize the Kotlin Multiplatform Content Creators Recognition Campaigns, which highlight articles and videos around the technology. In this blog post, we’re sharing another round of content pieces that will serve as a source of inspiration for learners.

Don’t miss out on the opportunity to become a part of the Kotlin Multiplatform community of content creators and see your work highlighted in one of the official Kotlin resources. We choose our favorite new content once every three months and promote it by:

If you’re struggling to come up with a fresh idea for content, feel free to use the following list of the most requested Kotlin Multiplatform topics for inspiration:

  • Experiments with cutting-edge tools and libraries, such as Kotlin Multiplatform libraries in Jetpack.
  • Experience with Compose Multiplatform for iOS.
  • Use cases – what have you shared with Kotlin Multiplatform?
  • The migration of large projects to Kotlin Multiplatform.

This list is just to help you get inspired, so don’t limit yourself. Feel free to share your expertise and experience on atopic of your choice. We love what our community has to say and can’t wait to see what you come up with! Don’t forget to add the #kotlinmultiplatform tag if the media platform you’re using allows it.

Adding the #kotlinmultiplatform tag on the media platform when posting content about Kotlin Multiplatform

You can also send us a link to your article, video, sample project, or any other type of content to kmm.feedback@kotlinlang.org so we don’t miss out!

We’d like to thank all of the content creators for their efforts and invite everyone to explore their work. Get motivated and continue building a vibrant community that drives the future of our technology forward!

Continue ReadingKudos to New Kotlin Multiplatform Content Creators!

End of content

No more pages to load