Redactar multiplataforma 1.5.0 lanzado

Compose Multiplatform 1.5.0 ya está disponible oficialmente. Toma el marco de interfaz de usuario declarativo Jetpack Compose para Kotlin y lo extiende desde Android al escritorio, iOS y la web. La versión de escritorio es estable, iOS está en Alpha y el soporte web aún es experimental. Para obtener instrucciones completas, consulte  el sitio web de Compose Multiplatform .

Algunos aspectos destacados de esta versión incluyen:

  1. Las API Dialog, Popup y WindowInsets ahora usan código común.

  2. Para el desplazamiento de iOS, se han mejorado la gestión de recursos y los campos de texto.

  3. El marco de prueba de la interfaz de usuario se ha estabilizado en el escritorio.

Esta versión se basa en  Jetpack Compose 1.5 y se centra en mejoras de rendimiento. Al mismo tiempo, se  basa en la versión 1.1 de Material Design 3  , incluidos nuevos componentes como el selector de fecha y el selector de hora.

Pruebe Compose Multiplataforma 1.5.0:

https://github.com/JetBrains/compose-multiplatform/releases/tag/v1.5.0 


Redactar multiplataforma 

Diálogo de soporte, ventanas emergentes y ventanas

A partir de la versión 1.5, los cuadros de diálogo y las ventanas emergentes están disponibles en Compose Multiplatform. Los cuadros de diálogo se utilizan para eventos modales donde el usuario realiza selecciones o ingresa datos. Mientras tanto, las ventanas emergentes se utilizan para comportamientos no modales, como proporcionar funcionalidad opcional.

En esta versión, los tipos base  Dialog  y  Popup , así como  DropdownMenu  y  AlertDialog  son accesibles desde código universal. Esto evita la necesidad de proporcionar funcionalidades específicas de la plataforma.

Por ejemplo, el siguiente elemento componible está escrito completamente en código genérico:

@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") },
       )
   }
}

Cómo aparece en escritorio, Android e iOS:

Demostración del cuadro de diálogo de escritorio

Demostración de diálogo de Android e iOS

La tercera característica disponible en esta versión es  la API WindowInsets , que describe cuánto ajuste se necesita para evitar que el contenido se superponga a la interfaz de usuario del sistema. A partir de la versión 1.5, esta función está incluida en Compose Multiplatform y, por lo tanto, está disponible en Android e iOS.

Usando la API WindowInsets, el contenido de fondo se puede dibujar detrás de la muesca a través de Compose Multiplatform. No es necesario agregar una línea blanca en la parte superior de la aplicación. La diferencia se muestra en la siguiente captura de pantalla:

Dibuje contenido de fondo en Compose Multiplatform usando la API WindowInsets

Mejoras en iOS

La plataforma iOS es el foco de esta versión e incluye una serie de mejoras. El desplazamiento imita la apariencia de la plataforma, la administración de recursos se simplifica y se mejora el manejo de texto.

desplazamiento natural

En esta versión, el desplazamiento de iOS se ajustó para imitar el desplazamiento nativo. Supongamos que la cantidad y/o el tamaño de los elementos que se mostrarán en su código excede el espacio disponible:

@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)
           )
       }
   }
}

Al desplazarse, los elementos aparecerán en los bordes de la pantalla, al igual que la aplicación nativa de iPhone:

Desplázate para que aparezca una ventana emergente en iOS

Soporte para fuentes dinámicas

Función de fuentes dinámicas en iOSPermita a los usuarios establecer tamaños de fuente preferidos: fuentes más grandes para una visualización más fácil, fuentes más pequeñas para más contenido. El tamaño del texto utilizado en su aplicación debe estar relacionado con esta configuración del sistema.

Compose Multiplatform ahora admite esta función. El incremento utilizado al escalar el texto es el mismo que se utiliza en las aplicaciones nativas, por lo que el comportamiento será el mismo.

Tome los siguientes elementos componibles como ejemplo:

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

Pantalla con tamaño de lectura preferido establecido al mínimo:

Funcionalidad de fuente dinámica (texto pequeño) en iOS en Compose Multiplatform

Este es el resultado cuando el tamaño de lectura preferido es máximo:

Funcionalidad de fuente dinámica (texto grande) en iOS en Compose Multiplatform

Soporte para pantallas de alta frecuencia de actualización

En versiones anteriores, la velocidad de fotogramas máxima era de 60 FPS. Esto puede hacer que la interfaz de usuario sea lenta y retrasada en dispositivos con pantallas de 120 Hz. A partir de esta versión, las velocidades de fotogramas admitidas son de hasta 120 FPS.

Gestión de recursos simplificada

A partir de 1.5.0, todos los recursos de la carpeta de recursos de un conjunto de fuentes de iOS se copian en el paquete de aplicaciones de forma predeterminada. Por ejemplo, si coloca un archivo de imagen en  src/commonMain/resources/, se copiará en el paquete y estará disponible desde el código.

Cuando usa CocoaPods, ya no necesita configurar este comportamiento en el archivo de compilación de Gradle. Tampoco es necesario volver a llamar  podInstall  para asegurarse de que el recurso se copie después de la modificación.

A partir de esta versión, si intenta configurar el comportamiento explícitamente en el script de compilación (como se muestra a continuación), recibirá el error:

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

Para obtener detalles completos y orientación sobre cómo migrar el código existente, consulte este documento  .

