Lists & Navigation in Kotlin Desktop: Compose Multiplatform | Lesson 04
Video: Lists & Navigation in Kotlin Desktop: Compose Multiplatform | Lesson 04 by Taught by Celeste AI - AI Coding Coach
Watch full page →Lists & Navigation in Kotlin Desktop: Compose Multiplatform | Lesson 04
In this lesson, we create a notes app using Compose Multiplatform for Kotlin Desktop, focusing on building efficient scrollable lists with LazyColumn and implementing type-safe navigation between screens. We use sealed classes to represent different screens and a when expression to route UI based on the current screen state, demonstrating state hoisting for navigation control.
Code
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
// Define screens as a sealed class for type-safe navigation
sealed class Screen {
object List : Screen()
data class Detail(val noteId: Int) : Screen()
}
@Composable
fun NotesApp() {
var currentScreen by remember { mutableStateOf(Screen.List) }
Scaffold(
topBar = {
TopBar(
title = when (currentScreen) {
is Screen.List -> "Notes"
is Screen.Detail -> "Note Details"
},
showBackButton = currentScreen is Screen.Detail,
onBack = { currentScreen = Screen.List }
)
}
) { padding ->
// Screen routing based on currentScreen state
when (val screen = currentScreen) {
is Screen.List -> NotesList(
notes = List(20) { "Note #$it" },
onNoteClick = { id -> currentScreen = Screen.Detail(id) },
modifier = Modifier.padding(padding)
)
is Screen.Detail -> NoteDetail(
noteId = screen.noteId,
modifier = Modifier
.padding(padding)
.verticalScroll(rememberScrollState())
)
}
}
}
@Composable
fun TopBar(title: String, showBackButton: Boolean, onBack: () -> Unit) {
SmallTopAppBar(
title = { Text(title) },
navigationIcon = if (showBackButton) {
{
IconButton(onClick = onBack) {
Icon(Icons.Default.ArrowBack, contentDescription = "Back")
}
}
} else null
)
}
@Composable
fun NotesList(notes: List, onNoteClick: (Int) -> Unit, modifier: Modifier = Modifier) {
LazyColumn(modifier = modifier.fillMaxSize()) {
items(notes.indices) { index ->
Card(
modifier = Modifier
.fillMaxWidth()
.padding(8.dp)
.clickable { onNoteClick(index) },
elevation = CardDefaults.cardElevation(defaultElevation = 4.dp)
) {
Text(
text = notes[index],
modifier = Modifier.padding(16.dp)
)
}
}
}
}
@Composable
fun NoteDetail(noteId: Int, modifier: Modifier = Modifier) {
Column(modifier = modifier.fillMaxSize().padding(16.dp)) {
Text("Details for Note #$noteId", style = MaterialTheme.typography.headlineMedium)
Spacer(Modifier.height(8.dp))
Text("Here you can show the full content of the note with id $noteId.")
}
}
Key Points
LazyColumnwithitems()efficiently renders large scrollable lists in Compose Desktop.- Clickable list items are created using
Cardwith theclickablemodifier to handle user interaction. - Sealed classes model app screens, enabling type-safe and clear navigation states.
- A
whenexpression drives screen routing based on the current navigation state. - State hoisting keeps navigation state in a parent composable, promoting unidirectional data flow and easy state management.