Skip to content

Kapitel 11: Styling & Themes

11.1 Flutter Styling-Grundlagen

TextStyle (Textstil)

dart
Text(
  'Flutter Lernen',
  style: TextStyle(
    fontSize: 24,              // Schriftgröße
    fontWeight: FontWeight.bold, // Fettschrift
    color: Colors.blue,        // Textfarbe
    fontStyle: FontStyle.italic, // Kursiv
    letterSpacing: 2.0,        // Buchstabenabstand
    wordSpacing: 4.0,          // Wortabstand
    height: 1.5,               // Zeilenhöhe
    decoration: TextDecoration.underline, // Unterstreichung
  ),
)

BoxDecoration (Container-Stil)

dart
Container(
  decoration: BoxDecoration(
    color: Colors.blue.shade100,      // Hintergrundfarbe
    borderRadius: BorderRadius.circular(8),  // Rahmenradius
    border: Border.all(color: Colors.blue), // Rahmen
    boxShadow: [                       // Schatten
      BoxShadow(
        color: Colors.grey.withOpacity(0.5),
        spreadRadius: 2,
        blurRadius: 4,
        offset: const Offset(0, 2),
      ),
    ],
    gradient: LinearGradient(           // Farbverlauf
      colors: [Colors.blue, Colors.purple],
      begin: Alignment.topLeft,
      end: Alignment.bottomRight,
    ),
  ),
  child: const Text('Container Inhalt'),
)

11.2 Theme-Konfiguration (globale Stilvereinheitlichung)

Globales Theme (MaterialApp.theme)

Vorteile:

  • ✅ Einheitliches Aussehen der gesamten App
  • ✅ Weniger Code (kein wiederholtes Styling)
  • ✅ Einfache Änderung des gesamten App-Stils
dart
MaterialApp(
  title: 'Meine App',
  theme: ThemeData(
    // Primärfarbe (AppBar, Buttons, etc.)
    primarySwatch: Colors.blue,
    
    // Farbschema (hell/dunkel)
    colorScheme: ColorScheme.fromSwatch(
      primarySwatch: Colors.blue,
    ).copyWith(
      secondary: Colors.orange,  // Akzentfarbe
    ),
    
    // Textthema
    textTheme: const TextTheme(
      headlineLarge: TextStyle(fontSize: 32, fontWeight: FontWeight.bold),
      bodyLarge: TextStyle(fontSize: 16),
    ),
    
    // Button-Theme
    elevatedButtonTheme: ElevatedButtonThemeData(
      style: ElevatedButton.styleFrom(
        padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12),
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(8),
        ),
      ),
    ),
    
    // AppBar-Theme
    appBarTheme: const AppBarTheme(
      elevation: 4,
      centerTitle: true,
    ),
  ),
  home: const HomePage(),
)

Lokales Theme (Theme-Widget)

Anwendungsfall: Teilbereiche anders gestalten.

dart
Theme(
  data: Theme.of(context).copyWith(  // Aktuelles Theme kopieren
    primaryColor: Colors.green,         // Nur PrimaryColor ändern
  ),
  child: Container(
    color: Theme.of(context).primaryColor,  // Verwendet lokales Theme
    child: const Text('Lokales Theme'),
  ),
)

11.3 Benutzerdefinierte Schriftarten & Icons

Schriftarten importieren

Schritt 1: Schriftart-Datei hinzufügen

assets/
└── fonts/
    └── SchöneSchrift.ttf

Schritt 2: pubspec.yaml konfigurieren

yaml
flutter:
  fonts:
    - family: SchöneSchrift
      fonts:
        - asset: assets/fonts/SchöneSchrift.ttf

Schritt 3: Schriftart verwenden

dart
Text(
  'Benutzerdefinierte Schrift',
  style: TextStyle(
    fontFamily: 'SchöneSchrift',  // Schriftfamilie
    fontSize: 24,
  ),
)

Globales Theme mit benutzerdefinierter Schrift:

dart
MaterialApp(
  theme: ThemeData(
    fontFamily: 'SchöneSchrift',  // Globale Schrift
  ),
)

Benutzerdefinierte Icons