Campo de texto mejorado

En versiones anteriores, ingresar texto podía provocar un comportamiento inesperado en dos situaciones. A partir de esta versión,  TextField se han realizado mejoras para superar estos problemas.

Problemas del caso

En primer lugar, TextField ahora se reconoce si la utilización automática de mayúsculas en las primeras letras está desactivada. Esto es especialmente importante al ingresar contraseñas. Puede controlar este comportamiento a través del argumento KeyboardOptions.

Para ilustrar esto, mire los elementos componibles a continuación:

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

La imagen de la izquierda muestra lo que sucede cuando el atributo en mayúsculas se establece en  KeyboardCapitalization.None , y la imagen de la derecha muestra  KeyboardCapitalization.Sentences lo que sucede cuando el valor es .

Demostración del caso TextField

teclado físico

El segundo caso está relacionado con el teclado de hardware. En versiones anteriores, al usar un teclado de hardware, presionar  Enter  provocaría múltiples saltos de línea y presionar  Retroceso  provocaría múltiples eliminaciones. A partir de esta versión, estos eventos se manejan correctamente. 


Mejoras de escritorio

Estabilizó el marco de pruebas.

Esta versión estabiliza la compatibilidad con las pruebas de Compose for Desktop. Jetpack Compose proporciona un conjunto de API de prueba  para verificar el comportamiento del código Compose. Estas API se trasladaron anteriormente al escritorio y estaban disponibles en versiones anteriores con limitaciones. Estas limitaciones ahora se han eliminado, lo que le permite escribir pruebas de IU integrales para su aplicación.

Para demostrar rápidamente las capacidades de prueba, creemos y probemos una interfaz de usuario simple. A continuación se muestra nuestro ejemplo componible:

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


   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")
               )
           }
       }
   }
}

Esto crea una interfaz de usuario simple que registra los intentos de búsqueda:

Aplicación de búsqueda para pruebas

Tenga en cuenta que Modifier.testTag se ha utilizado para dar nombres a las entradas en  TextField, Button y  LazyColumn .

Luego podemos manipular la UI en una prueba JUnit:

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))
   }
}

使用特定于 Compose 的 JUnit 规则:

  1. 将 UI 的内容设置为应用可组合项。

  2. 通过 onNodeWithTag 查找文本字段和按钮。

  3. 在文本字段中重复输入示例值,然后点击按钮。

  4. 通过 onAllNodesWithTag 查找生成的所有文本节点。

  5. 断言当前已创建的文本节点数,并获取最后一个。

  6. 断言最后一次尝试包含预期消息。

增强了 Swing 互操作性

此版本对 Swing 组件内 Compose 面板的改进呈现引入了实验性支持。这可以防止在显示、隐藏或调整面板大小时出现过渡呈现问题。它还支持在组合 Swing 组件和 Compose 面板时进行适当分层。Swing 组件现在可以在 ComposePanel 上方或下方显示。

为了说明这一点,请查看下面的示例:

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(600600)
           isVisible = true
       }
   }
}

在这段代码中,我们创建并显示一个 Swing JFrame,内容如下:

  1. JFrame 包含带有垂直分隔线的 JSplitPane

  2. 拆分窗格的左侧是青色的标准 JPanel

  3. 右侧是 JLayeredPane,由两层组成:

    • 包含 Box 可组合项的 ComposePanel,颜色为黑色

    • 自定义 Swing 组件,其中文本“Popup”出现在白色矩形内。这通过重写 paintComponent 方法实现。

属性 compose.swing.render.on.graphics 设为 true 时:

  • 自定义 Swing 组件显示在 Box 可组合项顶部。

  • 移动滑块时不会出现过渡图形伪影。

Swing 互操作性演示正常运行

如果此标志未设置,则自定义组件将不可见,并且滑块移动时可能出现过渡伪影:

Swing 互操作性演示非正常运行

请分享您对 Compose Multiplatform 的反馈。我们邀请您加入 Kotlin Slack #compose 频道,讨论与 Compose Multiplatform 和 Jetpack Compose 相关的一般主题。在 #compose-ios 中,您可以找到有关 Compose Multiplatform for iOS 的讨论。

试用 Compose Multiplatform 1.5.0:

https://github.com/JetBrains/compose-multiplatform/releases/tag/v1.5.0


更多文章和视频


本博文英文原作者:

Kotlin 技术布道师 

Garth Gilmour

这就是 Kotlin 编程语言

简洁、跨平台、且有趣!


本文分享自微信公众号 - JetBrains(JetBrainsChina)。
如有侵权,请联系 [email protected] 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

阿里云严重故障,全线产品受影响(已恢复) 俄罗斯操作系统 Aurora OS 5.0 全新 UI 亮相 汤不热 (Tumblr) 凉了 多家互联网公司急招鸿蒙程序员 .NET 8 正式 GA,最新 LTS 版本 UNIX 时间即将进入 17 亿纪元(已进入) 小米官宣 Xiaomi Vela 全面开源,底层内核为 NuttX Linux 上的 .NET 8 独立体积减少 50% FFmpeg 6.1 "Heaviside" 发布 微软推出全新“Windows App”
{{o.name}}
{{m.name}}

Supongo que te gusta

Origin my.oschina.net/u/5494143/blog/10110602
Recomendado
Clasificación