Compose-Grundlagen

20 MinutenDie Bausteine von Jetpack Compose kennenlernen

Die Wetter-App

Eine Liste von Städten, nach Antippen das aktuelle Wetter der Stadt.

  • Schritte 1–8: Oberfläche und Architektur mit Fake-Daten
  • Schritt 9: echte Wetterdaten von Open-Meteo, angebunden mit einem Coding Agent
  • Schritt 10: Feinschliff mit Material 3
  • Jeder Schritt ist ein Commit mit Tag, z. B. schritt-05

Projektstruktur

Der Kotlin-Code ist nach Aufgaben in Pakete aufgeteilt.

app/src/main/java/com/example/weatherandroidtif24/
├── MainActivity.kt
├── ui/          Screens und Composables, ViewModels
│   └── theme/   Farben, Schriften, Theme (aus der Vorlage)
├── model/       Datenmodell: City, CurrentWeather
└── data/        Datenquellen: Fake-Daten, Repositorys
    └── api/     HTTP-Client und DTOs (ab Schritt 9)

Composables

Ein Composable ist eine Kotlin-Funktion, die beschreibt, wie ein Teil der Oberfläche aussieht.

@Composable
fun WeatherScreen(modifier: Modifier = Modifier) {
    Text(text = "Lörrach", modifier = modifier)
    Text(text = "14 °C", modifier = modifier)
}

Composables

Mit @Preview zeigt Android Studio ein Composable direkt im Editor an, ohne Emulator.

@Preview(showBackground = true)
@Composable
fun WeatherScreenPreview() {
    WeatherScreen()
}

Layouts: Column, Row, Box

Composables werden mit Layout-Composables angeordnet.

  • Column: untereinander
  • Row: nebeneinander
  • Box: übereinander, z. B. Inhalt auf einem Hintergrund
  • Spacer: Abstand bzw. freier Platz

Layouts: Column, Row, Box

Die Verschachtelung im Code entspricht der Verschachtelung auf dem Bildschirm.

Layout als verschachtelte Boxen: Bildschirm und Code haben denselben Aufbau
Layout als verschachtelte Boxen: Bildschirm und Code haben denselben Aufbau

Layouts: Column, Row, Box

Column(horizontalAlignment = Alignment.CenterHorizontally) {
    Text(text = "Lörrach", fontSize = 28.sp)
    Text(text = "⛅", fontSize = 72.sp)
    Text(text = "14 °C", fontSize = 48.sp)
    Spacer(modifier = Modifier.height(16.dp))
    Row(modifier = Modifier.fillMaxWidth()) {
        Text(text = "Wind: 8 km/h")
        Spacer(modifier = Modifier.weight(1f))
        Text(text = "Teilweise bewölkt")
    }
}

Modifier

Modifier verändern Größe, Abstand, Hintergrund und Verhalten eines Composables. Sie werden durch aufeinanderfolgende Funktionsaufrufe verkettet.

Box(
    modifier = modifier
        .fillMaxWidth()
        .padding(16.dp)
        .background(Color(0xFFBBDEFB), RoundedCornerShape(24.dp))
        .padding(24.dp),
    contentAlignment = Alignment.Center,
) { /* Column von oben */ }

Datenmodell mit data class

Statt fester Texte bekommen Composables nun Daten als Parameter.

data class City(
    val name: String,
    val latitude: Double,
    val longitude: Double,
)

data class CurrentWeather(
    val temperature: Double,
    val windSpeed: Double,
    val condition: WeatherCondition,
)

Datenmodell mit data class

Composables sollten Daten als Parameter erhalten und sie nicht eigenständig holen.

@Composable
fun CurrentWeatherCard(
    city: City,
    weather: CurrentWeather,
    modifier: Modifier = Modifier,
) {
    // ...
    Text(text = city.name)
    Text(text = weather.condition.emoji())
    Text(text = "${weather.temperature.roundToInt()} °C")
}

Scaffold und TopAppBar

Compose bringt die Komponenten von Material Design 3 mit, dem Designsystem von Google. Scaffold ist das Grundgerüst eines Screens, z. B. mit einer TopAppBar.

Scaffold(
    topBar = { TopAppBar(title = { Text(text = city.name) }) },
) { innerPadding ->
    CurrentWeatherCard(
        city = city,
        weather = weather,
        modifier = Modifier.padding(innerPadding),
    )
}

Übung: Karte gestalten

  • Farben, Abstände und Schriftgrößen der Karte ändern, in der Preview ausprobieren
  • Bonus: neuer Parameter highlighted, der die Karte mit einem Rahmen hervorhebt