IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Vous êtes nouveau sur Developpez.com ? Créez votre compte ou connectez-vous afin de pouvoir participer !

Vous devez avoir un compte Developpez.com et être connecté pour pouvoir participer aux discussions.

Vous n'avez pas encore de compte Developpez.com ? Créez-en un en quelques instants, c'est entièrement gratuit !

Si vous disposez déjà d'un compte et qu'il est bien activé, connectez-vous à l'aide du formulaire ci-dessous.

Identifiez-vous
Identifiant
Mot de passe
Mot de passe oublié ?
Créer un compte

L'inscription est gratuite et ne vous prendra que quelques instants !

Je m'inscris !

Compose Multiplatform : la version 1.5.0 du framework d'interface utilisateur déclaratif multiplateforme pour Kotlin disponible

Le , par Michael Guilloux

28PARTAGES

5  0 
JetBrains annonce la disponibilité de la version de 1.5.0 de Compose Multiplatform, son framework d'interface utilisateur déclaratif multiplateforme pour Kotlin. Compose Multiplatform prend le framework d'interface utilisateur déclaratif Jetpack Compose pour Kotlin et l'étend au-delà d'Android pour le développement desktop, iOS et web. La version desktop est stable, la version iOS est en phase Alpha et le support du web est expérimental.

Voici les principaux points forts de cette version :

  • Les API Dialog, Popup et WindowInsets sont désormais dans le code commun.
  • Sur iOS, le défilement, la gestion des ressources et les champs de texte ont été améliorés.
  • Le framework de test d'interface utilisateur est satble sur desktop.

Cette version est basée sur Jetpack Compose 1.5, qui met l'accent sur les améliorations de performance. Elle s'appuie également sur la version 1.1 de Material Design 3, ce qui inclut de nouveaux composants tels que les sélecteurs de date et d'heure.

Compose Multiplatform prend en charge les boîtes de dialogue, les popups et les WindowInsets

À partir de la version 1.5, les boîtes de dialogue et les popups sont disponibles dans Compose Multiplatform. Les boîtes de dialogue sont utilisées pour les événements modaux, où l'utilisateur fait un choix ou saisit des données. Les popups, quant à eux, sont destinés aux comportements non modaux, tels que l'offre de fonctionnalités optionnelles.

Dans cette version, les types de base Dialog et Popup, ainsi que DropdownMenu et AlertDialog, sont accessibles à partir du code commun. Cela évite la nécessité de fournir une fonctionnalité spécifique à la plateforme.

Par exemple, le Composable ci-dessous est écrit entièrement dans le code commun :

Code kotlin : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
  
@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") }, 
       ) 
   } 
}


Voici comment il apparaîtra sur desktop, Android et iOS :




Une troisième fonctionnalité, disponible dans cette version, est l'API WindowInsets, qui décrit combien d'ajustements sont requis pour éviter que votre contenu ne chevauche l'interface utilisateur du système. À partir de la version 1.5, cette fonctionnalité est incluse dans Compose Multiplatform et peut donc être utilisée à la fois sur Android et iOS.

En utilisant l'API WindowInsets, vous pouvez dessiner du contenu d'arrière-plan via Compose Multiplatform derrière l'encoche. Cela se fait sans ajouter de ligne blanche en haut de l'application. Les captures d'écran ci-dessous illustrent la différence que cela fait :


Améliorations sur iOS

La plateforme iOS était au centre de cette version et comprend une grande variété d'améliorations. Le défilement imite l'apparence et la convivialité de la plateforme, la gestion des ressources a été simplifiée et la manipulation du texte est améliorée.

Défilement naturel

Dans cette version, le défilement sur iOS est adapté pour imiter le défilement natif. Disons que nous avons du code où le nombre et/ou la taille des éléments à afficher dépassent l'espace disponible :

Code kotlin : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
  
@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) 
           ) 
       } 
   } 
}


Lors du défilement, les éléments surgissent des bords de l'écran, comme dans les applications iPhone natives :


Prise en charge de Dynamic Type

La fonctionnalité Dynamic Type sur iOS permet à un utilisateur de définir la taille de police préférée - plus grande pour une visualisation plus facile ou plus petite pour s'adapter à plus de contenu. La taille de la police utilisée dans une application doit être relative à ce paramètre système.

Cette fonctionnalité est désormais prise en charge dans Compose Multiplatform. Les incréments utilisés pour mettre à l'échelle le texte sont les mêmes que ceux utilisés dans les applications natives, donc le comportement sera identique.

Par exemple, étant donné le Composable suivant :

Code kotlin : Sélectionner tout
1
2
3
4
5
  
@Composable 
fun DynamicType() { 
   Text("This is some sample text", fontSize = 30.sp) 
}


Voici ce qui sera affiché lorsque la taille de lecture préférée est réglée sur le minimum :


Alors que voici le résultat lorsque la taille de lecture préférée est au maximum :


Prise en charge des écrans à taux de rafraîchissement élevé

Dans les versions précédentes, le taux d'images maximum était de 60 images par seconde. Cela pouvait rendre l'interface utilisateur lente et saccadée sur les appareils avec des écrans 120 Hz. À partir de cette version, les taux de trame allant jusqu'à 120 images par seconde sont pris en charge.

Simplification de la gestion des ressources

À partir de la version 1.5.0, les ressources situées dans le dossier de ressources d'un ensemble de sources iOS sont copiées dans le bundle de l'application par défaut. Ainsi, par exemple, si vous placez un fichier image dans src/commonMain/resources/, il sera copié dans le bundle et sera utilisable à partir de votre code.

Si vous utilisez CocoaPods, vous n'avez plus besoin de configurer ce comportement dans le fichier de build Gradle. Vous n'avez également plus besoin de réinvoquer podInstall pour vous assurer que les ressources sont copiées après modification.

