Appearance
Anhang: Flutter Kernwissen
1. Kern-Widgets (nach Verwendungshäufigkeit, mit Beispielen)
Häufig verwendete Widgets
| Widget | Verwendung | Beispiel |
|---|---|---|
| Text | Textanzeige | Text('Hallo') |
| Image | Bilder | Image.network('url') |
| ElevatedButton | Button | ElevatedButton(onPressed: () {}, child: Text('Klick')) |
| TextField | Eingabefeld | TextField(controller: _controller) |
| Container | Container | Container(padding: EdgeInsets.all(16)) |
| Row | Horizontales Layout | Row(children: [Widget1(), Widget2()]) |
| Column | Vertikales Layout | Column(children: [Widget1(), Widget2()]) |
| Stack | Stapel-Layout | Stack(children: [Widget1(), Widget2()]) |
| ListView | Liste | ListView.builder(itemCount: 10, itemBuilder: (context, index) {...}) |
| GridView | Grid | GridView.count(crossAxisCount: 2, children: [...]) |
| Card | Karte | Card(child: ListTile(title: Text('Titel'))) |
| Scaffold | Seitengerüst | Scaffold(appBar: AppBar(title: Text('Titel'))) |
| AppBar | Obere Leiste | AppBar(title: Text('Titel'), actions: [IconButton(...)]) |
| Icon | Icon | Icon(Icons.home) |
| IconButton | Icon-Button | IconButton(icon: Icon(Icons.home), onPressed: () {}) |
| CircleAvatar | Rundes Bild | CircleAvatar(backgroundImage: NetworkImage('url')) |
| Divider | Trennlinie | Divider() |
| SizedBox | Größen-Box | SizedBox(height: 20) |
| Spacer | Abstand füllen | Spacer() |
| Expanded | Platz füllen | Expanded(child: Text('Text')) |
| Flexible | Flexibler Platz | Flexible(child: Text('Text')) |
| Positioned | Positionierung | Positioned(top: 10, left: 10, child: Widget()) |
| RefreshIndicator | Pull-to-Refresh | RefreshIndicator(onRefresh: _aktualisieren, child: ListView(...)) |
| SingleChildScrollView | Scrollbares Widget | SingleChildScrollView(child: Column(...)) |
| AlertDialog | Dialog | AlertDialog(title: Text('Titel'), content: Text('Inhalt')) |
| showModalBottomSheet | Bottom-Sheet | showModalBottomSheet(context: context, builder: (context) => Widget()) |
2. Layout-Widgets Verwendungsfälle (Row, Column, Stack, etc.)
Row (Horizontales Layout)
Verwendungsfälle:
- ✅ Buttons nebeneinander
- ✅ Icon + Text nebeneinander
- ✅ Bild + Beschreibung nebeneinander
Beispiel:
dart
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Icon(Icons.home),
Text('Startseite'),
ElevatedButton(onPressed: () {}, child: Text('Go')),
],
)Column (Vertikales Layout)
Verwendungsfälle:
- ✅ Formularfelder untereinander
- ✅ Listenelemente
- ✅ Seiteninhalt (von oben nach unten)
Beispiel:
dart
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Text('Zeile 1'),
Text('Zeile 2'),
ElevatedButton(onPressed: () {}, child: Text('Button')),
],
)Stack (Stapel-Layout)
Verwendungsfälle:
- ✅ Bild mit Text-Overlay
- ✅ Badge auf Icon
- ✅ Floating Action Button positionieren
Beispiel:
dart
Stack(
children: <Widget>[
Container(width: 300, height: 300, color: Colors.grey.shade200),
Positioned(
top: 10,
left: 10,
child: Icon(Icons.home, size: 30),
),
],
)ListView (Liste)
Verwendungsfälle:
- ✅ Neuigkeiten-Liste
- ✅ Kontaktliste
- ✅ Produktliste
Beispiel:
dart
ListView.builder(
itemCount: 10,
itemBuilder: (context, index) {
return ListTile(
leading: Icon(Icons.person),
title: Text('Element $index'),
);
},
)GridView (Grid)
Verwendungsfälle:
- ✅ Produkt-Grid
- ✅ Bild-Galerie
- ✅ Kategorie-Grid
Beispiel:
dart
GridView.count(
crossAxisCount: 2,
children: <Widget>[
Card(child: Text('Element 1')),
Card(child: Text('Element 2')),
],
)3. State Management Methoden (setState, Provider, GetX)
setState() (Einfachste Methode)
Verwendungsfall:
- ✅ Einfache Zustände (lokaler Zustand)
- ✅ Wenige Widgets betroffen
- ✅ Keine komplexe Zustandsverwaltung notwendig
Beispiel:
dart
class CounterPage extends StatefulWidget {
const CounterPage({super.key});
@override
State<CounterPage> createState() => _CounterPageState();
}
class _CounterPageState extends State<CounterPage> {
int _zaehler = 0;
void _erhoehen() {
setState(() {
_zaehler++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('$_zaehler', style: const TextStyle(fontSize: 48)),
ElevatedButton(
onPressed: _erhoehen,
child: const Text('Erhöhen'),
),
],
),
),
);
}
}Provider (Offiziell empfohlen)
Verwendungsfall:
- ✅ Cross-Widget Zustandsverwaltung
- ✅ Mittlere Komplexität
- ✅ Gute Dokumentation
Beispiel:
Schritt 1: Zustands-Klasse definieren
dart
class CounterProvider extends ChangeNotifier {
int _zaehler = 0;
int get zaehler => _zaehler;
void erhoehen() {
_zaehler++;
notifyListeners();
}
}Schritt 2: Zustand bereitstellen
dart
void main() {
runApp(
ChangeNotifierProvider(
create: (context) => CounterProvider(),
child: const MyApp(),
),
);
}Schritt 3: Zustand verbrauchen
dart
class CounterPage extends StatelessWidget {
const CounterPage({super.key});
@override
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Consumer<CounterProvider>(
builder: (context, provider, child) {
return Text(
'${provider.zaehler}',
style: const TextStyle(fontSize: 48),
);
},
),
ElevatedButton(
onPressed: () {
Provider.of<CounterProvider>(context, listen: false).erhoehen();
},
child: const Text('Erhöhen'),
),
],
),
);
}
}GetX (Einfach & beliebt)
Verwendungsfall:
- ✅ Schnelle Entwicklung
- ✅ Wenig Code
- ✅ Kombiniert Zustandsverwaltung, Routing, Abhängigkeitsinjektion
Beispiel:
Schritt 1: Controller erstellen
dart
class CounterController extends GetxController {
int zaehler = 0;
void erhoehen() {
zaehler++;
update();
}
}Schritt 2: Controller verwenden
dart
class CounterPage extends StatelessWidget {
final controller = Get.put(CounterController());
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
children: <Widget>[
GetBuilder<CounterController>(
builder: (c) => Text('${c.zaehler}'),
),
ElevatedButton(
onPressed: controller.erhoehen,
child: const Text('Erhöhen'),
),
],
),
),
);
}
}4. Netzwerkrequest & JSON-Parsing Vorlagen (kopieren & verwenden)
GET-Request (Daten abrufen)
Vorlage:
dart
import 'package:dio/dio.dart';
final dio = Dio();
Future<void> ladeDaten() async {
try {
final response = await dio.get('https://example.com/api');
print('Erfolg! Statuscode: ${response.statusCode}');
print('Daten: ${response.data}');
} catch (e) {
print('Fehler: $e');
}
}POST-Request (Daten senden)
Vorlage:
dart
import 'package:dio/dio.dart';
final dio = Dio();
Future<void> sendeDaten() async {
try {
final response = await dio.post(
'https://example.com/api',
data: {
'name': 'Max',
'alter': 25,
},
);
print('Erfolg! Statuscode: ${response.statusCode}');
print('Antwort: ${response.data}');
} catch (e) {
print('Fehler: $e');
}
}JSON-Parsing (Manuell)
Vorlage:
dart
// Angenommen, API gibt JSON zurück:
// {
// "id": 1,
// "title": "BeispielTitel",
// "body": "BeispielInhalt"
// }
final response = await dio.get('https://example.com/api');
// Manuelle Parsing
final data = response.data;
final titel = data['title'];
final inhalt = data['body'];
print('Titel: $titel');
print('Inhalt: $inhalt');JSON-Parsing (Automatisch mit json_serializable)
Schritt 1: Abhängigkeiten installieren
yaml
dependencies:
json_annotation: ^4.8.0
dev_dependencies:
build_runner: ^2.4.0
json_serializable: ^6.7.0Schritt 2: Modellklasse definieren
dart
import 'package:json_annotation/json_annotation.dart';
part 'post_model.g.dart';
@JsonSerializable()
class Post {
final int id;
final String title;
final String body;
Post({
required this.id,
required this.title,
required this.body,
});
factory Post.fromJson(Map<String, dynamic> json) => _$PostFromJson(json);
Map<String, dynamic> toJson() => _$PostToJson(this);
}Schritt 3: Code generieren
bash
flutter pub run build_runner buildSchritt 4: Verwenden
dart
final response = await dio.get('https://example.com/api');
final post = Post.fromJson(response.data);
print('Titel: ${post.title}');
print('Inhalt: ${post.body}');5. Packaging-Konfiguration Vorlagen (Android/iOS, kopieren & verwenden)
Android (APK/AAB erstellen)
Schritt 1: Signierungsschlüssel generieren
bash
keytool -genkey -v -keystore d:\key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias keySchritt 2: key.properties konfigurieren
storePassword=ihr_passwort
keyPassword=ihr_passwort
keyAlias=key
storeFile=d:/key.jksSchritt 3: build.gradle konfigurieren
gradle
def keystoreProperties = new Properties()
def keystorePropertiesFile = rootProject.file('key.properties')
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}
android {
...
signingConfigs {
release {
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
storePassword keystoreProperties['storePassword']
}
}
buildTypes {
release {
signingConfig signingConfigs.release
}
}
}Schritt 4: APK/AAB erstellen
bash
flutter build apk --release
flutter build appbundle --releaseiOS (IPA erstellen - nur auf Mac)
Schritt 1: Xcode konfigurieren
- Öffnen Sie
ios/Runner.xcworkspacein Xcode - Runner → Signing & Capabilities:
- Team auswählen (Apple ID hinzufügen)
- Bundle Identifier festlegen (z.B.
com.beispiel.meineapp)
Schritt 2: IPA erstellen
- Gerät auswählen: "Any iOS Device (arm64)"
- Product → Archive
- Nach Abschluss: "Distribute App"
- "App Store Connect" wählen
- Anweisungen folgen
6. Häufige Fehler-Schnellübersicht (schnelle Fehlersuche)
Fehler 1: Layout-Überlauf (Renderflex overflowed)
Fehlermeldung:
A RenderFlex overflowed by 100 pixels on the right.Lösungen:
Expandedverwenden
dart
Row(
children: <Widget>[
Expanded(child: Text('Sehr langer Text der überläuft...')),
Icon(Icons.more_vert),
],
)SingleChildScrollViewverwenden
dart
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(...),
)Flexibleverwenden
dart
Row(
children: <Widget>[
Flexible(child: Text('Langer Text...')),
Icon(Icons.more_vert),
],
)Fehler 2: Zustandsverwaltungsfehler
Fehler: setState() vergessen.
Lösung:
dart
void _erhoehen() {
setState(() {
_zaehler++; // UI wird aktualisiert!
});
}Fehler 3: Netzwerkrequest-Fehler
Fehler: await vergessen.
Lösung:
dart
Future<void> ladeDaten() async {
final response = await dio.get('https://example.com'); // await verwenden!
print(response.data);
}Fehler 4: JSON-Parsing fehlgeschlagen
Fehler: JSON-Struktur stimmt nicht mit Dart-Klasse überein.
Lösung:
- Überprüfen Sie die JSON-Struktur der API-Antwort
- Stellen Sie sicher, dass Ihre Dart-Klasse mit dem JSON übereinstimmt
- Verwenden Sie QuickType oder json_serializable
Fehler 5: Packaging fehlgeschlagen
Fehler: Signierungskonfiguration falsch.
Lösung:
- Stellen Sie sicher, dass
android/key.propertiesexistiert - Pfad in
build.gradlekorrekt
7. Häufig verwendete Drittanbieter-Plugins (nach Anwendungsfall)
Netzwerk
- dio: ^5.4.0 - Leistungsstarke Netzwerk-Bibliothek
- Link: https://pub.dev/packages/dio
- Verwendung: GET/POST-Requests, Interceptors, Request-Abbruch
Lokale Speicherung
shared_preferences: ^2.2.0 - Key-Value-Speicherung
- Link: https://pub.dev/packages/shared_preferences
- Verwendung: Einfache Datenspeicherung (Einstellungen, Login-Status)
sqflite: ^2.3.0 - Lokale Datenbank
- Link: https://pub.dev/packages/sqflite
- Verwendung: Strukturierte Datenspeicherung (Kontakte, Notizen)
UI-Komponenten
flutter_screenutil: ^5.9.0 - Responsives Design
- Link: https://pub.dev/packages/flutter_screenutil
- Verwendung: Responsives Design für verschiedene Bildschirmgrößen
cached_network_image: ^3.3.0 - Bild-Caching
- Link: https://pub.dev/packages/cached_network_image
- Verwendung: Effizientes Laden und Caching von Netzwerkbildern
State Management
provider: ^6.1.1 - Empfohlen (einfach)
- Link: https://pub.dev/packages/provider
- Verwendung: Einfaches State Management
get: ^4.6.5 - Einfach, beliebt
- Link: https://pub.dev/packages/get
- Verwendung: State Management, Routing, Dependency Injection
Andere
image_picker: ^1.0.4 - Bilder aus Kamera/Galerie auswählen
- Link: https://pub.dev/packages/image_picker
- Verwendung: Bilder aus Kamera oder Galerie auswählen
url_launcher: ^6.1.11 - URLs öffnen (Browser, Telefon, E-Mail)
- Link: https://pub.dev/packages/url_launcher
- Verwendung: URLs öffnen (Browser, Telefon, E-Mail)
Zusammenfassung
In diesem Anhang haben Sie:
- ✅ Kern-Widgets (nach Verwendungshäufigkeit) gelernt
- ✅ Layout-Widgets Verwendungsfälle gelernt
- ✅ State Management Methoden verglichen
- ✅ Netzwerkrequest & JSON-Parsing Vorlagen erhalten
- ✅ Packaging-Konfiguration Vorlagen erhalten
- ✅ Häufige Fehler-Schnellübersicht erhalten
- ✅ Häufig verwendete Drittanbieter-Plugins kennengelernt
Glückwunsch! Sie haben den Flutter-Anfänger-Kurs abgeschlossen! 🎉
Nächste Schritte:
- Üben Sie mit eigenen Projekten
- Erkunden Sie fortgeschrittene Themen (Bloc, GetX, Riverpod)
- Erstellen Sie eine vollständige App und veröffentlichen Sie sie im App Store / Play Store
- Treten Sie der Flutter-Community bei (Stack Overflow, Reddit, Discord)
Viel Erfolg bei Ihrer Flutter-Reise! 🚀
