Jetpack Compose

Build modern Android UIs declaratively with Kotlin — composables, state, and Material components

@Composable State Column / Row Material3

Table of Contents

1Introduction to Jetpack Compose

Jetpack Compose is Android's modern UI toolkit for building native interfaces using Kotlin. Instead of XML layouts, you describe UI with @Composable functions. When state changes, Compose automatically updates only the parts of the UI that changed — called recomposition.

Imperative (XML + Views) Declarative (Compose) ───────────────────────── ───────────────────── findViewById, setText State changes → UI recomposes Manual visibility toggles @Composable functions describe UI activity_main.xml setContent { MyScreen() }

XML Views vs Compose

XML / ViewsJetpack Compose
TextViewText()
ButtonButton { Text("Click") }
LinearLayoutColumn / Row
RecyclerViewLazyColumn
View BindingNot needed — UI is Kotlin code

Enable Compose in Gradle

app/build.gradle.ktsandroid { buildFeatures { compose = true } composeOptions { kotlinCompilerExtensionVersion = "1.5.8" } } dependencies { val composeBom = platform("androidx.compose:compose-bom:2024.02.00") implementation(composeBom) implementation("androidx.compose.ui:ui") implementation("androidx.compose.material3:material3") implementation("androidx.activity:activity-compose:1.8.2") }

First Compose Activity

MainActivity.ktclass MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { MyAppTheme { Surface( modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background ) { Greeting(name = "Kotlin") } } } } } @Composable fun Greeting(name: String) { Text( text = "Hello, $name!", modifier = Modifier.padding(16.dp) ) }
Prerequisites

Know Kotlin basics, null safety, and lambdas before Compose. See Kotlin Android Development for traditional Views-based UI.

2Composable Functions

A function marked with @Composable describes UI. Composables can call other composables, accept parameters, and re-run when their inputs change.

Basic composable structure

ProfileCard composable@Composable fun ProfileCard( name: String, email: String, onEditClick: () -> Unit ) { Card( modifier = Modifier .fillMaxWidth() .padding(16.dp), elevation = CardDefaults.cardElevation(defaultElevation = 4.dp) ) { Column(modifier = Modifier.padding(16.dp)) { Text(text = name, style = MaterialTheme.typography.headlineSmall) Spacer(modifier = Modifier.height(4.dp)) Text(text = email, style = MaterialTheme.typography.bodyMedium) Spacer(modifier = Modifier.height(12.dp)) Button(onClick = onEditClick) { Text("Edit Profile") } } } }

Modifier — style and layout

Modifier chainText( text = "Styled Text", modifier = Modifier .fillMaxWidth() .padding(horizontal = 16.dp, vertical = 8.dp) .background(Color.LightGray, shape = RoundedCornerShape(8.dp)) .clickable { /* handle click */ } .padding(12.dp), fontSize = 18.sp, fontWeight = FontWeight.Bold, color = MaterialTheme.colorScheme.primary )

Preview in Android Studio

@Preview annotation@Preview(showBackground = true, name = "Light Mode") @Composable fun ProfileCardPreview() { MyAppTheme { ProfileCard( name = "Nikhil", email = "nikhil@example.com", onEditClick = {} ) } }

Composable rules

RuleExplanation
Call from composables onlysetContent { } or another @Composable
RecompositionRe-runs when state/params change
Default parameter orderPut modifier: Modifier = Modifier first optional param
No return valueComposables emit UI, don't return widgets
Theme wrapper: Wrap previews and screens in MaterialTheme { } for colors, typography, and shapes — define in a Theme.kt file.

3State Management

Compose UI updates when state changes. Use remember for local UI state, state hoisting for reusable components, and ViewModel + StateFlow for screen-level data.

Local state with remember

Counter composable@Composable fun Counter() { var count by remember { mutableIntStateOf(0) } Column(horizontalAlignment = Alignment.CenterHorizontally) { Text(text = "Count: $count", fontSize = 24.sp) Spacer(modifier = Modifier.height(16.dp)) Button(onClick = { count++ }) { Text("Increment") } } }

State hoisting

Move state up to a parent composable so child composables stay stateless and reusable:

