支持 PC 、Web 和 Android 的 Compose Multiplatform 進入 Alpha 版本

原文連接:blog.jetbrains.com/kotlin/2021…html

Compose Multiplatform 的發佈標誌着使用 Kotlin 開發統一的 UI 支持又邁進了新一步!java

基於 Google 發佈的 Jetpack Compose Android 1.0 穩定版 的前提 :android

  • Compose for Desktop 和 Compose for Web 已經升級爲 Alpha 版本,它們的版本控制如今在 Compose Multiplatform 下保持一致,從而可使用相同的 artifacts 構建 Android、Desktop 和 Web UI。git

  • IDE 管理應用 JetBrains Toolbox App 已完成遷移到 Compose for Desktop。github

  • IntelliJ IDEA 和 Android Studio 的新插件 經過@Preview註釋能夠啓用 Compose for Desktop 的組件預覽。web

  • Compose for Desktop 如今默認使用可組合 API Window ,提供對自適應窗口大小、統一圖像資源的新支持,以及對 ARM64 上 Linux 的新平臺支持,容許在 Raspberry Pi 等目標上運行它。api

  • Compose for Web 進一步擴展了 DOM 和 CSS API。瀏覽器

另外在 The Compose Story 中 概述了 Compose 的路徑,並分享了更多聲明式多平臺用戶界面的信息!安全

統一 Desktop、Web 和 Android UI 開發

Jetpack Compose 是一個爲 Android 構建原生用戶界面的響應式開發 UI 框架,JetBrains 在 Google 的 Jetpack Compose 的基礎上將 Compose 框架拓展到更多新的平臺。服務器

藉助 Compose Multiplatform,開發者可使用和 Android Jetpack Compose 相同的 API 開發 Desktop 和 Web 構建用戶界面。

使用 Kotlin Multiplatform 提供的機制,如今能夠針對同一項目中的如下任意組合:

  • Android (Jetpack Compose)
  • Desktop
  • Web

之前 Compose for Desktop 和 Compose for Web 使用不一樣的 artifacts ,而如今開始它們將統一在一個 Gradle 插件和組件下,這意味着基於 Compose 開發 Android、Desktop 和 Web 用戶界面會更容易。

憑藉 Alpha 版本的更新,Compose Multiplatform 提供的 API 已經很接近其最終形態,咱們將全力投入 Compose 的開發支持,並指望在 2021 年內能達到 1.0 版本,更多詳細信息:瞭解有關 COMPOSE 多平臺的更多信息

Compose in Production:JetBrains Toolbox 應用

在 JetBrains 如今一些生產應用已經開始採用 Compose,首先是 JetBrains Toolbox App,它是 JetBrains IDE 的管理應用程序,每個月活躍用戶超過 800,000。

在它們的最新版本中,該團隊已將應用程序的實現徹底轉換爲 Compose for Desktop,在從基於 Electron 的 UI 遷移期間,團隊注意到了 Compose 的許多優點:

  • 內存消耗顯着減小,特別是當應用程序在後臺運行時
  • 安裝程序大小減小了大約 50%
  • 應用總體渲染性能顯着提高

JetBrains Toolbox 團隊負責人 Victor Kropp 也在帖子中分享了他對 Compose for Desktop 的見解:

Compose for Desktop 雖然仍處於早期階段,但已被證明了 Toolbox App 的絕佳選擇。在開發框架同事的支持下,幾乎能夠在短期內重寫整個 UI。這使咱們可以統一開發體驗,所以從業務邏輯到 UI,從應用到服務器,Toolbox 如今 100% 是 Kotlin。

用於 Compose Multiplatform 的新 IntelliJ IDEA 和 Android Studio 插件

在此版本中還發布了一個新的 IDE 插件來支持開發工做:用於 IntelliJ IDEA 和 Android Studio 的 Compose Multiplatform 插件,它與框架的新版本一塊兒發佈,並提供額外的功能來幫助用戶界面的開發工做

第一個版本包括了一項期待已久的功能:可以直接在 IDE 中預覽 Compose for Desktop 和 Android 組件,甚至無需啓動應用程序

要顯示@Composable不帶參數的函數預覽,能夠將@Preview註釋添加到其定義中,這時候會添加一個小的裝訂線圖標,可使用它來切換組件的預覽窗格:

這個新的預覽版能夠幫助開發者縮短開發週期,並更輕鬆地將想法轉化爲基於 Compose 的真實設計和佈局。