À partir de cette version, si vous essayez de configurer explicitement le comportement dans les scripts de build (comme indiqué ci-dessous), vous recevrez une erreur :

Code kotlin : Sélectionner tout
1
2
3
4
5
6
  
kotlin { 
    cocoapods { 
        extraSpecAttributes["resources"] = "..." 
    } 
}


Amélioration de TextField

Dans les versions précédentes, il y avait deux situations où la saisie de texte pouvait entraîner un comportement indésirable. À partir de cette version, TextField a été amélioré pour surmonter ces problèmes.

Problèmes de capitalisation

Tout d'abord, TextField reconnaît désormais lorsque la capitalisation automatique de la première lettre a été désactivée. C'est important, par exemple, lors de la saisie de mots de passe. Vous contrôlez ce comportement via l'argument keyboardOptions.

Pour illustrer cela, examinez le Composable ci-dessous :

Code kotlin : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
  
fun TextFieldCapitalization() { 
   var text by remember { mutableStateOf("") } 
   TextField( 
       value = text, 
       onValueChange = { text = it }, 
       keyboardOptions = KeyboardOptions( 
           capitalization = KeyboardCapitalization.Sentences, 
           autoCorrect = false, 
           keyboardType = KeyboardType.Ascii, 
       ), 
   ) 
}


L'image de gauche montre ce qui se passe lorsque la propriété de capitalisation est définie sur KeyboardCapitalization.None, tandis que l'image de droite montre ce qui se passe lorsque la valeur est KeyboardCapitalization.Sentences.


Claviers physiques

La deuxième situation concerne les claviers physiques. Dans les versions précédentes, lors de l'utilisation d'un clavier physique, appuyer sur Entrée entraînait l'ajout de plusieurs nouvelles lignes, et appuyer sur Retour déclenchait plusieurs suppressions. À partir de cette version, ces événements sont désormais traités correctement.

Améliorations sur desktop

Framework de test stabilisé

Cette version stabilise la prise en charge des tests sur Compose pour desktop. Jetpack Compose fournit un ensemble d'API de test pour vérifier le comportement de votre code Compose. Ces API ont été portées sur desktop et étaient disponibles dans les versions précédentes, mais avec des limitations. Ces limitations ont maintenant été levées, ce qui permet d'écrire des tests d'interface utilisateur complets pour votre application.

Afin de fournir un aperçu de la fonctionnalité de test, créons et testons une interface utilisateur simple. Voici notre Composable d'exemple :

Code kotlin : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
  
@Composable 
fun App() { 
   var searchText by remember { mutableStateOf("cats") } 
   val searchHistory = remember { mutableStateListOf<String>() } 
  
  
   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") 
               ) 
           } 
       } 
   } 
}


Cela crée une interface utilisateur simple qui enregistre les tentatives de recherche :


Remarquez que Modifier.testTag a été utilisé pour attribuer des noms à TextField, Button et aux éléments de LazyColumn.

Nous pouvons ensuite manipuler l'interface utilisateur dans un test JUnit :

Code kotlin : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
  
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)) 
   } 
}


En utilisant la règle JUnit spécifique à Compose, on peut :

  • définir le contenu de l'interface utilisateur en tant qu'App Composable ;
  • localiser le champ de texte et le bouton via onNodeWithTag ;
  • entrer à plusieurs reprises des valeurs d'exemple dans le champ de texte et cliquer sur le bouton ;
  • trouver tous les nœuds de texte qui ont été générés via onAllNodesWithTag ;
  • vérifier que le nombre actuel de nœuds de texte a été créé, et récupérer le dernier ;
  • vérifier que cette dernière tentative contient le message attendu.

Interopérabilité Swing améliorée

Cette version introduit une prise en charge expérimentale pour le rendu amélioré des panneaux Compose à l'intérieur des composants Swing. Cela évite les problèmes de rendu de transition lorsque les panneaux sont affichés, masqués ou redimensionnés. Cela permet également un superposition correcte lors de la combinaison de composants Swing et de panneaux Compose. Un composant Swing peut désormais être affiché au-dessus ou en dessous d'un ComposePanel.

Pour illustrer cela, examinez l'exemple ci-dessous :

Code kotlin : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
  
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(600, 600) 
           isVisible = true 
       } 
   } 
}


Ce code crée et affiche une JFrame Swing, avec le contenu suivant :

  • La JFrame contient un JSplitPane avec un séparateur vertical.
  • À gauche du split pane se trouve un JPanel standard, de couleur cyan.
  • À droite se trouve un JLayeredPane, composé de deux couches :
    • Un ComposePanel contenant un composable Box, de couleur noire.
    • Un composant Swing personnalisé, où le texte "Popup" apparaît à l'intérieur d'un rectangle blanc. Cela est réalisé en remplaçant la méthode paintComponent.


Lorsque la propriété compose.swing.render.on.graphics est définie sur true, alors :

  • Le composant Swing personnalisé est affiché au-dessus du Composable Box.
  • Il n'y a pas d'artefacts graphiques de transition lorsque le curseur est déplacé.


Si ce flag n'avait pas été défini, le composant personnalisé ne serait pas visible, et il pourrait y avoir des artefacts de transition lorsque le curseur était déplacé :



Voici présentées les nouevautés et améliorations introduites dans Compose Multiplatform 1.5.0. Utilisez les liens ci-dessous pour essayer la nouvelle version ou démarrer avec le framework d'interface utilisateur déclaratif multiplateforme pour Kotlin.

Essayer Compose Multiplatform 1.5.0
Découvrir les modèles Android et iOS sur GitHub

Une erreur dans cette actualité ? Signalez-nous-la !