{"id":449707,"date":"2024-02-29T18:58:33","date_gmt":"2024-02-29T17:58:33","guid":{"rendered":"https:\/\/blog.jetbrains.com\/?post_type=kotlin&#038;p=449707"},"modified":"2025-03-06T10:22:45","modified_gmt":"2025-03-06T09:22:45","slug":"compose-multiplatform-1-6-0-release","status":"publish","type":"kotlin","link":"https:\/\/blog.jetbrains.com\/ja\/kotlin\/2024\/02\/compose-multiplatform-1-6-0-release","title":{"rendered":"Compose Multiplatform 1.6.0 \u2013 Resources, UI Testing, iOS Accessibility, and Preview Annotation"},"content":{"rendered":"\n<p>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&#8217;s latest <a href=\"https:\/\/developer.android.com\/jetpack\/compose\" data-type=\"link\" data-id=\"https:\/\/developer.android.com\/jetpack\/compose\" target=\"_blank\" rel=\"noreferrer noopener\">Jetpack Compose update<\/a>.<\/p>\n\n\n\n<p align=\"center\"><a class=\"ek-link jb-download-button\" title=\"Get Started with Compose Multiplatform\" href=\"https:\/\/www.jetbrains.com\/help\/kotlin-multiplatform-dev\/compose-multiplatform-getting-started.html?utm_source=kotlinblog&#038;utm_medium=cta&#038;utm_campaign=compose-1.6.0\" target=\"_blank\" rel=\"noopener\">Get Started with Compose Multiplatform<\/a><\/p>\n\n\n\n<p>This release of Compose Multiplatform:<\/p>\n\n\n\n<ul>\n<li>Revamps the resource management library.<\/li>\n\n\n\n<li>Introduces a UI testing API.<\/li>\n\n\n\n<li>Adds iOS accessibility support.<\/li>\n\n\n\n<li>Brings a host of other features and improvements.<\/li>\n<\/ul>\n\n\n\n<p>For a description of all notable changes, see our&nbsp;<a href=\"https:\/\/www.jetbrains.com\/help\/kotlin-multiplatform-dev\/whats-new-compose-1-6-0.html\" target=\"_blank\" rel=\"noreferrer noopener\">What\u2019s new in Compose Multiplatform 1.6.0<\/a>&nbsp;page or check <a href=\"https:\/\/github.com\/JetBrains\/compose-multiplatform\/releases\/tag\/v1.6.0\" data-type=\"link\" data-id=\"https:\/\/github.com\/JetBrains\/compose-multiplatform\/releases\/tag\/v1.6.0\" target=\"_blank\" rel=\"noreferrer noopener\">the&nbsp;release notes on GitHub<\/a>.<\/p>\n\n\n\n<div class=\"wp-block-rank-math-toc-block\" id=\"rank-math-toc\"><h2>Table of Contents<\/h2><nav><ul><li class=\"\"><a href=\"#common-resources-api\">Common resources API<\/a><\/li><li class=\"\"><a href=\"#common-api-for-ui-testing\">Common API for UI testing<\/a><\/li><li class=\"\"><a href=\"#i-os-accessibility-support\">iOS accessibility support<\/a><\/li><li class=\"\"><a href=\"#preview-annotation-for-fleet\">@Preview annotation for Fleet<\/a><\/li><li class=\"\"><a href=\"#separate-platform-views-for-popups-dialogs-and-dropdown-menus\">Separate platform views for popups, dialogs, and dropdown menus<\/a><\/li><\/ul><\/nav><\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"common-resources-api\">Common resources API<\/h2>\n\n\n\n<p>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.<\/p>\n\n\n\n<p>The resources are organized in a number of directories as part of the <code>commonMain<\/code> source set:<\/p>\n\n\n\n<ul>\n<li><code>composeResources\/drawable<\/code> contains images<\/li>\n\n\n\n<li><code>composeResources\/font<\/code> contains fonts<\/li>\n\n\n\n<li><code>composeResources\/values<\/code> contains strings (in the format of <code>strings.xml<\/code>)<\/li>\n\n\n\n<li><code>composeResources\/files<\/code> contains any other files.<\/li>\n<\/ul>\n\n\n\n<p>Compose Multiplatform generates type-safe accessors for all of these resource types (excluding the <code>files<\/code> directory). For example, after placing a vector image <code>compose-multiplatform.xml<\/code> in the <code>composeResources\/drawable<\/code> directory, you can access it in your Compose Multiplatform code using the generated <code>Res<\/code> object:<\/p>\n\n\n\n<pre class=\"kotlin-code\" data-highlight-only=\"true\" theme=\"idea\" indent=\"4\" style=\"visibility: hidden; padding: 36px 0;\">\nimport androidx.compose.foundation.Image\nimport androidx.compose.runtime.Composable\nimport kotlinproject.composeapp.generated.resources.*\nimport org.jetbrains.compose.resources.ExperimentalResourceApi\nimport org.jetbrains.compose.resources.painterResource\n\n@OptIn(ExperimentalResourceApi::class)\n@Composable\nfun Logo() {\n    Image(\n        painterResource(Res.drawable.compose_multiplatform),\n        contentDescription = &quot;CMP Logo&quot;\n    )\n}\n<\/pre>\n\n\n\n<p>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\u2019re 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.<\/p>\n\n\n\n<p>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 <a href=\"https:\/\/www.jetbrains.com\/help\/kotlin-multiplatform-dev\/compose-images-resources.html\" target=\"_blank\" rel=\"noreferrer noopener\">the official documentation<\/a>!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"common-api-for-ui-testing\">Common API for UI testing<\/h2>\n\n\n\n<p>UI testing helps you make sure that your application behaves the way it is supposed to. With Compose Multiplatform 1.6.0, we\u2019re introducing an experimental API that allows you to write common UI tests for Compose Multiplatform that validate the behavior of your application\u2019s user interface across the different platforms supported by the framework.<\/p>\n\n\n\n<p>For example, you may want to ensure that a custom component correctly shows an informative string with the proper prefix:<\/p>\n\n\n\n<pre class=\"kotlin-code\" data-highlight-only=\"true\" theme=\"idea\" indent=\"4\" style=\"visibility: hidden; padding: 36px 0;\">\n@Composable\nfun MyInfoComposable(info: String, modifier: Modifier = Modifier) {\n    Text(modifier = modifier, text = &quot;[IFNO] $info&quot;)\n}\n<\/pre>\n\n\n\n<p>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 <a href=\"https:\/\/developer.android.com\/jetpack\/compose\/testing\" target=\"_blank\" rel=\"noreferrer noopener\">Jetpack Compose on Android<\/a>. After following the setup instructions from <a href=\"https:\/\/jetbrains.com\/help\/kotlin-multiplatform-dev\/compose-test.html\" target=\"_blank\" rel=\"noreferrer noopener\">the documentation<\/a> you can write a test that ensures the prefix is added properly:<\/p>\n\n\n\n<pre class=\"kotlin-code\" data-highlight-only=\"true\" theme=\"idea\" indent=\"4\" style=\"visibility: hidden; padding: 36px 0;\">\nimport androidx.compose.ui.test.ExperimentalTestApi\nimport androidx.compose.ui.test.runComposeUiTest\n...\n\nclass InformationTest {\n    @OptIn(ExperimentalTestApi::class)\n    @Test\n    fun shouldPrefixWithInfoTag() = runComposeUiTest {\n        setContent {\n            MyInfoComposable(&quot;Important things!&quot;, modifier = Modifier.testTag(&quot;info&quot;))\n        }\n        onNodeWithTag(&quot;info&quot;).assertTextContains(&quot;[INFO]&quot;, substring = true)\n    }\n}\n<\/pre>\n\n\n\n<p>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!):<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-resized\"><img decoding=\"async\" loading=\"lazy\" width=\"2586\" height=\"620\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2024\/02\/compose-test-result.png\" alt=\"\" class=\"wp-image-445971\" style=\"aspect-ratio:4.170967741935484;width:840px;height:auto\"\/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"i-os-accessibility-support\">iOS accessibility support<\/h2>\n\n\n\n<p>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:<\/p>\n\n\n\n<ul id=\"7277ddf8\">\n<li>Screen readers and VoiceOver can access the content of the Compose Multiplatform UI.<\/li>\n\n\n\n<li>Compose Multiplatform UI supports the same gestures as the native UIs for navigation and interaction.<\/li>\n<\/ul>\n\n\n\n<p>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.<\/p>\n\n\n\n<p>For details on the implementation and limitations of the current accessibility support, see <a href=\"https:\/\/www.jetbrains.com\/help\/kotlin-multiplatform-dev\/compose-ios-accessibility.html\" target=\"_blank\" rel=\"noreferrer noopener\">the documentation page<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"preview-annotation-for-fleet\">@Preview annotation for Fleet<\/h2>\n\n\n\n<p>With 1.6.0, Compose Multiplatform introduces the common <code>@Preview<\/code> annotation (previously available only for Android and Desktop). This annotation is supported by <a href=\"https:\/\/www.jetbrains.com\/fleet\/\" target=\"_blank\" rel=\"noopener\">JetBrains Fleet<\/a> (starting with <a href=\"https:\/\/blog.jetbrains.com\/ja\/fleet\/2024\/02\/fleet-1-31-improved-markdown-experience-additional-run-configuration-macros-support-for-vitest-and-more\" data-type=\"link\" data-id=\"https:\/\/blog.jetbrains.com\/fleet\/2024\/02\/fleet-1-31-improved-markdown-experience-additional-run-configuration-macros-support-for-vitest-and-more\/\" target=\"_blank\" rel=\"noreferrer noopener\">Fleet 1.31<\/a>). Add <code>@Preview<\/code> to your <code>@Composable<\/code> function, and you&#8217;ll be able to open the preview via the gutter icon:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img decoding=\"async\" loading=\"lazy\" width=\"1662\" height=\"1194\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2024\/02\/fleet-compose-preview-2.png\" alt=\"\" class=\"wp-image-450517\"\/><\/figure>\n\n\n\n<p>Try it out with a project generated by the <a href=\"https:\/\/kmp.jetbrains.com\/\" target=\"_blank\" rel=\"noreferrer noopener\">Kotlin Multiplatform wizard<\/a>!<\/p>\n\n\n\n<p>Fleet currently supports the <code>@Preview<\/code> annotation for <code>@Composable<\/code> functions without parameters. To use this common annotation, add the experimental <code>compose.components.uiToolingPreview<\/code> library to your dependencies (as opposed to <code>compose.uiTooling<\/code>, used for desktop and Android).<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"separate-platform-views-for-popups-dialogs-and-dropdown-menus\">Separate platform views for popups, dialogs, and dropdown menus<\/h2>\n\n\n\n<p>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 <code>Dialog<\/code>, <code>Popup<\/code>, or <code>Dropdown<\/code> composables in these scenarios, they can expand beyond the bounds of the individual widget and even expand across the entire screen!<\/p>\n\n\n\n<p>This is also possible for desktop targets, although as an <a href=\"https:\/\/www.jetbrains.com\/help\/kotlin-multiplatform-dev\/whats-new-compose-1-6-0.html#separate-platform-views-for-popups-dialogs-and-dropdowns-ios-desktop\" target=\"_blank\" rel=\"noreferrer noopener\">experimental feature<\/a> for now.<\/p>\n\n\n\n<img decoding=\"async\" src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2024\/02\/Compose-Multiplatform-Demo.png\" alt=\"Dialog, Popup, or Dropdown in Compose Multiplatform\" data-gif-src=\"https:\/\/blog.jetbrains.com\/wp-content\/uploads\/2024\/02\/Compose-Multiplatform-Demo.gif\">\n\n\n\n<h2 class=\"wp-block-heading\" id=\"other-notable-changes\">Other notable changes<\/h2>\n\n\n\n<p>To learn about the rest of the changes included in this release:<\/p>\n\n\n\n<ul>\n<li><a href=\"https:\/\/www.jetbrains.com\/help\/kotlin-multiplatform-dev\/compose-multiplatform-getting-started.html\" data-type=\"link\" data-id=\"https:\/\/www.jetbrains.com\/help\/kotlin-multiplatform-dev\/compose-multiplatform-getting-started.html\" target=\"_blank\" rel=\"noreferrer noopener\"><\/a>See <a href=\"https:\/\/www.jetbrains.com\/help\/kotlin-multiplatform-dev\/whats-new-compose-1-6-0.html\" target=\"_blank\" rel=\"noreferrer noopener\">What\u2019s new in Compose Multiplatform 1.6.0<\/a> page where we talk about improvements and features introduced in 1.6.0 in more detail.<\/li>\n\n\n\n<li><a href=\"https:\/\/github.com\/JetBrains\/compose-multiplatform\/releases\/tag\/v1.5.10?utm_source=kotlinblog&amp;utm_medium=blogpost&amp;utm_campaign=compose-1-5-10\" data-type=\"link\" data-id=\"https:\/\/github.com\/JetBrains\/compose-multiplatform\/releases\/tag\/v1.5.10?utm_source=kotlinblog&amp;utm_medium=blogpost&amp;utm_campaign=compose-1-5-10\" target=\"_blank\" rel=\"noreferrer noopener\"><\/a><a href=\"https:\/\/github.com\/JetBrains\/compose-multiplatform\/releases\/tag\/v1.6.0\" data-type=\"link\" data-id=\"https:\/\/github.com\/JetBrains\/compose-multiplatform\/releases\/tag\/v1.6.0\" target=\"_blank\" rel=\"noreferrer noopener\">Compose Multiplatform release notes on GitHub<\/a> has an exhaustive list of merged pull requests for 1.6.0.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"what-else-to-read-and-watch\">What else to read and watch<\/h2>\n\n\n\n<ul>\n<li><a href=\"https:\/\/www.jetbrains.com\/help\/kotlin-multiplatform-dev\/compose-multiplatform-getting-started.html\" target=\"_blank\" rel=\"noreferrer noopener\">Get started with Compose Multiplatform \u2014 tutorial<\/a><\/li>\n<\/ul>\n\n\n\n<ul>\n<li><a href=\"https:\/\/www.youtube.com\/live\/IGuVIRZzVTk?si=x5EH-ztI6gT2JM4c\" target=\"_blank\" rel=\"noreferrer noopener\">Build Apps for iOS, Android, and Desktop With Compose Multiplatform \u2014 video<\/a><\/li>\n\n\n\n<li><a href=\"https:\/\/www.jetbrains.com\/help\/kotlin-multiplatform-dev\/compose-multiplatform-and-jetpack-compose.html\" target=\"_blank\" rel=\"noreferrer noopener\">Compose Multiplatform and Jetpack Compose<\/a><\/li>\n<\/ul>\n","protected":false},"author":1038,"featured_media":448125,"comment_status":"closed","ping_status":"closed","template":"","categories":[956],"tags":[6706,477],"cross-post-tag":[],"acf":[],"_links":{"self":[{"href":"https:\/\/blog.jetbrains.com\/ja\/wp-json\/wp\/v2\/kotlin\/449707"}],"collection":[{"href":"https:\/\/blog.jetbrains.com\/ja\/wp-json\/wp\/v2\/kotlin"}],"about":[{"href":"https:\/\/blog.jetbrains.com\/ja\/wp-json\/wp\/v2\/types\/kotlin"}],"author":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/ja\/wp-json\/wp\/v2\/users\/1038"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/ja\/wp-json\/wp\/v2\/comments?post=449707"}],"version-history":[{"count":10,"href":"https:\/\/blog.jetbrains.com\/ja\/wp-json\/wp\/v2\/kotlin\/449707\/revisions"}],"predecessor-version":[{"id":551542,"href":"https:\/\/blog.jetbrains.com\/ja\/wp-json\/wp\/v2\/kotlin\/449707\/revisions\/551542"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/ja\/wp-json\/wp\/v2\/media\/448125"}],"wp:attachment":[{"href":"https:\/\/blog.jetbrains.com\/ja\/wp-json\/wp\/v2\/media?parent=449707"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/ja\/wp-json\/wp\/v2\/categories?post=449707"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/ja\/wp-json\/wp\/v2\/tags?post=449707"},{"taxonomy":"cross-post-tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/ja\/wp-json\/wp\/v2\/cross-post-tag?post=449707"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}