Hoisted state pattern// Stateless child — receives value + callback @Composable fun NameField(name: String, onNameChange: (String) -> Unit) { OutlinedTextField( value = name, onValueChange = onNameChange, label = { Text("Your name") }, modifier = Modifier.fillMaxWidth() ) } // Stateful parent owns the state @Composable fun RegistrationScreen() { var name by remember { mutableStateOf("") } Column(modifier = Modifier.padding(16.dp)) { NameField(name = name, onNameChange = { name = it }) Spacer(modifier = Modifier.height(16.dp)) Text("Hello, ${name.ifEmpty { "Guest" }}!") } }

ViewModel + StateFlow

ViewModel and collectAsStateclass HomeViewModel : ViewModel() { private val _uiState = MutableStateFlow(HomeUiState()) val uiState: StateFlow<HomeUiState> = _uiState.asStateFlow() fun loadData() { viewModelScope.launch { _uiState.update { it.copy(isLoading = true) } // fetch from repository... _uiState.update { it.copy(isLoading = false, message = "Loaded") } } } } data class HomeUiState( val message: String = "", val isLoading: Boolean = false ) @Composable fun HomeScreen(viewModel: HomeViewModel = viewModel()) { val uiState by viewModel.uiState.collectAsStateWithLifecycle() if (uiState.isLoading) { CircularProgressIndicator() } else { Text(uiState.message) } }
State APIScopeUse for
remember { mutableStateOf() }ComposableToggle, counter, expand/collapse
rememberSaveableComposableSurvives rotation / process death
ViewModel + StateFlowScreenAPI data, business logic
derivedStateOfComposableComputed values from other state
Coroutines in Compose

Use viewModelScope.launch for async work — pairs naturally with Compose state. Review Kotlin Coroutines.

4UI Components

Compose provides layout composables and Material Design components for building screens — text, buttons, inputs, lists, and app structure.

Layout composables

Column, Row, Box@Composable fun LoginForm() { Column( modifier = Modifier .fillMaxSize() .padding(24.dp), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally ) { Text("Sign In", style = MaterialTheme.typography.headlineMedium) Spacer(modifier = Modifier.height(24.dp)) OutlinedTextField(value = "", onValueChange = {}, label = { Text("Email") }) Spacer(modifier = Modifier.height(12.dp)) Button(onClick = {}, modifier = Modifier.fillMaxWidth()) { Text("Login") } } }

Common Material components

ComponentPurpose
Text()Display text with typography styles
Button() / TextButton()Clickable actions
OutlinedTextField()Text input with label
Card()Elevated container for grouped content
Icon() / IconButton()Icons from Material Icons
Switch() / Checkbox()Boolean toggles
LazyColumn()Efficient scrollable list
Scaffold()TopBar, FAB, bottom bar structure

LazyColumn — scrollable list

Task list@Composable fun TaskList(tasks: List<String>, onTaskClick: (String) -> Unit) { LazyColumn( contentPadding = PaddingValues(16.dp), verticalArrangement = Arrangement.spacedBy(8.dp) ) { items(tasks, key = { it }) { task -> Card( modifier = Modifier .fillMaxWidth() .clickable { onTaskClick(task) } ) { Text(text = task, modifier = Modifier.padding(16.dp)) } } } }

Scaffold — app screen structure

Scaffold with TopAppBar@OptIn(ExperimentalMaterial3Api::class) @Composable fun TaskScreen(onAddClick: () -> Unit) { Scaffold( topBar = { TopAppBar(title = { Text("My Tasks") }) }, floatingActionButton = { FloatingActionButton(onClick = onAddClick) { Icon(Icons.Default.Add, contentDescription = "Add task") } } ) { innerPadding -> Box(modifier = Modifier.padding(innerPadding)) { TaskList( tasks = listOf("Learn Compose", "Build app"), onTaskClick = {} ) } } }

Layout mapping from XML

XMLCompose
LinearLayout (vertical)Column
LinearLayout (horizontal)Row
FrameLayoutBox
ScrollView + listLazyColumn
ToolbarTopAppBar in Scaffold
Deep dive: For navigation, theming, and advanced Compose patterns, see the full Android Jetpack Compose tutorial in the Android track.

5Summary Cheatsheet

TopicKey Takeaway
IntroductionDeclarative UI in Kotlin; setContent { }; no XML layouts
Composable Functions@Composable; Modifier; @Preview; recomposition
State Managementremember, state hoisting, ViewModel + StateFlow
UI ComponentsColumn/Row/Box, Text, Button, LazyColumn, Scaffold
Material3MaterialTheme for colors and typography
Next lessonKotlin Projects