feat(theme): user-selectable custom fonts (#19)

Add a per-role font picker in Appearance settings. The two Material
typeface roles can be set independently: brand (display/headline) and
plain (title/body/label). Each can be the system default, a bundled
font (Atkinson Hyperlegible, Lora, JetBrains Mono), or a .ttf/.otf the
user loads from the device. The choice rebuilds the app-wide typography
in MainActivity; a null/"system" choice leaves the Material default.

Per the issue discussion the font-size and font-colour parts were
dropped — Android's accessibility font scaling and the dynamic-colour
theme already cover them.

Custom files are copied into app-private storage and validated with
android.graphics.fonts.Font.Builder before replacing the previous one,
so a bad pick can't wedge global text rendering; a missing/unreadable
file degrades to the system font. Each bundled font is previewed in its
own face in the picker. OFL licences + attribution vendored under
licenses/fonts/.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-01 15:09:41 +02:00
parent 69460bc35a
commit bfc9a0db39
20 changed files with 839 additions and 3 deletions

View File

@@ -252,6 +252,15 @@
<string name="settings_theme_dark">Dunkel</string>
<string name="settings_dynamic_color">Dynamische Farben</string>
<string name="settings_dynamic_color_unavailable">Erfordert Android 12 oder neuer</string>
<string name="settings_font_headings">Schriftart für Überschriften</string>
<string name="settings_font_body">Schriftart für Text</string>
<string name="settings_font_system">Systemstandard</string>
<string name="font_atkinson_hyperlegible">Atkinson Hyperlegible</string>
<string name="font_lora">Lora</string>
<string name="font_jetbrains_mono">JetBrains Mono</string>
<string name="settings_font_choose_file">Datei auswählen…</string>
<string name="settings_font_custom_selected">Eigene Schriftart</string>
<string name="settings_font_import_failed">Diese Datei konnte nicht als Schriftart gelesen werden</string>
<string name="settings_week_start">Wochenstart</string>
<string name="settings_week_start_auto">Automatisch</string>
<string name="settings_time_format">Zeitformat</string>