replica: one folder per app (replica/wetter)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
@@ -0,0 +1,171 @@
|
||||
# Komponenten: Wetter-Klon (Compose, Material 3 Expressive)
|
||||
|
||||
Tokens: `tokens.json` → `Tokens.kt` (über `gen_theme.py`). Komponenten verwenden nur Rollen (`WColor.onScene`), nie rohe Hex-Werte.
|
||||
Icons: Material Symbols Rounded (Apache 2.0) für die UI. Die Wettericons sind eigene oder [Meteocons](https://github.com/basmilius/weather-icons) (MIT), animiert über Lottie. Kein Google-Artwork.
|
||||
Schrift: Roboto Flex (OFL). Texte sind alle neu geschrieben, auf Deutsch.
|
||||
|
||||
## Grundregel Kontrast über Szenen
|
||||
|
||||
Text auf dem animierten Himmel nutzt `on-scene`, bei hellen Szenen (Schnee, Nebel, unterer Tagesverlauf) `on-scene-dark`. Die Szene meldet ihre Helligkeit (`scene.isLight`), und das Theme wählt danach.
|
||||
Beim klaren Tageshimmel oben besteht weißer Text nur als Großtext (3,9:1). Kleiner Text dort braucht deshalb einen Scrim, einen Verlauf von 0 auf 25 % Schwarz hinter dem Hero-Kopf.
|
||||
Karten auf der Szene: `scene-card` mit 85 % Deckkraft plus Blur (API 31+, `RenderEffect`). Ohne Blur wird `scene-card` voll deckend gezeigt.
|
||||
|
||||
---
|
||||
|
||||
```
|
||||
WeatherScene (animierter Hintergrund)
|
||||
variants clear, partly-cloudy, cloudy, rain, drizzle, snow, sleet, storm, fog × day/night; intensity 0..1
|
||||
layers sky gradient (scene-*-top/bottom) → sun/moon+stars → clouds (AGSL noise) → precipitation particles → lightning flash → fog
|
||||
states playing, paused (off-screen / lifecycle STOPPED), reduced (battery saver, "Animationen entfernen", setting off → static gradient), transitioning (crossfade 600ms between conditions)
|
||||
motion parallax 0.3× on scroll, wind direction tilts rain, haptic tick on lightning (if vibrations on, never during severe alert)
|
||||
a11y decorative: no semantics; condition always also stated in text
|
||||
perf adaptive quality (particle count by frame time), 30fps cap on low-end
|
||||
used on S01, S02 (row backgrounds, static), S12 (pre-rendered bitmap)
|
||||
|
||||
HeroBlock
|
||||
content city name (title) + location pin if current, temperature (display 96sp, wdth 125), condition (headline), "Gefühlt 12°" + H/T (body)
|
||||
states loading (shimmer on numbers, scene neutral), filled, stale ("Stand: vor 2 Std" chip), offline (cloud-off icon chip), no-permission (CTA "Standort erlauben")
|
||||
tokens on-scene / on-scene-dark, space 24 top
|
||||
motion temperature counts up on first load (300ms), collapses into app bar on scroll (large → small top app bar)
|
||||
a11y one merged semantics node: "Berlin, 14 Grad, leicht bewölkt, gefühlt 12, Höchstwert 17, Tiefstwert 9"
|
||||
used on S01
|
||||
|
||||
AlertBanner
|
||||
variants minor (alert-minor), moderate/severe (alert-severe), extreme (alert-extreme)
|
||||
content icon, event ("Sturmböen"), agency + validity ("DWD · bis 18:00"), chevron
|
||||
states single, stacked (n more), expanded (inline first lines), expired (removed with fade)
|
||||
tokens radius lg, padding 16
|
||||
a11y liveRegion polite on appear; whole banner is one button "Warnung: Sturmböen, Deutscher Wetterdienst, bis 18 Uhr. Details"
|
||||
used on S01 (top of cards, replaces Brief), S11
|
||||
|
||||
BriefCard
|
||||
content 1–2 sentences, generated (e.g. "Ab 15 Uhr Regen, abends trocken. Morgen 6° kühler.")
|
||||
states loading (two shimmer lines), filled, hidden (alert active or setting off)
|
||||
tokens scene-card, body, radius xl
|
||||
used on S01
|
||||
|
||||
HourlyStrip
|
||||
content per hour: time label, icon, temp, precip % if ≥ 20 %; sunrise/sunset inserted as items; "Jetzt" first
|
||||
states loading, filled, scroll; selected-hour (tap shows detail tooltip)
|
||||
extra temperature line chart behind items (Canvas, smooth cubic)
|
||||
a11y LazyRow, each item "15 Uhr, 14 Grad, Regen 40 Prozent"
|
||||
used on S01 (fixed position), S04, S12 (widget variant)
|
||||
|
||||
DayRow / DailyList
|
||||
content weekday ("Heute", "Mo"), icon, precip %, low temp, range bar (gradient cold→warm over the 10-day min..max, dot = current temp today), high temp
|
||||
states default, pressed (ripple), expanded (inline hourly, optional)
|
||||
a11y "Montag, Regen 60 Prozent, 8 bis 15 Grad"
|
||||
used on S01, S12
|
||||
|
||||
MetricCard (base for all detail cards)
|
||||
variants small 1×1, wide 2×1; shapes per tokens.shape (squircle, cookie, arch, pill)
|
||||
slots header (icon + label), value (metric 32sp), visual (gauge/chart), footer (one-line explanation)
|
||||
states default, pressed (morph radius→md, spring-fast), dragging (elevation card-drag, scale 1.04, haptic), placeholder (dashed border while dragging), loading, unavailable ("In deiner Region nicht verfügbar")
|
||||
tokens scene-card / scene-card-light, on-scene, radius lg
|
||||
a11y button → opens S05; reorder via accessibility actions "Nach oben/unten verschieben"
|
||||
used on S01, S10
|
||||
|
||||
instances
|
||||
Precip next-hour bar chart (minutely_15) + "Regen in ~20 Min" / total today
|
||||
Wind compass dial with arrow, speed, gusts, Beaufort label
|
||||
UV cookie shape, arc 0–11+, colour by band (uv-high etc.), "Sonnenschutz 11–16 Uhr"
|
||||
Humidity value + dew point, vertical fill
|
||||
Pressure dial with trend arrow (rising/falling over 3h)
|
||||
Visibility value + description
|
||||
Sun arch with sun position dot, sunrise/sunset times, day length
|
||||
AQI pill scale (aqi-good..aqi-bad), value, main pollutant
|
||||
Pollen top 3 types with level dots (Europe only, else hidden)
|
||||
Map static radar preview thumbnail → opens S06
|
||||
|
||||
RadarMap (S06)
|
||||
content MapLibre + OSM base (light/dark style), RainViewer overlay, location dot, attribution
|
||||
controls timeline scrubber (past 2h … +30min), play/pause FAB, time label, legend
|
||||
states loading tiles, playing, paused, no-coverage, offline
|
||||
a11y scrubber is a Slider with "13:40, Vorhersage" values
|
||||
used on S06
|
||||
|
||||
CityRow
|
||||
content name, admin area, local time, temp, condition icon, H/T; current-location row with pin and not deletable
|
||||
states default, pressed, swiping (red bg + trash icon reveal), deleted (snackbar "Gelöscht · Rückgängig"), dragging (reorder)
|
||||
bg static mini scene gradient for the city's condition
|
||||
motion shared element (name + temp) into S01
|
||||
used on S02
|
||||
|
||||
SearchField + ResultList
|
||||
states empty (recents), typing (debounced 300ms, progress), results, no results ("Kein Ort gefunden"), error (retry)
|
||||
a11y SearchBar (M3), results announce count
|
||||
used on S03
|
||||
|
||||
TopAppBar
|
||||
variants transparent over scene (S01), surface (S02, S08)
|
||||
content menu/list button, city title (collapsed), settings icon (no account avatar)
|
||||
used on S01, S02, S08
|
||||
|
||||
PagerIndicator
|
||||
dots for saved cities, current one wide (expressive pill); swipe between cities
|
||||
used on S01
|
||||
|
||||
Settings rows
|
||||
variants radio group, switch, link row, section header
|
||||
states default, disabled (with reason text), focused
|
||||
used on S08, S09
|
||||
|
||||
Snackbar, Dialog (permission rationale), Shimmer placeholder: M3 standard with tokens.
|
||||
```
|
||||
|
||||
## Widgets (Glance)
|
||||
|
||||
```
|
||||
Widget shell
|
||||
radius widget (24dp, follows system launcher radius on Android 12+)
|
||||
styles dynamic_color (surface-container from wallpaper), condition (pre-rendered scene bitmap + on-scene text), transparent (text with shadow)
|
||||
states loading ("…"), filled, stale (small clock icon), no location ("Ort wählen"), error (tap to retry)
|
||||
tap opens S01 for that city; refresh icon only on ≥ 4×2
|
||||
|
||||
NowWidget 2×1: icon + temp | 2×2: + city, condition, H/T
|
||||
HourlyWidget 4×2: now block + 6 hours (icon, temp, time)
|
||||
DailyWidget 4×2: now + 5 days | 4×3: + range bars
|
||||
FullWidget 4×4: now, 5 hours, 5 days, alert line if active
|
||||
GlanceWidget 4×1: "Fr., 17. Okt. · ☀ 14°" one line, alert replaces date (two lines: event, agency)
|
||||
|
||||
type display-widget 44sp for temps, label for times; size by SizeMode.Responsive breakpoints
|
||||
a11y contentDescription on root summarising the widget
|
||||
config S12-config activity: location picker, style, live preview, "Fertig"
|
||||
```
|
||||
|
||||
## Screens → Komponenten (Status)
|
||||
|
||||
| Screen | Komponenten |
|
||||
| --- | --- |
|
||||
| S01 | WeatherScene, TopAppBar, HeroBlock, AlertBanner, BriefCard, HourlyStrip, DailyList, MetricCard×n, PagerIndicator |
|
||||
| S02 | TopAppBar, CityRow, SearchField |
|
||||
| S03 | SearchField, ResultList |
|
||||
| S04/S05 | HourlyStrip, chart, MetricCard expanded |
|
||||
| S06 | RadarMap |
|
||||
| S08/S09 | Settings rows |
|
||||
| S10 | MetricCard (dragging/placeholder) |
|
||||
| S11 | AlertBanner expanded, text |
|
||||
| S12 | Widgets |
|
||||
|
||||
## Abgleich mit Screenshots (ref-01..04), überschreibt Abweichungen oben
|
||||
|
||||
Gemessen an `replica/screens/ref-*.png`. Das Layout-Muster übernehmen wir, die Grafik zeichnen wir selbst.
|
||||
|
||||
- **HeroBlock:** zentrierte Spalte. Oben die Wetterlage (22sp), darunter die Temperatur sehr groß und **fett** (112sp, 700, nicht dünn) mit dem Wettericon direkt rechts daneben, etwa 40 % der Ziffernhöhe, oben ausgerichtet. Dann „Gefühlt 19°“ und „Höchstwert 22° · Tiefstwert 14°“. Am Tag ist der Text dunkel auf hellem Himmel, nachts weiß. Es gibt keinen Scrim, die hellen Szenen sind entsprechend hell gewählt.
|
||||
- **Szene:** ruhiger, weicher Verlauf mit großen, unscharfen, langsam treibenden Formen (Wolkenschemen, Hügel). Keine fotorealistische Darstellung. Bei Niederschlag fallen dezente Partikel.
|
||||
- **Karten-Container:** deckend (`card` bzw. `dark-card`, warm getöntes Neutral), Radius 28, Padding 20. Die Kopfzeile besteht aus einem Outline-Icon und dem Titel (card-title). Zwischen den Karten 12 dp Abstand, nach außen 16 dp Rand.
|
||||
- **HourlyStrip:** Die Spalten zeigen Temperatur, darunter Icon, darunter Niederschlag in % (`precip-text`, klein), darunter die Uhrzeit. Die aktuelle Stunde trägt einen **Cookie-Chip** (`now-chip`) hinter der Temperatur, das Label heißt „Jetzt“.
|
||||
- **DailyList:** **horizontal** scrollende Reihe vertikaler **Kapseln** (`pill`, Radius 24, ca. 56×190 dp). In jeder Kapsel stehen Höchstwert, Tiefstwert (muted), Icon, Niederschlag in % und Tag plus Datum. Ein Tipp auf die Kapsel öffnet S04.
|
||||
- **DayDetail (S04, bestätigt):** oben eine Kapselreihe, die gewählte Kapsel ist hervorgehoben (`pill-selected`). Darunter Datum, Ort, „24°/14°“ (day-range 56sp) mit Icon, Wetterlage, die stündliche Vorhersage für diesen Tag und darunter dieselben Detailkarten.
|
||||
- **Detailkarten:** Raster mit 2 Spalten aus quadratischen Kacheln, **Formen statt einheitlicher Karten**:
|
||||
- Wind: Kreis, darin ein abgerundetes Dreieck als Blob (`fill-*`), gedreht in die Windrichtung, mittig Wert und Einheit, darunter „Aus NW“
|
||||
- UV: Cookie mit 12 Wellen, Wert und Stufe, Punkte auf einem unteren Bogen, der aktive Punkt farbig
|
||||
- Sichtweite: Kreis mit gewellter Innenfläche (`fill-tertiary`), Wert und Einheit
|
||||
- Luftfeuchte: Rechteck, Füllstand mit gewellter Oberkante, Höhe = %, unten ein runder Chip mit dem Taupunkt
|
||||
- Luftdruck: Kreis mit 270°-Bogenanzeige, Wert groß, Einheit darunter
|
||||
- Sonne: Rechteck mit gefülltem Sinus-Hügel über der Horizontlinie, der Nachtteil dunkler, Sonnenpunkt auf der Kurve, Aufgang und Untergang als Zeiten
|
||||
- Luftqualität: Rechteck mit Verlaufsbalken und Knopf, Wert, Einstufung („Gute Luftqualität“); ohne Daten wird „– –“ gezeigt
|
||||
- **NowcastCard (neu):** „Regen ab 09:15“ als Titel, Untertitel „Leichter Regen von 09:15 bis 10:45“. Ein Punkt-Balkendiagramm zeigt die nächsten 2–3 Stunden in 15-Minuten-Schritten, die Y-Achse in drei Stufen (leicht, mäßig, stark). Ein Marker-Chip am Beginn, die X-Achse mit Uhrzeiten. Die Karte erscheint nur, wenn in den nächsten 3 Stunden Niederschlag kommt. Daten: Open-Meteo `minutely_15`.
|
||||
- **BriefCard:** wie eine normale Karte mit Icon, Titel „Kurz gesagt“ und einem Chevron zum Auf- und Zuklappen. Darunter 2–3 Sätze Text in body.
|
||||
- **Vorschau eines Orts (S15, neu):** Ein gesuchter Ort öffnet die volle Ansicht mit einem Button „Speichern“ oben rechts (gefüllter Pill-Button, Tonal).
|
||||
- **Abweichungen, die bewusst eigen bleiben:** eigene Icons und Szenen, ein eigener Akzent erst in `/replica-brand`, eigene Texte. Die Kartenformen sind M3-Expressive-Standardformen (`MaterialShapes`: Cookie, Circle, Triangle, Wavy), damit ist nichts vom Original nachgezeichnet.
|
||||
Reference in New Issue
Block a user