To-Do app with two sections, Active and Completed, using Jetpack Compose. The app demonstrates the concepts we covered in class: data classes, state, remember/rememberSaveable, and state hoisting. The UI is responsive, accessible, and can handle common edge cases gracefully.
- Add item
- List items (active)
- List items (Completed)
- Sections & empty states
- Delete tasks from either list.
-
The
Taskdata class models each task with three properties:id: unique identifier for each tasktitle: task descriptionisCompleted: Boolean state indicating if the task is completed
data class Task(
val id: Int,
val title: String,
val isCompleted: Boolean = false
)-
rememberSaveableis used to store and restore state across recompositions and configuration changes (like screen rotation). -
Examples:
taskText→ holds text input from the usertasks→ list of all tasksvalidationMessage→ displays error messages
var taskText by rememberSaveable { mutableStateOf("") }
var tasks by rememberSaveable { mutableStateOf(listOf<Task>()) }
var validationMessage by remember { mutableStateOf("") }- State is hoisted so that child composables (
TaskListandTaskItem) receive their state and callbacks from the parent (ToDoApp). - This makes the UI modular and testable.
- Example:
onToggleTaskandonDeleteTaskare passed down fromToDoAppintoTaskListand then intoTaskItem.
TaskList(
tasks = activeTasks,
onToggleTask = { toggleTask(it) },
onDeleteTask = { deleteTask(it) }
)-
The app is structured into smaller reusable UI pieces:
ToDoApp()→ main app logicTaskList()→ displays a list of tasksTaskItem()→ UI for a single task