原文連接: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 的路徑,並分享了更多聲明式多平臺用戶界面的信息!安全
Jetpack Compose 是一個爲 Android 構建原生用戶界面的響應式開發 UI 框架,JetBrains 在 Google 的 Jetpack Compose 的基礎上將 Compose 框架拓展到更多新的平臺。服務器
藉助 Compose Multiplatform,開發者可使用和 Android Jetpack Compose 相同的 API 開發 Desktop 和 Web 構建用戶界面。
使用 Kotlin Multiplatform 提供的機制,如今能夠針對同一項目中的如下任意組合:
之前 Compose for Desktop 和 Compose for Web 使用不一樣的 artifacts ,而如今開始它們將統一在一個 Gradle 插件和組件下,這意味着基於 Compose 開發 Android、Desktop 和 Web 用戶界面會更容易。
憑藉 Alpha 版本的更新,Compose Multiplatform 提供的 API 已經很接近其最終形態,咱們將全力投入 Compose 的開發支持,並指望在 2021 年內能達到 1.0 版本,更多詳細信息:瞭解有關 COMPOSE 多平臺的更多信息
在 JetBrains 如今一些生產應用已經開始採用 Compose,首先是 JetBrains Toolbox App,它是 JetBrains IDE 的管理應用程序,每個月活躍用戶超過 800,000。
在它們的最新版本中,該團隊已將應用程序的實現徹底轉換爲 Compose for Desktop,在從基於 Electron 的 UI 遷移期間,團隊注意到了 Compose 的許多優點:
JetBrains Toolbox 團隊負責人 Victor Kropp 也在帖子中分享了他對 Compose for Desktop 的見解:
Compose for Desktop 雖然仍處於早期階段,但已被證明了 Toolbox App 的絕佳選擇。在開發框架同事的支持下,幾乎能夠在短期內重寫整個 UI。這使咱們可以統一開發體驗,所以從業務邏輯到 UI,從應用到服務器,Toolbox 如今 100% 是 Kotlin。
在此版本中還發布了一個新的 IDE 插件來支持開發工做:用於 IntelliJ IDEA 和 Android Studio 的 Compose Multiplatform 插件,它與框架的新版本一塊兒發佈,並提供額外的功能來幫助用戶界面的開發工做。
第一個版本包括了一項期待已久的功能:可以直接在 IDE 中預覽 Compose for Desktop 和 Android 組件,甚至無需啓動應用程序。
要顯示@Composable
不帶參數的函數預覽,能夠將@Preview
註釋添加到其定義中,這時候會添加一個小的裝訂線圖標,可使用它來切換組件的預覽窗格:
這個新的預覽版能夠幫助開發者縮短開發週期,並更輕鬆地將想法轉化爲基於 Compose 的真實設計和佈局。
要查找並安裝新插件,請在插件市場中搜索「Compose Multiplatform IDE Support」,或點擊下方直接打開插件頁面:安裝 COMPOSE 多平臺插件
除了將 Compose for Desktop 升級爲 Alpha 的一大步以外,在此版本中還改進了其 API 並增長了對新平臺的支持。
在里程碑4桌面版中,咱們推出了一個實驗組API:Window
,MenuBar
和Tray
,這些新 API 都使用 @Composable
與應用程序中的其餘組件相同的狀態管理、行爲和條件呈現概念。
在此版本中,這些可組合版本如今是管理窗口、菜單欄和托盤圖標的默認方式,取代了舊的窗口 API。
若是尚未嘗試過這些新 API,或者只是想了解有關它們提供的行爲和功能的更多信息,能夠參考更新的 Compose for Desktop 教程,瞭解窗口和托盤管理。
有時咱們想將某些內容做爲一個總體顯示,而在不事先知道將顯示的內容的狀況下,這意味着咱們不知道它的最佳窗口尺寸。
爲了更輕鬆地開發這些 UI 場景,咱們引入了自適應窗口大小功能,經過將窗口的一個或兩個維度設置WindowSize
爲 Dp.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") }
)
}
}
}
複製代碼
在此版本的 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 還不是最終版本,目前正在繼續開發,未來可能會改變它。
在進一步穩定 Compose for Desktop 的 API 的過程當中,如今可使用統一的 painterResource
,而不是將圖形資源分紅 svgResource
、 imageResource
、vectorXmlResource
:
@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!")
}
}
}
複製代碼
在此版本中,除了現有的 x86-64 支持以外,Compose for Desktop 還增長了對運行在基於 ARM64 處理器的設備上的 Linux 的支持。
總的來講,如今可使用 Compose for Desktop 爲如下平臺編寫 UI:
除了 Compose for Desktop,Compose for Web 也已升級爲 Alpha 版本,二者都已經調整了版本控制方案和發佈週期,並經過他們的 DSL 擴展了可用的功能,用於樣式和事件管理。
咱們將繼續改進和完善 API,以經過 CSS 指定樣式規則,這個最新版本在類型安全的 DSL 中增長了對算術運算、設置屬性和動畫的更好支持。
如今能夠對 CSS 數值執行任意操做,若是對相同單位的兩個值使用運算,將得到相同單位的新值,以下例所示:
val a = 5.px
val b = 20.px
borderBottom(a + b) // 25px
複製代碼
擴展了對全部最經常使用的 CSS 屬性的類型安全訪問,並涵蓋了大部分的現代瀏覽器支持的全部 CSS 屬性。
這意味着在大多數狀況下可以直接從類型安全的 API 中得到支持,而對於更奇特的屬性,或尚不支持的屬性,還能夠經過property
直接獲取鍵和值的函數進行賦值:
borderWidth(topLeft = 4.px, bottomRight = 10%) // type-safe access!
property("some-exotic-property", "hello-friend") // raw property assignment
複製代碼
爲了使基於 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
已被刪除,如今能夠直接使用 onInput
或onChange
,這意味着再也不須要搜索正確命名的回調:
Input(type = InputType.Text, attrs = {
onInput { event ->
val inputValue: String = event.value
}
})
Input(type = InputType.Checkbox, attrs = {
onInput { event ->
val isChecked: Boolean = event.value
}
})
複製代碼
不管是 Web、桌面、Android 仍是這三者,咱們都但願你能嘗試一下 Compose Multiplatform!
咱們預計 Compose Multiplatform 1.0(咱們的第一個穩定版本)將於今年晚些時候發佈,所以如今是嘗試爲您的生產應用評估 Compose Multiplatform 的理想時機。
這裏有有許多可用資源:
對於桌面應用程序,能夠在Compose for Desktop 教程 中找到有關如何開始使用的最新信息。
對於瀏覽器應用程序,Compose for Web 教程將幫助啓動和運行。
示例應用程序展現包括要研究的其餘示例,包括 Web、桌面和多平臺應用程序。
Compose Multiplatform 目前處於 Alpha 階段 ,雖然大多數 API 如今已經很是相似於它們的穩定形狀,但請記住仍可能會更改某些 API,以確保最終版本提供儘量最佳的開發體驗。
隨着接近穩定版本,咱們將繼續依靠用戶的反饋來幫助實現這一目標!