Flutter: Bilder einbinden – Assets und Image.asset
Zuletzt aktualisiert:
7 Min. Lesezeit

Um Bilder in Ihr Flutter-Projekt aufzunehmen, legen Sie sie zunächst in einem Ordner ab und definieren sie anschließend in der Datei pubspec.yaml als Assets. Das klingt einfach, doch eine der häufigsten „Warum funktioniert das nicht?“-Fragen im Unterricht geht auf kleine Fehler in genau diesen beiden Schritten zurück. Dieser Beitrag behandelt die Schritte, die Unterstützung verschiedener Auflösungen, SVG- und Netzwerkbilder und wie Sie diese Fehler aufspüren.
Schritt 1: Bilderordner anlegen
Legen Sie im Wurzelverzeichnis Ihres Flutter-Projekts (auf derselben Ebene wie der Ordner lib) einen Bilderordner an. Sehen Sie die Projektstruktur zum ersten Mal, erklärt der Leitfaden zu den ersten Schritten mit Flutter, wozu die einzelnen Ordner dienen:
my_flutter_app/
├── lib/
├── assets/
│ └── images/
│ ├── logo.png
│ ├── profile.jpg
│ └── banner.png
├── pubspec.yaml
└── ...Hinweis: Üblich sind die Ordnernamen assets, images oder assets/images. Sie können einen beliebigen Namen wählen, im Team erwartet aber jeder die Struktur assets/images/.
Schritt 2: pubspec.yaml konfigurieren
Öffnen Sie pubspec.yaml und ergänzen Sie unter dem Abschnitt flutter: die Asset-Definition; die vollständige Syntax dieses Abschnitts beschreibt Flutters Leitfaden „Adding assets and images“:
Ein einzelnes Bild hinzufügen
flutter:
uses-material-design: true
assets:
- assets/images/logo.pngEinen ganzen Ordner hinzufügen
flutter:
uses-material-design: true
assets:
- assets/images/Endet der Ordnerpfad mit /, werden alle Dateien in diesem Ordner als Assets aufgenommen. Unterordner sind in dieser Angabe nicht enthalten; die einzige Ausnahme sind Auflösungsordner wie 2.0x und 3.0x, die wir weiter unten ansehen.
Mit Unterordnern
flutter:
assets:
- assets/images/
- assets/images/icons/
- assets/images/backgrounds/Beispiel für pubspec.yaml
name: my_app
description: My Flutter application.
environment:
sdk: ^3.9.0
dependencies:
flutter:
sdk: flutter
flutter:
uses-material-design: true
assets:
- assets/images/
- assets/icons/Die Zeile sdk unter environment müssen Sie nicht von Hand schreiben; flutter create füllt sie anhand der installierten Dart-Version aus. Das ^3.9.0 hier entspricht der Dart-Version, die mit Flutter 3.35 ausgeliefert wird.
Schritt 3: Bilder verwenden
Das Widget Image.asset
Image.asset ist einer der Konstruktoren, die in der API-Dokumentation des Image-Widgets aufgeführt sind, und wie die anderen ein ganz normales Widget; Sie können es im Widget-Baum in eine Row, Column oder einen Container setzen:
Image.asset('assets/images/logo.png')Größe festlegen
Image.asset(
'assets/images/logo.png',
width: 200,
height: 200,
)Einpassen mit BoxFit
Image.asset(
'assets/images/banner.png',
width: double.infinity,
height: 200,
fit: BoxFit.cover, // Fläche ausfüllen
)BoxFit-Werte:
cover: Füllt die Fläche vollständig und schneidet Überstehendes abcontain: Das ganze Bild ist sichtbar; es kann Leerraum bleibenfill: Füllt die Fläche; das Seitenverhältnis kann verzerrt werdenfitWidth: Passt an die Breite anfitHeight: Passt an die Höhe annone: Zeigt das Bild in OriginalgrößescaleDown: Verhält sich wiecontain, vergrößert das Bild aber nie
Praktische Beispiele
Beispiel 1: Ein Logo anzeigen
class LogoWidget extends StatelessWidget {
const LogoWidget({super.key});
@override
Widget build(BuildContext context) {
return Center(
child: Image.asset(
'assets/images/logo.png',
width: 150,
height: 150,
),
);
}
}Beispiel 2: Profilbild
const CircleAvatar(
radius: 50,
backgroundImage: AssetImage('assets/images/profile.jpg'),
)CircleAvatar erwartet einen ImageProvider und kein Widget; deshalb steht hier AssetImage statt Image.asset.
Beispiel 3: Bannerbild
SizedBox(
width: double.infinity,
height: 200,
child: Image.asset(
'assets/images/banner.png',
fit: BoxFit.cover,
),
)Brauchen Sie nur eine Größe, ist SizedBox statt Container leichter und macht die Absicht klarer.
Beispiel 4: Symbolbild
Row(
children: [
Image.asset(
'assets/images/icons/star.png',
width: 24,
height: 24,
),
const SizedBox(width: 8),
const Text('Meine Favoriten'),
],
)Die SizedBox, die den Abstand zwischen Symbol und Text schafft, ist für solche kleinen Zeilen das praktischste Werkzeug.
Beispiel 5: Hintergrundbild
Container(
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/images/background.jpg'),
fit: BoxFit.cover,
),
),
child: const Center(
child: Text(
'Willkommen',
style: TextStyle(
color: Colors.white,
fontSize: 32,
fontWeight: FontWeight.bold,
),
),
),
)Müssen Sie mehrere Elemente frei über dem Bild platzieren, sind Stack und Positioned der flexiblere Weg.
Bilder für verschiedene Bildschirmdichten
Für unterschiedliche Bildschirmdichten können Sie Bilder in verschiedenen Auflösungen bereitstellen:
Ordnerstruktur
assets/
└── images/
├── logo.png (1x, Hauptdatei)
├── 1.5x/
│ └── logo.png (1.5x)
├── 2.0x/
│ └── logo.png (2x)
├── 3.0x/
│ └── logo.png (3x)
└── 4.0x/
└── logo.png (4x)Die Datei trägt in jedem Ordner denselben Namen; nur die Pixelmaße unterscheiden sich. Ist logo.png zum Beispiel 100x100 Pixel groß, sollte 2.0x/logo.png 200x200 und 3.0x/logo.png 300x300 Pixel haben.
pubspec.yaml
flutter:
assets:
- assets/images/logo.pngHinweis: Flutter nimmt die Varianten in den Ordnern 1.5x, 2.0x, 3.0x und 4.0x automatisch zusammen mit der Hauptdatei auf; Sie müssen sie nicht einzeln angeben.
Verwendung
Image.asset('assets/images/logo.png')Flutter wählt automatisch die Variante, die der devicePixelRatio des Geräts am nächsten liegt. Im Code schreiben Sie immer den Pfad der Hauptdatei. Soll dasselbe Bild zwischen zwei Seiten wachsend hinüberfliegen, genügt es, Image.asset in einen Hero zu packen; Details finden Sie im Beitrag über Hero-Animationen.
Tipps zur Benennung von Bildern
Schreiben Sie die Auflösung nicht in den Dateinamen; Namen wie logo_low.png und logo_high.png umgehen Flutters automatische Auswahl und zwingen Sie, im Code zu entscheiden, wann welche Datei verwendet wird. Nutzen Sie für die Auflösung stattdessen die Ordner 2.0x und 3.0x von oben.
Diese Regeln für Dateinamen erleichtern die Arbeit:
onboarding_step1.png // Kleinbuchstaben, Wörter mit Unterstrich getrennt
icon_cart_24.png // bei Symbolen in mehreren Größen die Größe ans Ende
bg_login.jpg // Präfix nach Art (bg_, icon_, img_)Vermeiden Sie Leerzeichen, Umlaute und Großbuchstaben. Manche Dateisysteme unterscheiden Groß- und Kleinschreibung; ein Logo.PNG, das auf Ihrem Rechner funktioniert, wird in einer anderen Umgebung womöglich nicht gefunden.
Pfade an einer Stelle sammeln
Wiederholen sich Bildpfade als Strings überall im Code, fällt ein Tippfehler erst zur Laufzeit auf. Die Pfade als Konstanten an einer Stelle zu halten, senkt dieses Risiko:
abstract final class AppImages {
static const logo = 'assets/images/logo.png';
static const profile = 'assets/images/profile.jpg';
static const banner = 'assets/images/banner.png';
}
// Verwendung
Image.asset(AppImages.logo)abstract final class ist eine Schreibweise aus Dart 3: Die Klasse lässt sich weder instanziieren noch von außen erweitern, es ist also klar, dass sie nur Konstanten gruppiert.
Lade- und Fehlerzustände
Sanftes Einblenden (frameBuilder)
Image.asset(
'assets/images/logo.png',
frameBuilder: (context, child, frame, wasSynchronouslyLoaded) {
if (wasSynchronouslyLoaded) {
return child;
}
return AnimatedOpacity(
opacity: frame == null ? 0 : 1,
duration: const Duration(milliseconds: 300),
curve: Curves.easeOut,
child: child,
);
},
)frame ist null, bis das erste Frame dekodiert ist; dieses Beispiel hält das Bild bis dahin unsichtbar und blendet es danach sanft ein.
Fehlerfall
Image.asset(
'assets/images/logo.png',
errorBuilder: (context, error, stackTrace) {
return Container(
color: Colors.grey.shade300,
child: const Center(
child: Icon(Icons.error, color: Colors.red),
),
);
},
)errorBuilder zeigt statt des roten Fehlerbildschirms ein Widget Ihrer Wahl, wenn die Datei nicht gefunden oder nicht dekodiert werden kann. Bei Assets deutet das meist auf einen Konfigurationsfehler hin; prüfen Sie vor dem Verstecken des Fehlers den Abschnitt „Häufige Fehler“ weiter unten.
Image.network und Image.asset
Image.asset (lokales Bild)
Image.asset('assets/images/logo.png')- Ist im App-Paket enthalten
- Braucht keine Internetverbindung
- Lädt schnell
- Vergrößert die App
Image.network (Bild aus dem Internet)
Image.network('https://example.com/image.png')- Wird zur Laufzeit aus dem Internet geladen
- Braucht eine Internetverbindung
- Kann je nach Verbindung verzögert erscheinen
- Vergrößert die App nicht
- Flutter hält heruntergeladene Bilder nur im Speicher (
ImageCache); nach dem Schließen der App werden sie erneut geladen. Für einen Cache auf der Festplatte verwenden Sie das Paketcached_network_imageweiter unten.
Sanftes Laden mit FadeInImage
Um einen lokalen Platzhalter zu zeigen, während ein Bild aus dem Netz lädt:
FadeInImage.assetNetwork(
placeholder: 'assets/images/placeholder.png',
image: 'https://example.com/image.png',
fit: BoxFit.cover,
)Dasselbe erreichen Sie mit ImageProviders:
FadeInImage(
placeholder: const AssetImage('assets/images/placeholder.png'),
image: const NetworkImage('https://example.com/image.png'),
fit: BoxFit.cover,
)Da der Platzhalter ein Asset ist, erscheint er sofort; trifft das Netzwerkbild ein, ersetzt es den Platzhalter mit einem weichen Übergang.
SVG-Bilder
Flutters Image-Widget kann kein SVG zeichnen; dafür brauchen Sie das Paket flutter_svg. Fügen Sie es im Terminal hinzu:
flutter pub add flutter_svgDer Befehl trägt die aktuelle Version des Pakets selbst in den Abschnitt dependencies von pubspec.yaml ein.
Verwendung
import 'package:flutter_svg/flutter_svg.dart';
SvgPicture.asset(
'assets/images/logo.svg',
width: 100,
height: 100,
semanticsLabel: 'App-Logo',
)Auch die SVG-Datei muss in pubspec.yaml als Asset definiert sein. Um die Farbe zu ändern, verwenden Sie colorFilter: const ColorFilter.mode(Colors.orange, BlendMode.srcIn).
Cached Network Image
Das Paket cached_network_image speichert Netzwerkbilder auf der Festplatte zwischen:
flutter pub add cached_network_imageVerwendung
import 'package:cached_network_image/cached_network_image.dart';
CachedNetworkImage(
imageUrl: 'https://example.com/image.png',
placeholder: (context, url) => const CircularProgressIndicator(),
errorWidget: (context, url, error) => const Icon(Icons.error),
)Ist ein Bild einmal heruntergeladen, wird es auf dem Gerät gespeichert und bei späteren Starts ohne Netzzugriff angezeigt.
Häufige Fehler
1. Einrückung in pubspec.yaml
# ❌ FALSCH
flutter:
uses-material-design: true
assets:
- assets/images/
# ✅ RICHTIG
flutter:
uses-material-design: true
assets:
- assets/images/In YAML hat die Einrückung Bedeutung. Die Zeile assets: muss unter flutter: um zwei Leerzeichen eingerückt sein; verwenden Sie keine Tabulatoren.
2. Falscher Pfad
// ❌ FALSCH
Image.asset('images/logo.png') // 'assets/' fehlt
// ✅ RICHTIG
Image.asset('assets/images/logo.png')Der Pfad im Code muss genau so beginnen wie der Pfad in pubspec.yaml.
3. Groß- und Kleinschreibung im Dateinamen
// Heißt die Datei logo.PNG:
Image.asset('assets/images/logo.png') // Wird in manchen Umgebungen nicht gefundenIhr Dateisystem kann Groß- und Kleinschreibung unterscheiden; gleichen Sie den Pfad im Code Buchstabe für Buchstabe mit dem Dateinamen ab.
4. Einen Unterordner nicht angeben
Die Angabe assets/images/ umfasst nicht die Dateien in assets/images/icons/. Fügen Sie jeden Unterordner als eigene Zeile hinzu.
5. Das Hot-Reload-Problem
Bei Änderungen an pubspec.yaml:
- Hot Reload reicht nicht
- Führen Sie einen Hot Restart aus (die 🔄-Schaltfläche)
- Sehen Sie weiterhin „Unable to load asset“, beenden Sie die App vollständig und starten Sie sie neu
Zusammenfassung
Bilder in Flutter hinzufügen:
- Ordner anlegen:
assets/images/ - Bilder hinzufügen: PNG, JPG, WebP; für SVG zusätzlich
flutter_svg - In pubspec.yaml definieren:
flutter: assets: - assets/images/ - Hot Restart ausführen
- Verwenden:
Image.asset('assets/images/logo.png')
Empfehlungen:
- Für mehrere Auflösungen die Ordner
2.0xund3.0xanlegen - Aussagekräftige Dateinamen in Kleinbuchstaben verwenden
- Bildpfade in einer einzigen Konstantenklasse sammeln
- Für SVG-Bilder
flutter_svgnutzen - Netzwerkbilder mit
cached_network_imageauf der Festplatte zwischenspeichern
Tipps zur Performance:
- Keine Bilder einbinden, die viel größer sind als ihre Anzeigegröße
- WebP liefert meist kleinere Dateien als PNG und JPG
- Zeigen Sie ein großes Bild auf kleiner Fläche, geben Sie
cacheWidthodercacheHeightan, damit es im Speicher kleiner dekodiert wird:Image.asset('assets/images/banner.png', cacheWidth: 600) - Für lange Bilderlisten
ListView.builderverwenden; es werden nur die sichtbaren Elemente aufgebaut - Ungenutzte Bilder aus dem Projekt löschen
Bilder sind ein wichtiger Teil der visuellen Identität einer Flutter-App. In der richtigen Größe, an der richtigen Stelle und im richtigen Format lassen sie Ihre App schnell und sorgfältig gemacht wirken. Das App-Symbol selbst ist dagegen kein Asset, sondern eine Plattformressource; darum geht es gesondert im Beitrag zum Erstellen eines App-Icons.
Häufig gestellte Fragen
Ich habe es in pubspec.yaml eingetragen, bekomme aber „Unable to load asset“ – warum?
Drei Verdächtige gibt es: Die Zeile assets: muss unter flutter: um zwei Leerzeichen eingerückt sein, der Pfad im Code muss vollständig sein wie assets/images/logo.png, und nach einer Änderung an pubspec ist ein Hot Restart nötig. Denken Sie auch daran, dass Unterordner einzeln aufgeführt werden müssen.
Kann ich Bilder statt in assets im Ordner lib ablegen?
Technisch ja, und Sie müssen sie trotzdem in pubspec.yaml deklarieren. Aber lib ist für Code gedacht; Bilder unter assets/ im Projektwurzelverzeichnis zu halten, sorgt für Ordnung und entspricht der Struktur, die Ihre Teamkollegen erwarten.
Die Bilder machen meine App zu groß – was tun?
Verwenden Sie WebP statt PNG, verkleinern Sie Bilder auf die Größe, in der sie tatsächlich angezeigt werden, und löschen Sie ungenutzte Dateien. Große, selten angezeigte Bilder über cached_network_image aus dem Netz zu laden, statt sie einzubetten, senkt die Größe ebenfalls deutlich.
Verwandte Artikel
Flutter: Helles und dunkles Theme mit ThemeData
Ein Flutter-Theme mit ThemeData aufbauen: ColorScheme.fromSeed, helles und dunkles Theme, ThemeMode, Theme.of, TextTheme, Komponenten-Themes, ThemeExtension.
Flutter: TextField und TextEditingController verwenden
TextField in Flutter: TextEditingController und dispose, InputDecoration, Tastaturtypen, inputFormatters, Passwortfelder, FocusNode und onChanged im Vergleich.
Flutter: Widgets überlagern mit Stack und Positioned
Stack und Positioned in Flutter: wie ein Stack seine Größe bestimmt, fit, alignment, clipBehavior, Positioned.fill, PositionedDirectional, Badge und Overlays.