Appearance
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.ttfSchritt 2: pubspec.yaml konfigurieren
yaml
flutter:
fonts:
- family: SchöneSchrift
fonts:
- asset: assets/fonts/SchöneSchrift.ttfSchritt 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)
- Generieren Sie eine Icon-Font (z.B. mit https://www.fluttericon.com/)
- Fügen Sie die generierte
.ttf-Datei zuassets/fonts/hinzu - Konfigurieren Sie
pubspec.yaml:
yaml
flutter:
fonts:
- family: MeineIcons
fonts:
- asset: assets/fonts/MeineIcons.ttf- 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);
}- 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:
- ✅
TextStylefür Textstilierung gelernt - ✅
BoxDecorationfü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:
- Erstellen Sie ein globales Theme mit benutzerdefinierter Schriftart
- Implementieren Sie eine Theme-Umschaltung (hell/dunkel) mit
provider - Verwenden Sie
BoxDecoration, um schöne Cards mit Schatten und Farbverlauf zu erstellen - Importieren Sie benutzerdefinierte Icons und verwenden Sie diese in Ihrer App
- Erstellen Sie ein lokales Theme für einen bestimmten Bildschirmbereich
Häufige Fehler:
- ❌
pubspec.yamlnach Hinzufügen von Schriftarten/Icons nicht neu laden →flutter pub getausführen - ❌
Theme.of(context)inStatelessWidgetohnelisten: falseverwenden → Unnötige Rebuilds - ❌
BoxDecorationundcolorgleichzeitig inContainerverwenden → Fehler! (Verwenden Siedecoration: BoxDecoration(color: ...)) - ❌ Zu komplexe Themes für einfache Apps → Behalten Sie es einfach!
