支持 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,以确保最终版本提供尽量最佳的开发体验。

随着接近稳定版本,咱们将继续依靠用户的反馈来帮助实现这一目标!

相关文章
相关标签/搜索