要查找並安裝新插件,請在插件市場中搜索「Compose Multiplatform IDE Support」,或點擊下方直接打開插件頁面:安裝 COMPOSE 多平臺插件

Compose for Desktop 的新增功能

除了將 Compose for Desktop 升級爲 Alpha 的一大步以外,在此版本中還改進了其 API 並增長了對新平臺的支持。

默認狀況下可組合的窗口 API

在里程碑4桌面版中,咱們推出了一個實驗組APIWindowMenuBarTray,這些新 API 都使用 @Composable 與應用程序中的其餘組件相同的狀態管理、行爲和條件呈現概念。

在此版本中,這些可組合版本如今是管理窗口、菜單欄和托盤圖標的默認方式,取代了舊的窗口 API。

若是尚未嘗試過這些新 API,或者只是想了解有關它們提供的行爲和功能的更多信息,能夠參考更新的 Compose for Desktop 教程,瞭解窗口和托盤管理。

自適應窗口大小

有時咱們想將某些內容做爲一個總體顯示,而在不事先知道將顯示的內容的狀況下,這意味着咱們不知道它的最佳窗口尺寸。

爲了更輕鬆地開發這些 UI 場景,咱們引入了自適應窗口大小功能,經過將窗口的一個或兩個維度設置WindowSizeDp.Unspecified,Compose for Desktop 將自動調整該維度中窗口的初始大小以適應其內容:

fun main() = application {
   val state = rememberWindowState(width = Dp.Unspecified, height = Dp.Unspecified) //automatic size
   Window(
       onCloseRequest = ::exitApplication,
       state = state,
       title = "Adaptive",
       resizable = false
   ) {
       Column(Modifier.background(Color(0xFFEEEEEE))) {
           Row {
               Text("label 1", Modifier.size(100.dp, 100.dp).padding(10.dp).background(Color.White))
               Text("label 2", Modifier.size(150.dp, 200.dp).padding(5.dp).background(Color.White))
               Text("label 3", Modifier.size(200.dp, 300.dp).padding(25.dp).background(Color.White))
           }
       }
   }
}
複製代碼

連同刪除窗口(經過undecorated = true 的應用程序Window定義),咱們相信這種建立動態大小窗口的新方法,爲各類形狀和大小的用戶界面新增了額外的可能性。

可組合窗口菜單的附加功能

桌面應用一般帶有豐富而複雜的窗口菜單。在此版本中還添加了容許建立豐富菜單的其餘 API。

它們能夠被結構化,經過圖標、快捷方式和助記符來豐富,並集成普遍使用的複選框和單選列表(單選按鈕)的邏輯:

@OptIn(ExperimentalComposeUiApi::class)
@Composable
private fun MenuBarScope.FileMenu() = Menu("Settings", mnemonic = 'S') {
   Item(
       "Reset",
       mnemonic = 'R',
       shortcut = KeyShortcut(Key.R, ctrl = true),
       onClick = { println("Reset") }
   )
   CheckboxItem(
       "Advanced settings",
       mnemonic = 'A',
       checked = isAdvancedSettings,
       onCheckedChange = { isAdvancedSettings = !isAdvancedSettings }
   )
   if (isAdvancedSettings) {
       Menu("Theme") {
           RadioButtonItem(
               "Light",
               mnemonic = 'L',
               icon = ColorCircle(Color.LightGray),
               selected = theme == Theme.Light,
               onClick = { theme = Theme.Light }
           )
           RadioButtonItem(
               "Dark",
               mnemonic = 'D',
               icon = ColorCircle(Color.DarkGray),
               selected = theme == Theme.Dark,
               onClick = { theme = Theme.Dark }
           )
       }
   }
}
複製代碼

支持上下文菜單

Compose for Desktop Alpha 支持默認和自定義上下文菜單,能夠經過單擊鼠標右鍵觸發。

對於可選擇的文本和文本字段,該框架提供了一組默認的上下文菜單項,讓用戶能夠複製、粘貼、剪切和選擇。

@OptIn(ExperimentalComposeUiApi::class, androidx.compose.foundation.ExperimentalFoundationApi::class)
fun main() = singleWindowApplication(title = "Context menu") {
   DesktopMaterialTheme { //it is mandatory for Context Menu
       val text = remember {mutableStateOf("Hello!")}
       ContextMenuDataProvider(
           items = {
               listOf(ContextMenuItem("Clear") { text.value = "" })
           }
       ) {
               TextField(
                   value = text.value,
                   onValueChange = { text.value = it },
                   label = { Text(text = "Input") }
               )
       }
   }
}
複製代碼