Methode 1: Icon-Font (ähnlich wie Schriftarten)

  1. Generieren Sie eine Icon-Font (z.B. mit https://www.fluttericon.com/)
  2. Fügen Sie die generierte .ttf-Datei zu assets/fonts/ hinzu
  3. Konfigurieren Sie pubspec.yaml:
yaml
flutter:
  fonts:
    - family: MeineIcons
      fonts:
        - asset: assets/fonts/MeineIcons.ttf
  1. Definieren Sie Icons:
dart
class MeineIcons {
  MeineIcons._();
  
  static const _kFontFam = 'MeineIcons';
  
  static const IconData haus = IconData(0xe800, fontFamily: _kFontFam);
  static const IconData einstellungen = IconData(0xe801, fontFamily: _kFontFam);
}
  1. Verwenden Sie die Icons:
dart
Icon(MeineIcons.haus)

Methode 2: Bild-Icons (einfacher)

dart
Image.asset(
  'assets/icons/haus.png',
  width: 24,
  height: 24,
)

11.4 Praxisbeispiel: Globales Theme konfigurieren & Theme-Umschaltung

Schritt 1: Theme-Provider erstellen (mit provider)

dart
import 'package:flutter/material.dart';

class ThemeProvider extends ChangeNotifier {
  bool _isDarkMode = false;
  
  bool get isDarkMode => _isDarkMode;
  
  ThemeData get themeData => _isDarkMode ? _buildDarkTheme() : _buildLightTheme();
  
  ThemeData _buildLightTheme() {
    return ThemeData(
      primarySwatch: Colors.blue,
      brightness: Brightness.light,
      appBarTheme: const AppBarTheme(
        elevation: 4,
        centerTitle: true,
      ),
      elevatedButtonTheme: ElevatedButtonThemeData(
        style: ElevatedButton.styleFrom(
          padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12),
        ),
      ),
    );
  }
  
  ThemeData _buildDarkTheme() {
    return ThemeData(
      primarySwatch: Colors.blue,
      brightness: Brightness.dark,
      scaffoldBackgroundColor: Colors.grey[900],
      appBarTheme: AppBarTheme(
        elevation: 4,
        centerTitle: true,
        backgroundColor: Colors.grey[850],
      ),
    );
  }
  
  void toggleTheme() {
    _isDarkMode = !_isDarkMode;
    notifyListeners();
  }
}

Schritt 2: In main.dart bereitstellen

dart
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'theme_provider.dart';

void main() {
  runApp(
    ChangeNotifierProvider(
      create: (context) => ThemeProvider(),
      child: const MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    final themeProvider = Provider.of<ThemeProvider>(context);
    
    return MaterialApp(
      theme: themeProvider.themeData,
      home: const HomePage(),
    );
  }
}

Schritt 3: In UI verwenden (Theme umschalten)

dart
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'theme_provider.dart';

class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    final themeProvider = Provider.of<ThemeProvider>(context, listen: false);
    
    return Scaffold(
      appBar: AppBar(
        title: const Text('Theme-Beispiel'),
        actions: <Widget>[
          IconButton(
            icon: const Icon(Icons.brightness_6),
            onPressed: () {
              themeProvider.toggleTheme();  // Theme umschalten
            },
          ),
        ],
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            // Text mit globalem Text-Theme
            Text(
              'Flutter Theme',
              style: Theme.of(context).textTheme.headlineLarge,
            ),
            const SizedBox(height: 20),
            
            // Button mit globalem Button-Theme
            ElevatedButton(
              onPressed: () {},
              child: const Text('Button'),
            ),
            const SizedBox(height: 20),
            
            // Container mit Theme-Farbe
            Container(
              width: 100,
              height: 100,
              color: Theme.of(context).primaryColor,
              child: const Center(
                child: Text(
                  'Farbe',
                  style: TextStyle(color: Colors.white),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

Zusammenfassung

In diesem Kapitel haben Sie:

  • TextStyle für Textstilierung gelernt
  • BoxDecoration für Container-Stilierung gelernt
  • ✅ Globales Theme (MaterialApp.theme) konfiguriert
  • ✅ Lokales Theme (Theme-Widget) verwendet
  • ✅ Benutzerdefinierte Schriftarten importiert und verwendet
  • ✅ Benutzerdefinierte Icons erstellt und verwendet
  • ✅ Ein Praxisbeispiel (Theme-Umschaltung) implementiert

Nächstes Kapitel: Wir werden fortgeschrittene Widgets lernen (ListView, GridView, Dialog, etc.).


Übungsaufgaben:

  1. Erstellen Sie ein globales Theme mit benutzerdefinierter Schriftart
  2. Implementieren Sie eine Theme-Umschaltung (hell/dunkel) mit provider
  3. Verwenden Sie BoxDecoration, um schöne Cards mit Schatten und Farbverlauf zu erstellen
  4. Importieren Sie benutzerdefinierte Icons und verwenden Sie diese in Ihrer App
  5. Erstellen Sie ein lokales Theme für einen bestimmten Bildschirmbereich

Häufige Fehler:

  • pubspec.yaml nach Hinzufügen von Schriftarten/Icons nicht neu laden → flutter pub get ausführen
  • Theme.of(context) in StatelessWidget ohne listen: false verwenden → Unnötige Rebuilds
  • BoxDecoration und color gleichzeitig in Container verwenden → Fehler! (Verwenden Sie decoration: BoxDecoration(color: ...))
  • ❌ Zu komplexe Themes für einfache Apps → Behalten Sie es einfach!

Frei für alle Anfänger