Quand on crée un nouveau projet Jetpack Compose avec Android Studio , on obtient un ensemble de fichiers avec une arborescence spécifique. Pour l'instant le seul fichier qui nous intéresse est le fichier MainActivity
package com.example.test01
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import com.example.test01.ui.theme.Test01Theme
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Test01Theme {
// A surface container using the 'background' color from the theme
Surface(
color = MaterialTheme.colorScheme.background
modifier = Modifier.fillMaxSize(),
) {
Greeting("Android")
}
}
}
}
}
@Composable
fun Greeting(name: String, modifier: Modifier = Modifier) {
Text(
text = "Hello $name!",
modifier = modifier
)
}
@Preview(showBackground = true)
@Composable
fun GreetingPreview() {
Test01Theme {
Greeting("Android")
}
}
Dans notre exemple, l'élément Surface( ) { } est caractérisé par deux propriétés:
En fait, l'élément le plus important du fichier MainActivity est la fonction setContent {}. C'est dans cette fonction qu'il faut placer tout le contenu de l'application
Si on veut un "Hello World!" très basique, On peut se passer des propriétés par défaut du thème ainsi que de l'élément Surface(). On peut aussi placer l'élément Text() directement dans le bloc setContent{}
package com.example.hellobasic
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.material3.Text
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
Text( text = "Hello World!" )
}
}
}
Il me semble que les éléments les plus importants pour la mise en Page d'une Interface utilisateur (UI) sont les composables Column(){} et Row(){} qui permettent d'organiser les éléments composables soit en colonne soit en ligne.
On peut obtenir des mises en page assez élaborées en plaçant des lignes dans des colonnes et des colonnes dans des lignes.
package com.example.columns
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyApp()
}
}
}
@Composable
fun MyApp() {
Column( //Conteneur principal,
verticalArrangement = Arrangement.spacedBy(10.dp),
modifier = Modifier.fillMaxSize()
) {
Row( // moitié haute de l'écran
horizontalArrangement = Arrangement.spacedBy(10.dp),
modifier = Modifier
.fillMaxWidth()
.weight(1f)
)
{
Column(
verticalArrangement = Arrangement.Top,
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.fillMaxHeight()
.weight(1f)
.background(Color.Cyan)
) {
Txt(" Top ")
Txt(" Top ")
Txt(" Top ")
}
Column(
verticalArrangement = Arrangement.spacedBy(20.dp),
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.fillMaxHeight()
.weight(1f)
.background(Color.Cyan)
) {
Txt("spacedBy")
Txt("spacedBy")
Txt("spacedBy")
}
Column(
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.fillMaxHeight()
.weight(1f)
.background(Color.Cyan)
) {
Txt("Center")
Txt("Center")
Txt("Center")
}
Column(
verticalArrangement = Arrangement.Bottom,
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.fillMaxHeight()
.weight(1f)
.background(Color.Cyan)
) {
Txt("Bottom")
Txt("Bottom")
Txt("Bottom")
}
}
Row( // moitié basse de l'écran
horizontalArrangement = Arrangement.spacedBy(10.dp),
modifier = Modifier
.fillMaxWidth()
.weight(1f)
)
{
Column(
verticalArrangement = Arrangement.SpaceAround,
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.fillMaxHeight()
.weight(1f)
.background(Color.Cyan)
) {
Txt("SpaceAround")
Txt("SpaceAround")
Txt("SpaceAround")
}
Column(
verticalArrangement = Arrangement.SpaceEvenly,
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.fillMaxHeight()
.weight(1f)
.background(Color.Cyan)
) {
Txt("SpaceEvenly")
Txt("SpaceEvenly")
Txt("SpaceEvenly")
}
Column(
verticalArrangement = Arrangement.SpaceBetween,
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.fillMaxHeight()
.weight(1f)
.background(Color.Cyan)
) {
Txt("SpaceBetween")
Txt("SpaceBetween")
Txt("SpaceBetween")
}
}
}
}
@Composable
fun Txt(str: String) {
Text(text = str,
modifier = Modifier
.background(Color.Yellow, shape = RoundedCornerShape(10.dp))
.padding(5.dp)
)
}
Dans la figure ci-dessus:
package com.example.rows
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyApp()
}
}
}
@Composable
fun MyApp() {
Column(verticalArrangement = Arrangement.spacedBy(10.dp),
modifier = Modifier.fillMaxSize())
{
MyRow(Arrangement.Start)
MyRow(Arrangement.Center)
MyRow(Arrangement.End)
MyRow(Arrangement.SpaceAround)
MyRow(Arrangement.SpaceEvenly)
MyRow(Arrangement.SpaceBetween)
Row(horizontalArrangement = Arrangement.spacedBy(20.dp),
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.fillMaxWidth()
.background(Color.Cyan)
.height(70.dp)
)
{
Txt("spacedBy")
Txt("spacedBy")
Txt("spacedBy")
}
}
}
@Composable
fun Txt(str: String){
Text(text = str,
modifier = Modifier
.background(Color.Yellow, shape = RoundedCornerShape(10.dp))
.padding(5.dp)
)
}
@Composable
fun MyRow(arrHor: Arrangement.Horizontal) {
Row(horizontalArrangement = arrHor,
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.fillMaxWidth()
.background(Color.Cyan)
.height(70.dp)
)
{
Txt(arrHor.toString().substringAfter("#"))
Txt(arrHor.toString().substringAfter("#"))
Txt(arrHor.toString().substringAfter("#"))
}
}
Dans la figure ci-dessus:
Si on essaye d'afficher une liste avec un grand nombre d'éléments dans une Column(), on aura un problème car Column() ne permet pas de défilement vertical et il n'y aura que les premiers éléments qui seront visibles
LazyColumn est conçue pour gérer de grandes listes efficacement car elle offre la possibilité de défilement vertical. Son fonctionnement est optimisé car il n'y a que les éléments visibles dans la fenêtre d'affichage qui sont composés graphiquement
Il existe plusieurs façons d'ajouter des éléments dans un LazyColumn :
package com.example.lazycolun
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyApp()
}
}
}
@Composable
fun MyApp() {
val maListe = listOf("Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi", "Dimanche")
LazyColumn(
verticalArrangement = Arrangement.spacedBy(8.dp),
modifier = Modifier
.fillMaxWidth()
.padding(start = 20.dp)
)
{
item {
Text(
text = "En-tête",
fontSize = 30.sp,
modifier = Modifier
.fillMaxWidth()
.background(Color.Cyan)
)
}
item {
Button(onClick = { /*TODO*/ })
{ Text(text = "Bouton A") }
}
item {
Button(onClick = { /*TODO*/ })
{ Text(text = "Bouton B") }
}
item { Spacer(modifier = Modifier.height(20.dp)) }
items(5) { index ->
Text("Élément numéro $index")
}
item { Spacer(modifier = Modifier.height(20.dp)) }
items(maListe) { item ->
Text(text = item)
}
item { Spacer(modifier = Modifier.height(20.dp)) }
itemsIndexed(maListe) { index, item ->
Text(text = "jour $index -> $item")
}
}
}
Cet élément permet de placer un text dans un conteneur
L'apparence du texte dépend d'un certain nombre d'attributs et de modificateurs
Text(
"le texte ici",
attribut1 = valeur,
attribut2 = valeur
…,
modifier = Modifier
.modif1
.modif2
.modif3
…
)
package com.example.text
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.wrapContentHeight
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyApp()
}
}
}
@Composable
fun MyApp() {
Column( horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.fillMaxSize()
.background(Color.Green)) {
Box (
modifier = Modifier
.background(Color.Cyan, shape = RoundedCornerShape(10.dp))
.width(200.dp)
.height(200.dp)
){
Text(
text = "Hello",
fontWeight = FontWeight.Bold,
fontStyle = FontStyle.Italic,
fontSize = 20.sp,
color = Color.Red,
textAlign = TextAlign.Center, // centrer le texte horizontalement
modifier = Modifier
.align(alignment = Alignment.BottomCenter) // position dans le père
.width(100.dp)
.height(100.dp)
.background(Color.Yellow, shape = RoundedCornerShape(5.dp))
.border(width=2.dp, Color.Blue, shape = RoundedCornerShape(5.dp))
.wrapContentHeight(Alignment.CenterVertically) // centrer le texte verticalement
)
}
}
}
Dans cette exemple, on teste quelques composables: Column(), Box() et Text()
Le bouton exécute une action lorsque l'utilisateur clique dessus. L'apparence du bouton dépend d'un certain nombre d'attributs et de modificateurs. Le bouton est un conteneur, on y place généralement du texte et des icônes
Button(
attribut1 = valeur,
attribut2 = valeur,
…,
modifier = Modifier
.modif1
.modif2
.modif3
…
){
Contenu du bouton: Label, icônes ...
}
onClick = {Toast.makeText(context, "Bouton cliqué", Toast.LENGTH_SHORT).show() },
enabled = true,
shape = RoundedCornerShape(10.dp),
border = BorderStroke(2.dp, Color.Blue),
colors = ButtonDefaults.buttonColors(
contentColor = Color.White,
containerColor = Color(0xFF33FFFF)
)
contentPadding = PaddingValues(
start = 20.dp,
top = 12.dp,
end = 20.dp,
bottom = 12.dp
),
Modifier.align(Alignment.Center)
Modifier.width(100.dp)
Modifier.height(100.dp)
Modifier.size(200.dp, 100.dp)
Modifier.padding(16.dp)
Padding de tout les cotés. Le texte
apparaîtra dans
l'espace qui reste après le padding
Modifier.padding(horizontal = 40.dp)
Padding à gauche et à droite
Modifier.padding(vertical = 40.dp)
Padding en haut et en bas
Modifier.padding(start = 40.dp)
Padding gauche
Modifier.padding(start = 40.dp, end = 30.dp, top = 10.dp, bottom = 20.dp)
Padding de chaque coté
Modifier.border(width=2.dp, Color.Blue, shape = RoundedCornerShape(5.dp))
package com.example.button0
import android.os.Bundle
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.CutCornerShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableLongStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyApp()
}
}
}
@Composable
fun MyApp() {
val backColor1 = 0xFFFFE0B2
val backColor2 = 0xFFB2DFDB
val backMask = backColor1 xor backColor2
val butColor1 = 0xFF883333
val butColor2 = 0xFF3399AA
val butMask = butColor1 xor butColor2
var butColor by remember { mutableLongStateOf(butColor1) }
var backColor by remember { mutableLongStateOf(backColor1) }
Column(
verticalArrangement = Arrangement.spacedBy(10.dp),
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier
.fillMaxSize()
.background(Color(backColor))
.padding(10.dp)
)
{
val context = LocalContext.current
Button(onClick = { Toast.makeText(context, "par défaut", Toast.LENGTH_SHORT).show() },
) {
Text(text = "par défaut")
}
Button(onClick = { Toast.makeText(context, "Rectangle", Toast.LENGTH_SHORT).show() },
shape = RectangleShape,
) {
Text(text = "Rectangle")
}
Button(onClick = { Toast.makeText(context, "Circulaire", Toast.LENGTH_SHORT).show() },
shape = CircleShape,
modifier = Modifier
.width(120.dp)
.height(120.dp)
) {
Text(text = "Circulaire")
}
Button(onClick = { Toast.makeText(context, "Coins coupés", Toast.LENGTH_SHORT).show() },
shape = CutCornerShape(5.dp),
) {
Text(text = "Coins coupés")
}
Button(onClick = { Toast.makeText(context, "Arrondi", Toast.LENGTH_SHORT).show() },
shape = RoundedCornerShape(10.dp),
) {
Text(text = "Coins arrondis")
}
OutlinedButton(onClick = { Toast.makeText(context, "Outlined", Toast.LENGTH_SHORT).show() }
) {
Text("Outlined")
}
OutlinedButton(onClick = { Toast.makeText(context, "Outlined épais", Toast.LENGTH_SHORT).show() },
border = BorderStroke(2.dp, Color.Blue),
// colors = ButtonDefaults.buttonColors(containerColor = Color(butColor) )
) {
Text("Outlined épais")
}
Button(
onClick = { backColor = backColor xor backMask },
shape = RoundedCornerShape(10.dp),
modifier = Modifier
.size(140.dp, 60.dp)
) {
Text(
text = "Modifier\ncouleur fond",
textAlign = TextAlign.Center
)
}
Button(
onClick = { butColor = butColor xor butMask },
shape = RoundedCornerShape(10.dp),
colors = ButtonDefaults.buttonColors(
containerColor = Color(butColor),
contentColor = Color.Yellow
),
modifier = Modifier
.width(120.dp)
.height(60.dp)
) {
Text(
text = "Modifier\nma couleur",
textAlign = TextAlign.Center
)
}
TextButton(onClick = {Toast.makeText(context, "TextButton", Toast.LENGTH_SHORT).show()},
border = BorderStroke(width = 1.dp, color = Color.Black),
shape = RoundedCornerShape(10.dp),
colors = ButtonDefaults.textButtonColors(
containerColor = Color.Green.copy(alpha = 0.8f))
)
{
Text(text = "+",
fontSize = 28.sp,
fontWeight = FontWeight.Bold,
)
}
}
}
Box est un conteneur. Les élément contenus (fils) sont placés sur des plans superposés. On s'en sert par exemple s'il faut superposer un texte sur une image.
Un fils peut être positionné sur son plan grâce à ses modificateurs .align() et .offset()
package com.example.boximage
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.size
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyApp()
}
}
}
@Composable
fun MyApp() {
Box(modifier = Modifier
.size(200.dp, 200.dp)
.background(Color.Cyan))
{
Button(onClick = { /*TODO*/ },
modifier = Modifier
.align(Alignment.CenterStart)
.offset(y = -30.dp)
)
{
Text(text = "Button 1")
}
Button(onClick = { /*TODO*/ },
colors = ButtonDefaults.buttonColors(containerColor = Color.Magenta ),
modifier = Modifier
.align(Alignment.Center)
)
{
Text(text = "Button 2")
}
Button(onClick = { /*TODO*/ },
colors = ButtonDefaults.buttonColors(containerColor = Color.Gray ),
modifier = Modifier
.align(Alignment.CenterEnd)
.offset(y = 30.dp)
)
{
Text(text = "Button 3")
}
}
}
Les icônes peuvent être définies de deux manières principales : avec ImageVector et avec painter.
Icon(imageVector = Icons.Default.Call, contentDescription = null)
Dès qu'on a tapé Icons.Default. VScode affiche la liste des icônes disponibles
Icon(painter = painterResource(id = R.drawable.outline_delete_24), contentDescription = null)
Row(horizontalArrangement = Arrangement.SpaceAround,
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.fillMaxWidth()
.height(50.dp)
.background(Color(0xFF33BB88)))
{
Icon(imageVector = Icons.Default.Call, contentDescription = null)
Icon(imageVector = Icons.Default.Call, contentDescription = null, modifier = Modifier.size(48.dp))
Icon(imageVector = Icons.Default.Build, contentDescription = null, tint = Color.Magenta)
Icon(painter = painterResource(id = R.drawable.outline_bluetooth_24), contentDescription = null)
Icon(painter = painterResource(id = R.drawable.outline_download_for_offline_24),
contentDescription = null, tint = Color.Blue)
Icon(painter = painterResource(id = R.drawable.outline_delete_24), contentDescription = null)
}
C'est tout simplement l'utilisation d'une Icône comme un bouton
package com.example.iconbutton
import android.os.Bundle
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Favorite
import androidx.compose.material3.FilledIconButton
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.IconButtonDefaults
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyApp()
}
}
}
@Composable
fun MyApp() {
val context = LocalContext.current
Row(horizontalArrangement = Arrangement.SpaceAround,
modifier = Modifier
.fillMaxWidth()
.height(50.dp)
.background(Color(0xFF43928B))
)
{
IconButton(onClick = { Toast.makeText(context, "IconButton", Toast.LENGTH_SHORT).show() }) {
Icon(imageVector = Icons.Default.Favorite, contentDescription = null)
}
IconButton(
onClick = { Toast.makeText(context, "IconButton", Toast.LENGTH_SHORT).show() },
colors = IconButtonDefaults.filledTonalIconButtonColors(
containerColor = Color(0xFF8BC34A),
contentColor = Color.Red
)
)
{
Icon(imageVector = Icons.Default.Favorite, contentDescription = null)
}
FilledIconButton(onClick = {
Toast.makeText(context, "FilledIconButton", Toast.LENGTH_SHORT).show()
}) {
Icon(imageVector = Icons.Default.Favorite, contentDescription = null)
}
FilledIconButton(
onClick = { Toast.makeText(context, "FilledIconButton", Toast.LENGTH_SHORT).show() },
colors = IconButtonDefaults.filledTonalIconButtonColors(
containerColor = Color(0xFF8BC34A),
contentColor = Color.Red
)
)
{
Icon(imageVector = Icons.Default.Favorite, contentDescription = null)
}
FilledIconButton(
onClick = { Toast.makeText(context, "FilledIconButton", Toast.LENGTH_SHORT).show() },
shape = RoundedCornerShape(12.dp), // Coins arrondis de 12.dp
colors = IconButtonDefaults.filledTonalIconButtonColors(
containerColor = Color(0xFF8BC34A),
contentColor = Color.Red
)
) {
Icon(
imageVector = Icons.Default.Favorite,
contentDescription = "Favorite Icon",
)
}
}
}
Le FloatingActionButton (FAB) est un bouton utilisé pour représenter une action principale ou très importante dans une interface utilisateur. Il s'agit d'un bouton qui "flotte" au-dessus du reste du contenu de l'interface, avec une icône à l'intérieur.
En réalité, le FAB est un bouton comme les autres. Il se distingue seulement par sa conception qui attire l'attention de l'utilisateur, grâce à son élévation qui lui donne un aspect flottant
Par contre, du point de vue positionnement, le FAB ne flotte pas au dessus des autres composants comme son nom pourrait le faire croire, et il n'est pas positionné automatiquement en bas de l'écran comme on peut le lire dans certains document.
Le positionnement du FAB dépend dans quel conteneur il est placé. Par exemple, si on le place dans une colonne qui contient déjà deux composables, il se positionnera normalement derrières ces composants. On pourra seulement le positionner horizontalement à l'aide du modifier align
Pour réellement faire flotter le FAB au dessus du reste du contenu et avoir beaucoup plus de souplesse de positionnement, il faut utiliser un Box() comme conteneur principal occupant tout l'écran. Dans ce Box(), on placera le contenu (dans une colonne par exemple) et le FAB, qui dans ce cas va se superposer à tout le reste et on peut le positionner horizontalement et verticalement à l'aide du modifier align
package com.example.floatingbutton
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material3.Button
import androidx.compose.material3.FloatingActionButton
import androidx.compose.material3.Icon
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyApp()
}
}
}
@Composable
fun MyApp() {
Box(
modifier = Modifier
.fillMaxSize()
.background(Color.LightGray)
) {
Column(
verticalArrangement = Arrangement.spacedBy(20.dp),
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.fillMaxSize()
) {
Button(onClick = { /*TODO*/ }) {
Text("Button 1")
}
Button(onClick = { /*TODO*/ }) {
Text("Button 2")
}
}
FloatingActionButton(
onClick = { /*TODO*/ },
modifier = Modifier
.align(Alignment.BottomEnd) // Positionner en bas à droite
.padding(16.dp) // Ajouter un padding pour éloigner du bord
) {
Icon(
imageVector = Icons.Default.Add,
contentDescription = "Add"
)
}
}
}
Spacer permet d'ajouter un espace vide entre les éléments. Pratique pour gérer l'espacement dans les Row, Column,
Spacer(modifier = Modifier.height(20.dp)) // Espacement vertical
Spacer(modifier = Modifier.width(20.dp)) // Espacement horizontale
Ce composable permet de charger et d'afficher une images à partir du dossier drawable ou même des images provenant d'une URL
Commencer par copier les images dans le dossier drawable de votre application. Le nom des fichiers ne doit contenir que des lettres minuscule (a - z), des chiffres (0 - 9) et le caractère underscore '_'
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.fillMaxWidth()
)
{
Image(
painter = painterResource(id = R.drawable.android),
contentDescription = null, modifier = Modifier.size(150.dp, 150.dp)
)
Spacer(modifier = Modifier.height(20.dp))
Image(
painter = painterResource(id = R.drawable.jpc),
contentDescription = null
)
Spacer(modifier = Modifier.height(20.dp))
Box(
modifier = Modifier
.size(200.dp, 200.dp)
.background(Color.Cyan)
){
Image(
painter = painterResource(id = R.drawable.android),
contentDescription = null,
modifier = Modifier.align(Alignment.CenterEnd)
)
}
}
permet à l'utilisateur de saisir du texte pour interagir avec l'application
C'est un composant qui nécessite beaucoup de pratique pour cerner toutes ses possibilités
L'exemple ci-dessous crée deux champs de saisie TextField() et deux champs d'affichage Text(). On va les appeler Textfield1, Textfield2, Text1 et Text2. Les deux TextFields sont légèrement différents
package com.example.textfield
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.unit.dp
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyApp()
}
}
}
@Composable
fun MyApp() {
var tf1variable by remember { mutableStateOf("") }
var tf2variable by remember { mutableStateOf("") }
var txt2 by remember { mutableStateOf("") }
Column(
verticalArrangement = Arrangement.spacedBy(20.dp),
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.fillMaxSize()
)
{
Spacer(modifier = Modifier.height(40.dp))
TextField(
value = tf1variable,
onValueChange = { tf1variable = it },
)
TextField(
value = tf2variable,
onValueChange = { tf2variable = it },
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done), // touche de validation
keyboardActions = KeyboardActions(
onDone = {
txt2 = tf2variable
tf2variable = ""
}
)
)
Text(
text = tf1variable,
modifier = Modifier
.size(200.dp, 40.dp)
.background(Color.LightGray)
.padding(8.dp)
)
Text(
text = txt2,
modifier = Modifier
.size(200.dp, 40.dp)
.background(Color.LightGray)
.padding(8.dp)
)
}
}
Si on clique dans Textfield1, le clavier apparaît comme indiqué sur la figure ci-dessous. On peut faire quelques observations:
Si on clique dans TextField2, le clavier apparaît comme indiqué sur la figure ci-dessous. On peut faire quelques observations:
L'apparence d'un TextField peut être ajustée à l'aide de ces attributs et ses modifiers.
textStyle = TextStyle(
color = Color.Blue, // Couleur du texte
fontSize = 20.sp, // Taille de la police
fontWeight = FontWeight.Bold, // Poids de la police (ex: gras)
lineHeight = 24.sp,
letterSpacing = 0.5.sp
),
colors = TextFieldDefaults.colors(
unfocusedContainerColor = Color(0xFFD6E4DE),
focusedContainerColor = Color.Cyan,
cursorColor = Color.Red, // Couleur du curseur
focusedIndicatorColor = Color.Red // Couleur du trait bas lorsque le TextField est focalisé
),
TextField(
value = tf1variable,
onValueChange = { tf1variable = it },
label = { Text("Nom") },
placeholder = { Text(text = "Entrez votre nom")},
textStyle = TextStyle(
color = Color.Blue, // Couleur du texte
fontSize = 20.sp, // Taille de la police
fontWeight = FontWeight.Bold, // Poids de la police (ex: gras)
letterSpacing = 2.sp, // espacement des caractères
),
colors = TextFieldDefaults.colors(
unfocusedContainerColor = Color(0xFFD6E4DE), // couleur de fond non-focussé
focusedContainerColor = Color.Cyan, // couleur de fond quand focussé
cursorColor = Color.Red, // Couleur du curseur
focusedIndicatorColor = Color.Red // Couleur du trait bas lorsque le TextField est focalisé
),
shape = RoundedCornerShape(topStart = 15.dp, topEnd=15.dp), // Coins arrondis de 12.dp
modifier = Modifier.size(300.dp, 70.dp) // Largeur et hauteur
)
La figure ci-dessous montre l'apparence du TextField avant d'avoir le focus, après avoir le focus et après avoir entré un texte
Le composable TextField gère plusieurs aspects liés au clavier virtuel, permettant de personnaliser l'apparence du clavier et les actions qu'il déclenche
keyboardOptions = KeyboardOptions( capitalization = KeyboardCapitalization.Sentences)
Quand on termine une saisie en cliquant sur la touche de validation, le clavier reste ouvert. Si on désire le fermer, une façon de le faire consiste à retirer le focus au TextField.
val focusManager1= LocalFocusManager.current
focusManager1.clearFocus() // pour fermer le clavier
val focusRecuaster1 = remember { FocusRequester() }
val focusManager1= LocalFocusManager.current
Modifier.focusRequester(focusRecuaster1)
focusManager1.clearFocus() // pour retirer le focus
focusRecuaster1.requestFocus() //pour donner le focus
LaunchedEffect(focusRecuaster1) {
focusRecuaster1.requestFocus() // pour donner le focus
}
LaunchedEffect(focusManager1) {
focusManager1.clearFocus() // pour retirer le focus
}
var isTFfocused by remember { mutableStateOf(false) }
Modifier.onFocusChanged {isTFfocused = it.isFocused }
Comme on peut le voir sur la figure ci-dessous, Le TextField (jaune) est un container qui contient un objet Text() (vert). Les marges entre les deux sont fixées par défaut et on ne peut pas les modifier. Quand on diminue la taille verticale du TextField(.weight ou .height), les marges sont conservées et c'est la taille du Text() qui diminue d'où le 'clipage' du texte. Si on veut agir sur ces marges, il faut utiliser BasicTextField()
OutlinedTextField est le même composable que TextField avec quelques différence visuelles. OutlinedTextField se distingue par:
var tf2variable by remember { mutableStateOf("") }
OutlinedTextField(
value = tf2variable,
label = { Text("Prénom") },
placeholder = { Text(text = "Taper votre prénom")},
onValueChange ={textsaisi ->
tf2variable = textsaisi },
textStyle = TextStyle(fontSize = 20.sp),
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 20.dp),
shape = RoundedCornerShape(size = 10.dp),
colors = TextFieldDefaults.colors(
unfocusedContainerColor = Color(0xFFD6E4DE),
focusedContainerColor = Color(0xFFE1F5F3),
cursorColor = Color.Blue, // Couleur du curseur
focusedIndicatorColor = Color.Red // Couleur de bordure lorsque le TextField est focalisé
),
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done), // bouton OK
keyboardActions = KeyboardActions(
onDone = {
txt2 = tf2variable
tf2variable = ""
focusManager1.clearFocus() // pour fermer le clavier
}
),
)
Le composable Checkbox fournit une case à cocher que l'utilisateur peut cocher ou décocher. Il est associé à une variable booléenne qui détermine son état, ainsi qu'une fonction lambda qui gère les modifications de cet état. Le composable ne propose pas un champ pour afficher un label à coté du Checkbox, il faut utiliser une Row() et y placer le Checkbox() et un Text()
package com.example.checkbox
import android.os.Bundle
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.material3.Checkbox
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyApp()
}
}
}
@Composable
fun MyApp() {
var cb1state by remember { mutableStateOf(false) }
var cb2state by remember { mutableStateOf(false) }
var cb3state by remember { mutableStateOf(false) }
val context = LocalContext.current
Column(verticalArrangement = Arrangement.spacedBy(20.dp)) {
Row(
verticalAlignment = Alignment.CenterVertically
) {
Checkbox(
checked = cb1state,
onCheckedChange = {
Toast.makeText(context, "Condition 1 est ${if (it) "Acceptée" else "refusée"}", Toast.LENGTH_SHORT).show()
cb1state = it }
)
Text("Accepter condition 1 ")
}
Row(
verticalAlignment = Alignment.CenterVertically
) {
Checkbox(
checked = cb2state,
onCheckedChange = { newstate ->
Toast.makeText(context, "Condition 2 est ${if (newstate) "Acceptée" else "refusée"}", Toast.LENGTH_SHORT).show()
cb2state = newstate }
)
Text("Accepter condition 2 ")
}
Row( verticalAlignment = Alignment.CenterVertically){
Checkbox(
checked = cb3state,
onCheckedChange = { newstate ->
Toast.makeText(context, "Condition 3 est ${if (newstate) "Acceptée" else "refusée"}", Toast.LENGTH_SHORT).show()
cb3state = newstate }
)
Text("Accepter condition 3 ")
}
}
}
Le composable Switch() fonctionne exactement comme un Checkbox(), il n'y a que le dessin qui n'est pas le même
package com.example.switch
import android.os.Bundle
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.material3.Switch
import androidx.compose.material3.SwitchDefaults
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyApp()
}
}
}
@Composable
fun MyApp() {
var switchState1 by remember { mutableStateOf(false) }
var switchState2 by remember { mutableStateOf(false) }
val context = LocalContext.current
Column(
modifier = Modifier.padding(16.dp),
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
Row(
verticalAlignment = Alignment.CenterVertically
) {
Text("Condition 1")
Spacer(modifier = Modifier.width(8.dp))
Switch(
checked = switchState1,
onCheckedChange = {
Toast.makeText(context, "Condition 1 est ${if (it) "Acceptée" else "refusée"}", Toast.LENGTH_SHORT).show()
switchState1 = it }
)
}
Row(
verticalAlignment = Alignment.CenterVertically
) {
Text("Condition 2")
Spacer(modifier = Modifier.width(8.dp))
Switch(
checked = switchState2,
colors = SwitchDefaults.colors(
checkedThumbColor = Color.Blue,
uncheckedThumbColor = Color.Red,
checkedTrackColor = Color.Magenta,
uncheckedTrackColor = Color.DarkGray
),
onCheckedChange = {
Toast.makeText(context, "Condition 2 est ${if (it) "Acceptée" else "refusée"}", Toast.LENGTH_SHORT).show()
switchState2 = it }
)
}
}
}
RadioButton() permet de choisir une option parmi plusieurs
package com.example.radiobutton
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.RadioButton
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyApp()
}
}
}
@Composable
fun MyApp() {
val options = listOf("Option 1", "Option 2","Option 3", "Option 4", "Option 5")
var selectedOption by remember { mutableStateOf(options[0]) }
Column(
modifier = Modifier.padding(16.dp),
verticalArrangement = Arrangement.spacedBy(10.dp)
) {
options.forEach { option ->
Row(verticalAlignment = Alignment.CenterVertically) {
RadioButton(
selected = selectedOption == option,
onClick = { selectedOption = option }
)
Text(option)
}
}
Text(text = "L'option sélectionnée est : $selectedOption")
}//fin colonne
}
Il arrive qu'on soit amené à répéter plusieurs fois un composable avec une lourde mise en forme ce qui peut être assez fastidieux.
Dans ce cas il peut être intéressant de créer une fonction composable pour cet élément
package com.example.personalcomposable
import android.os.Bundle
import android.widget.Toast
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyApp()
}
}
}
@Composable
fun MyApp() {
val context = LocalContext.current
Column(verticalArrangement = Arrangement.spacedBy(20.dp),
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.fillMaxSize())
{
Button(onClick = { /*TODO*/ }) {
Text(text = "B0")
}
MyTextButton(
text = "B1",
onClick = { Toast.makeText(context, "B1", Toast.LENGTH_SHORT).show()}
)
MyTextButton(
text = "B2",
onClick = {Toast.makeText(context, "B2", Toast.LENGTH_SHORT).show()}
)
MyTextButton(
text = "B3",
onClick = {}
)
MyTextButton(
text = "B4",
onClick = {}
)
MyTextButton(
text = "B5",
onClick = {}
)
}
}
@Composable
fun MyTextButton(
text: String,
onClick: () -> Unit,
) {
TextButton(
onClick = onClick,
border = BorderStroke(width = 1.dp, color = Color.Red),
shape = RoundedCornerShape(10.dp),
colors = ButtonDefaults.textButtonColors(
containerColor = Color.Green.copy(alpha = 0.3f)),
modifier = Modifier.size(width = 80.dp, height = 40.dp)
) {
Text(text = text,
fontSize = 20.sp,
fontWeight = FontWeight.Bold)
}
}
@Preview(showBackground = true)
@Composable
fun MyPreview() {
MyApp()
}
Le composant AlertDialog affiche une boite de dialogue pop-up par dessus l'interface utilisateur pour permettre à l'utilisateur d'effectuer des taches comme:
Le composable AlertDialog peut être personnalisé à l'aide de plusieurs paramètres spécifiques:
En général, les plus utilisés sont:
package com.example.alertdialog1
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.sp
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
MyApp()
}
}
}
@Composable
fun MyApp() {
var statusMSG by remember { mutableStateOf("Status inconu") }
var showDialog1 by remember { mutableStateOf(false) }
Column(horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.fillMaxSize()) {
Button(onClick = {
showDialog1 = true
}) {
Text(text = "Montrer Dialog")
}
Text(text = statusMSG)
}
if (showDialog1) {
AlertDialog(
onDismissRequest = {
statusMSG = "Ignoré"
showDialog1 = false
},
title = { Text(text = "Alerte!", color = Color.Red) },
text = { Text(text = "Voulez-vous vraiment supprimer le fichier", fontSize = 20.sp) },
confirmButton = {
Button(onClick = {
statusMSG = "Confirmé"
showDialog1 = false
}) {
Text(text = "Confirmer")
}
},
dismissButton = {
Button(onClick = {
statusMSG = "Annulé"
showDialog1 = false
}) {
Text("Annuler")
}
}
)
}
}
L'interface utilisateur contient un bouton Montrer Dialog et un champ de texte. Quand on clique sur le bouton, une boite de dialogue s'ouvre. Au retour du Dialogue, le champ de texte affichera un status correspondant au choix qui a été fait dans le dialogue.
L'appel à AlertDialog est placé dans la fonction composable MyApp() mais il est conditionné par l'état de la variable showDialog1
Quand on clique sur le bouton Montrer Dialog, on place la variable à true. Le changement de la variable provoque la recomposition de MyApp() qui conduit à l'ouverture de la boite de dialogue puisque l'état de la variable est true
A partir du dialogue, si on clique sur Confirmer, Annuler ou en dehors de la boite, alors la variable est placée à false. Le changement provoque la recomposition de L'UI entraînant la fermeture de la boîte de dialogue lors de la recomposition.
Chaque composable peut être caractérisé par un ensemble de paramètres (attributs) qui définissent ses propriétés spécifiques: taille, couleur, style ...
Parmi ces paramètre, il y en a un qui n'est pas comme les autres, c'est le paramètre modifier. A première vue, il semble avoir le même rôle que les autres attributs car il sert aussi à modifier l'apparence du composable. Mais il a un fonctionnement spécifique, on peut lui affecter l'objet (classe) Modifier auquel on peut attribuer plusieurs options, et ces options seront exécutées séquentiellement pour formater le composable.
Rien de mieux qu'un petit exemple
Box(modifier = Modifier
.size(300.dp, 300.dp)
.background(Color.Yellow)
.padding(40.dp)
.background(Color.Cyan)
.padding(40.dp)
.background(Color.Magenta)
.padding(40.dp)
.border(width=5.dp, Color.Blue)
.background(Color.Green)
)