光標更改行爲和指針圖標 API

在此版本的 Compose for Desktop 開始,當鼠標懸停在文本字段或可選文本上時,鼠標指針如今會自動變成文本選擇光標,表示能夠進行文本選擇,使應用感受更加貼近原生。

對於本身的組件,還可使用新添加的 pointerIcon 修飾符來調整鼠標指針的行爲,能夠在將鼠標懸停在特定組件上時更改指針。

@OptIn(ExperimentalComposeUiApi::class)
@Composable
fun ApplicationScope.pointerIcons() {
   Window(onCloseRequest = ::exitApplication, title = "Pointer icons") {
           Text(
               modifier = Modifier.pointerIcon(PointerIcon.Hand),
               text = "Hand icon!"
           )
   }
}
複製代碼

鼠標可點擊修改器

爲了更方便處理在鼠標單擊時單擊或按下的鼠標按鈕和鍵盤修飾鍵,這裏引入了一個帶有.mouseClickable 修飾符的新 API 。

將此修飾符添加到組件就能夠容許指定接收 MouseClickScope 的回調,它提供了有關事件的完整信息:

@ExperimentalDesktopApi
@Composable
fun ApplicationScope.mouseClickable() {
   Window(onCloseRequest = ::exitApplication, title = "mouseClickable") {
       Box {
           var clickableText by remember { mutableStateOf("Click me!") }

           Text(
               modifier = Modifier.mouseClickable(
                   onClick = {
                       if (buttons.isPrimaryPressed && keyboardModifiers.isShiftPressed)  {
                           clickableText = "Shift + left-mouse click!"
                       } else {
                           clickableText = "Wrong combination, try again!"
                       }
                   }
               ),
               text = clickableText
           )

       }
   }
}
複製代碼

請注意,這個 API 還不是最終版本,目前正在繼續開發,未來可能會改變它。

統一的圖像資源和 Painter

在進一步穩定 Compose for Desktop 的 API 的過程當中,如今可使用統一的 painterResource,而不是將圖形資源分紅 svgResourceimageResourcevectorXmlResource : 

@Composable
fun ApplicationScope.painterResource() {
   Window(onCloseRequest = ::exitApplication, title = "Image resources") {
       Column {
           Image(
               painter = painterResource("sample.svg"), // Vector
               contentDescription = "Sample",
               modifier = Modifier.fillMaxSize()
           )
           Image(
               painter = painterResource("sample.xml"), // Vector
               contentDescription = "Sample",
               modifier = Modifier.fillMaxSize()
           )
           Image(
               painter = painterResource("sample.png"), // ImageBitmap
               contentDescription = "Sample",
               modifier = Modifier.fillMaxSize()
           )
       }
   }
}
複製代碼

咱們還將 window icon 屬性從 java.awt.Image 更改成androidx.compose.ui.graphics.painter.Painter,所以除了將來的光柵圖形以外,還可使用基於矢量的圖標:

fun vectorWindowIcon() {
   application {
       var icon = painterResource("sample.svg") //vector icon
       Window(onCloseRequest = ::exitApplication, icon = icon) {
           Text("Hello world!")
       }
   }
}
複製代碼

支持 ARM64 上的 Linux

在此版本中,除了現有的 x86-64 支持以外,Compose for Desktop 還增長了對運行在基於 ARM64 處理器的設備上的 Linux 的支持。

總的來講,如今可使用 Compose for Desktop 爲如下平臺編寫 UI:

  • x64 和 arm64 上的 macOS
  • x64 和 arm64 上的 Linux
  • x64 上的 Windows

Compose for Web 的新增功能

除了 Compose for Desktop,Compose for Web 也已升級爲 Alpha 版本,二者都已經調整了版本控制方案和發佈週期,並經過他們的 DSL 擴展了可用的功能,用於樣式和事件管理。

擴展的 CSS API

咱們將繼續改進和完善 API,以經過 CSS 指定樣式規則,這個最新版本在類型安全的 DSL 中增長了對算術運算、設置屬性和動畫的更好支持。

CSS 單元的算術運算

如今能夠對 CSS 數值執行任意操做,若是對相同單位的兩個值使用運算,將得到相同單位的新值,以下例所示:

val a = 5.px
val b = 20.px
borderBottom(a + b) // 25px
複製代碼

用於設置屬性的 CSS API

擴展了對全部最經常使用的 CSS 屬性的類型安全訪問,並涵蓋了大部分的現代瀏覽器支持的全部 CSS 屬性。

這意味着在大多數狀況下可以直接從類型安全的 API 中得到支持,而對於更奇特的屬性,或尚不支持的屬性,還能夠經過property直接獲取鍵和值的函數進行賦值:

borderWidth(topLeft = 4.px, bottomRight = 10%) // type-safe access!

property("some-exotic-property", "hello-friend") // raw property assignment
複製代碼

動畫API

爲了使基於 Compose 的用戶界面更加動態,如今提供了從類型安全的 DSL 中建立 CSS 動畫的選項:

object AppStyleSheet : StyleSheet() {
   val bounce by keyframes {
       from {
           property("transform", "translateX(50%)")
       }

       to {
           property("transform", "translateX(-50%)")
       }
   }

   val myClass by style {
       animation(bounce) {
           duration(2.s)
           timingFunction(AnimationTimingFunction.EaseIn)
           direction(AnimationDirection.Alternate)
       }
   }
}
複製代碼

若是想本身更多地探索這些 API,請務必查看咱們新添加的示例,這些示例展現了一些更高級的 CSS 動畫和 DOM 操做功能。

事件層次結構、事件偵聽器和新的輸入類型

處理事件,尤爲是由輸入組件發出的事件,是對 Compose 應用程序中的更改作出反應的關鍵部分之一。

在此版本中簡化了對事件屬性的訪問,使其更容易定義事件偵聽器,並提供了不一樣的輸入類型。

事件類型層次結構

之前大多數基於事件的 API 要求直接使用nativeEvent eventTarget  以訪問感興趣的事件的值。

今後版本的 Compose for Web 開始,您如今能夠訪問 a SyntheticEvent,其子類型使其更容易訪問所發出事件的相關屬性。

  • SyntheticMouseEvent 公開座標;
  • SyntheticInputEvent公開文本值;
  • SyntheticKeyEvent公開 click 鍵

舉幾個例子:

Div(attrs = {
   onClick { event -> // SyntheticMouseEvent
       val x = event.x
       val y = event.y
   }
})
複製代碼

這些新事件類型旨在直接提供對 在 Native 事件中可用 相同的屬性的訪問,而無需訪問 nativeEvent 或直接事件的目標。

輸入

在常規 HTML 中,不一樣的輸入類型,從文本字段到複選框都共享同一個標籤——輸入。

爲了更輕鬆地在 Kotlin DSL 中使用這些不一樣的輸入類型並提供更多相關提示,這裏引入了許多用於建立不一樣類型輸入的附加函數:

TextInput(value = "text", attrs = {
   onInput { } // all these components have attrs same as HTMLInputElement
})
CheckboxInput(checked = false)
RadioInput(checked = false)
NumberInput(value = 0, min = 0, max = 10)
DateInput(value = 2021-10-10") TelInput(value = "0123456") EmailInput() // and other input types 複製代碼

事件監聽器

進一步統一了用於監聽不一樣輸入類型事件的函數。

輸入偵聽器的輸入類型特定函數 onCheckBoxInput 已被刪除,如今能夠直接使用 onInputonChange ,這意味着再也不須要搜索正確命名的回調:

Input(type = InputType.Text, attrs = {
   onInput { event ->
       val inputValue: String = event.value
   }
})

Input(type = InputType.Checkbox, attrs = {
   onInput { event ->
       val isChecked: Boolean = event.value
   }
})
複製代碼

試用 Compose Multiplatform Alpha!

不管是 Web、桌面、Android 仍是這三者,咱們都但願你能嘗試一下 Compose Multiplatform!

咱們預計 Compose Multiplatform 1.0(咱們的第一個穩定版本)將於今年晚些時候發佈,所以如今是嘗試爲您的生產應用評估 Compose Multiplatform 的理想時機。

這裏有有許多可用資源:

預發佈說明

Compose Multiplatform 目前處於 Alpha 階段 ,雖然大多數 API 如今已經很是相似於它們的穩定形狀,但請記住仍可能會更改某些 API,以確保最終版本提供儘量最佳的開發體驗。

隨着接近穩定版本,咱們將繼續依靠用戶的反饋來幫助實現這一目標!

相關文章
相關標籤/搜索