ComposeActivityapp/build.gradle.kts pour configurer Compose (buildFeatures, dependencies, etc) et l'ajouter au AndroidManifest.xmlAndroidManifest pour en faire notre activity principale à la place de l'ancienne, et relancez l'app pour vérifier: il faut déplacer ... de l'ancienne activity à la nouvelleGreeting en ListScreen et GreetingPreview en ListPreview et supprimez l'argument nameVous devriez avoir quelque chose comme ça:
class ComposeActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//...
setContent {
TodoTheme {
ListScreen()
}
}
}
}
LazyColumn et items), avec des éléments, c'est légerement plus simple qu'une RecyclerView 🙃 :LazyColumn{
items(100) {
Text(text = "Item #$it")
}
}
Modifier.fillMaxWidth() à la LazyColumnModifier.padding(16.dp) à la LazyColumn pour ajouter un peu d'espace autourverticalArrangement = Arrangement.spacedBy(8.dp) comme argumentOn va maintenant ajouter un peu d'interactivité sur notre liste.
items en haut de ListScreen:var items by remember { mutableStateOf(List(100) { "Item #$it" }) }
items au lieu de la liste statique: attention il faudrait importer une autre fonction items qui prend directement une List au lieu d'un Int (l'IDE devrait vous proposer l'import automatiquement mais parfois il confond les 2)String par des data class Task et ajoutez la description:items(items) { task ->
Column {
Text(text = task.title)
Text(text = task.description)
}
}
On va utiliser des éléments de "Material Design 3" pour améliorer un peu l'interface facilement.
ListScreen pour qu'elle utilise un Scaffold, avec une TopAppBar (acceptez de "Opt-in à ExperimentalMaterial3Api") avec le titre de votre choixFloatingActionButton avec une icône "Add"Scaffold à la LazyColumn pour que le contenu ne soit pas caché par la TopAppBarScaffold(
modifier = Modifier.fillMaxSize(),
topBar = { TopAppBar(title = { Text(/* title */) }) },
floatingActionButton = {
FloatingActionButton(onClick = { /* TODO */ }) {
Icon(imageVector = Icons.Default.Add, contentDescription = "Add")
}
}
) {
LazyColumn() {
// ...
}
}
On va maintenant implémenter l'ajout d'éléments à la liste.
FloatingActionButton pour ajouter un nouvel élément à la liste comme précédemment mais en Compose:onClick = {
val newItem = Task(title = "Item #${items.size}")
items = items + newItem
}
LazyListState pour scroller automatiquement jusqu'en bas:val listState = rememberLazyListState() en haut de ListScreenlistState à la LazyColumn avec state = listStateonClick du FloatingActionButton pour scroller jusqu'en bas après avoir ajouté l'élément avec listState.animateScrollToItem(items.size - 1)val coroutineScope = rememberCoroutineScope() en haut de ListScreencoroutineScope.launch {
// suspend function
}
Ajoutez un bouton de suppression dans chaque élément et faites sorte qu'il fonctionne Pour avoir un item avec le texte à gauche et le bouton tout à droite vous pouvez utiliser une Row avec horizontalArrangement = Arrangement.SpaceBetween ou bien un Spacer(modifier = Modifier.weight(1f)) entre les 2 éléments.
On va d'abord permettre de naviguer vers notre ancienne MainActivity:
actions de la top bar:IconButton(onClick = {...}) {
Icon(
imageVector = Icons.AutoMirrored.Filled.ArrowForward,
contentDescription = "go to classic app"
)
}
MainActivity:val intent = Intent(context, MainActivity::class.java)
context.startActivity(intent)
Pour récupérer un Context on utilise un CompositionLocal:
val context = LocalContext.current
Maintenant on va utiliser la bibliothèque Navigation3 pour gérer la navigation de manière plus propre:
app/build.gradle.kts: doc@Composable DetailScreen(task: Task) qui affiche les détails d'une tâcheListScreen dans un autre fichier égalementComposeActivity, au lieu d'afficher directement ListScreen, créez et utilisez un composant App():ListScreen sans la topBar: déplacez là dans un autre Scaffold que vous ajouterez dans App() pour qu'elle soit commune à tous les écransListScreen pour qu'au clic sur un élément, on navigue vers DetailNavScreen@Serializable
data object ListNavScreen : NavKey
@Serializable
data class DetailNavScreen(val task: Task) : NavKey
@Composable
fun App() {
// on créé notre historique de navigation avec la liste comme écran initial
val backStack = rememberNavBackStack(ListNavScreen)
NavDisplay(
backStack = backStack,
entryProvider = entryProvider {
entry<ListNavScreen> { ListScreen(onClickItem = {...}) }
entry<DetailNavScreen> { key -> DetailScreen(task = key.task) }
}
)
}
TaskItem pour la partie qui affiche chaque item et faire en sorte qu'au clic sur un item, on remonte un event onClick qui permettra de naviguer vers l'écran détail:@Composable
private fun TaskItem(
modifier: Modifier = Modifier,
item: Task,
onClick: (Task) -> Unit,
onDelete: () -> Unit,
) {...}
App(), faites en sorte que ce clic navigue bien:// Pour naviguer vers l'écran détail, on l'ajoute à l'historique:
backStack.add(DetailNavScreen(...))
DetailScreen qui permet de revenir en arrière:// Pour revenir en arrière, on enlève le dernier écran de l'historique:
backStack.removeLastOrNull()