CustomPainter — was es ist, paint- und shouldRepaint-Methoden in Flutter

Autor: IT Sectr Veröffentlicht: 2026-07-22 Lesezeit: 10 Min.

CustomPainter ist eine abstrakte Klasse aus dem Flutter SDK, die Entwicklern die vollständige Kontrolle über das Rendern benutzerdefinierter 2D-Grafiken auf der Canvas gibt. Der Entwickler erstellt eine Unterklasse von CustomPainter und implementiert zwei obligatorische Methoden: paint(Canvas, Size) und shouldRepaint(covariant CustomPainter oldDelegate). Laut der Flutter API-Dokumentation (2026) wird CustomPainter zusammen mit dem CustomPaint-Widget verwendet, das das Rendern an das übergebene CustomPainter-Objekt bei jedem Animationsframe oder Zustandswechsel delegiert.

Wichtigste Punkte

  • CustomPainter — abstrakte Flutter-Klasse, die benutzerdefiniertes Rendern auf Canvas über die Methoden paint und shouldRepaint definiert
  • CustomPaint — Widget, das CustomPainter als Parameter painter oder foregroundPainter akzeptiert und das Ergebnis auf dem Bildschirm anzeigt
  • Canvas — Objekt, das Zeichenmethoden bereitstellt (drawLine, drawCircle, drawPath, drawRect, drawArc und andere)
  • shouldRepaint — Optimierungsmethode, die bestimmt, ob das Objekt bei einer Aktualisierung neu gezeichnet werden muss
  • size — Größe des Zeichenbereichs, der vom übergeordneten Widget an paint(Canvas canvas, Size size) übergeben wird

Was ist CustomPainter?

CustomPainter ist eine Basisklasse von Flutter zur Implementierung benutzerdefinierter 2D-Grafiken. Sie ersetzt den Ansatz des Überschreibens von onDraw in Android und bietet ein flexibleres und deklaratives Rendering-Modell. Der Entwickler erstellt eine Unterklasse von CustomPainter, überschreibt die paint-Methode, in der er Canvas und Size erhält, und führt alle Zeichenoperationen auf der Canvas aus. Das CustomPaint-Widget verwaltet den paint-Aufruf und integriert das Ergebnis in den Widget-Baum.

Der Hauptunterschied zwischen CustomPainter und direktem Zeichnen über Canvas ist die Trennung von Rendering-Logik (paint) und Neuzeichnungs-Trigger (shouldRepaint). Das Flutter-System ruft shouldRepaint jedes Mal auf, wenn sich das übergeordnete Widget ändert. Wenn shouldRepaint false zurückgibt, wird paint nicht aufgerufen, was Ressourcen spart. Dieser Mechanismus ähnelt shouldRebuild in RenderObject und ist Teil der Flutter-Architektur mit ihren drei Bäumen (Widget, Element, RenderObject).

CustomPaint ist ein Widget, das die Parameter painter (Hintergrundebene) und foregroundPainter (Vordergrundebene) akzeptiert. Beide Parameter akzeptieren CustomPainter-Objekte. Der Hintergrund-painter wird vor dem untergeordneten Widget von CustomPaint gezeichnet, der foregroundPainter danach. Dies ermöglicht die Verwendung von CustomPaint als Container mit dekorativem Hintergrund oder Überlagerung, ohne die Möglichkeit zu verlieren, normale Widgets darin einzubetten.

Canvas und Paint in Flutter

Canvas ist das zentrale Zeichenobjekt in Flutter, das die grafische Oberfläche kapselt. Es stellt etwa 40 Zeichenmethoden bereit: drawLine, drawCircle, drawRect, drawPath, drawArc, drawImage, drawPicture, drawPoints und andere. Canvas in Flutter entspricht einer ähnlichen Klasse in Android Canvas, ist jedoch an die Dart-Architektur und die Flutter Engine angepasst. Canvas arbeitet in einem Koordinatensystem, in dem der Ursprung (0, 0) die obere linke Ecke ist.

Paint — nicht zu verwechseln mit der paint()-Methode — ist eine Klasse, die den Zeichenstil definiert: Farbe (color), Linienstärke (strokeWidth), Stil (style: fill oder stroke), Deckkraft, Mischmodus (blendMode) und Antialiasing-Maske. Paint wird vor dem Zeichnen konfiguriert und an die Canvas-Methoden übergeben. Wichtig: Paint ist ein veränderbares Objekt, es wird jedoch empfohlen, es einmal zu erstellen und wiederzuverwenden, wobei nur die notwendigen Parameter geändert werden.

Canvas-MethodeZweckParameter
drawCircleKreis zeichnenOffset center, double radius, Paint paint
drawLineLiniensegment zeichnenOffset p1, Offset p2, Paint paint
drawRectRechteck zeichnenRect rect, Paint paint
drawPathBeliebigen Pfad zeichnenPath path, Paint paint
drawArcBogen oder Sektor zeichnenRect rect, double startAngle, double sweepAngle, bool useCenter, Paint paint
drawRRectRechteck mit abgerundeten EckenRRect rrect, Paint paint
drawOvalOval zeichnenRect rect, Paint paint
drawImageBild aus Image zeichnenImage image, Offset p, Paint paint

Canvas-Transformationen

Canvas unterstützt Transformationen des Koordinatensystems: translate(double dx, double dy) verschiebt den Ursprung; rotate(double radians) dreht das System; scale(double sx, double sy) skaliert; skew(double sx, double sy) neigt. Vor einer Transformation wird empfohlen, den Canvas-Zustand über save() zu speichern und nach Abschluss über restore() wiederherzustellen. Dies verhindert die Akkumulation von Transformationen bei nachfolgenden paint-Aufrufen.

Die Methoden paint und shouldRepaint

paint(Canvas canvas, Size size) ist die obligatorische Methode, die die gesamte Zeichenlogik implementiert. Der Parameter canvas ist die grafische Oberfläche zum Zeichnen. Der Parameter size ist die Größe des zum Zeichnen zugewiesenen Bereichs (Breite und Höhe in logischen Pixeln). Canvas ist vorkonfiguriert, sodass der Ursprung (0,0) der oberen linken Ecke des Zeichenbereichs entspricht. Alle Koordinaten werden relativ zu diesem Ursprung angegeben.

shouldRepaint(covariant CustomPainter oldDelegate) ist eine obligatorische Methode, die die Neuzeichnungsfrequenz optimiert. Flutter ruft shouldRepaint bei jeder Aktualisierung des Widget-Baums auf, die CustomPainter betrifft. Wenn die Methode false zurückgibt, gilt das bereits gerenderte Bild als gültig und paint wird nicht aufgerufen. Eine typische Implementierung ist: return oldDelegate.someField != someField — Vergleich der Felder des alten und neuen painters, um die Notwendigkeit einer Neuzeichnung zu bestimmen.

Für animierte oder sich ständig ändernde Bilder (Uhren, Ladeanzeigen, Diagramme) sollte shouldRepaint bei jeder Zustandsänderung true zurückgeben. Wenn das Objekt statisch ist (Logo, Symbol, Hintergrund), gibt shouldRepaint nach der ersten Darstellung false zurück. Flutter speichert das paint-Ergebnis automatisch zwischen und zeichnet nur neu, wenn sich Größe, Deckkraft oder der shouldRepaint-Aufruf ändern.

Beispiel für benutzerdefiniertes Zeichnen mit CustomPainter in Dart

Lassen Sie uns GaugePainter erstellen — eine benutzerdefinierte kreisförmige Anzeige mit animierter Füllung. CustomPainter akzeptiert den aktuellen Wert (Fortschritt von 0,0 bis 1,0) und zeichnet einen Bogen mit einem Farbverlauf. Die shouldRepaint-Methode vergleicht den Fortschrittswert zur Optimierung. CustomPaint wird mit dem size-Parameter in den Widget-Baum eingefügt, um den Zeichenbereich zu begrenzen.

dart
class GaugePainter extends CustomPainter {
    final double progress;
    final Color startColor;
    final Color endColor;

    GaugePainter({
        required this.progress,
        this.startColor = Colors.blue,
        this.endColor = Colors.cyan,
    });

    @override
    void paint(Canvas canvas, Size size) {
        final center = Offset(size.width / 2,
            size.height / 2);
        final radius = center.dx - 12;
        final bgPaint = Paint()
            ..color = Colors.grey.withOpacity(0.3)
            ..style = PaintingStyle.stroke
            ..strokeWidth = 16
            ..strokeCap = StrokeCap.round;

        final progressPaint = Paint()
            ..shader = LinearGradient(
                colors: [startColor, endColor],
            ).createShader(
                Rect.fromCircle(
                    center, radius))
            ..style = PaintingStyle.stroke
            ..strokeWidth = 16
            ..strokeCap = StrokeCap.round;

        canvas.drawCircle(center, radius, bgPaint);
        canvas.drawArc(
            Rect.fromCircle(center, radius),
            -math.pi / 2,
            2 * math.pi * progress,
            false, progressPaint);
    }

    @override
    bool shouldRepaint(
        GaugePainter oldDelegate) {
        return oldDelegate.progress != progress;
    }
}

CustomPainter mit Path für komplexe Formen

Das Beispiel zeichnet ein Wellendiagramm mit Path. Path ermöglicht das Erstellen beliebiger Konturen aus Linien, Bezier-Kurven und Bögen. Nach dem Erstellen der Kontur wird sie mit Farbe gefüllt oder mit einer Linie umrandet. Im Beispiel wird das Diagramm aus einer Reihe von Punkten erstellt, die eine Wellenform simulieren.

dart
class WavePainter extends CustomPainter {
    final List<double> values;

    WavePainter({required this.values});

    @override
    void paint(Canvas canvas, Size size) {
        final path = Path();
        final dx = size.width /
            (values.length - 1);

        path.moveTo(0, size.height);
        for (var i = 0; i < values.length; i++) {
            final x = i * dx;
            final y = size.height *
                (1 - values[i]);
            path.lineTo(x, y);
        }
        path.lineTo(size.width, size.height);
        path.close();

        final fillPaint = Paint()
            ..color = Colors.blue.withOpacity(0.3)
            ..style = PaintingStyle.fill;

        canvas.drawPath(path, fillPaint);
    }

    @override
    bool shouldRepaint(
        WavePainter oldDelegate) {
        return oldDelegate.values != values;
    }
}

ForegroundPainter und backgroundPainter: Unterschied

painter (Hintergrund) wird vor dem untergeordneten Widget von CustomPaint gezeichnet. Wenn CustomPaint ein untergeordnetes Widget (Parameter child) hat, wird der Hintergrund-painter darunter angezeigt. Dies ist geeignet für Dekorationen: Fortschrittsbalken, Hintergrundmuster, Wasserzeichen. foregroundPainter wird nach dem untergeordneten Widget gezeichnet, also darüber. Es wird für Überlagerungen verwendet: Hervorhebungen, Masken, Messlineale, Anmerkungen.

Der Unterschied zwischen painter und foregroundPainter ist entscheidend für die Z-Reihenfolge. Wenn Sie etwas hinter dem Inhalt zeichnen müssen — verwenden Sie painter. Wenn über dem Inhalt — foregroundPainter. In einigen Fällen können Sie beide painter gleichzeitig verwenden: Hintergrund über painter, Überlagerungsbeschriftung über foregroundPainter. Dies ermöglicht die Trennung der Logik verschiedener grafischer Ebenen in zwei separate CustomPainter-Klassen.

Der Parameter size in der paint-Methode ist für beide painter gleich und wird durch die Größe des für CustomPaint zugewiesenen Bereichs bestimmt. Die Größe kann explizit über den size-Parameter in CustomPaint oder implizit über den übergeordneten Container festgelegt werden. Wenn die Größe Size.zero ist, wird paint nicht aufgerufen — Flutter überspringt das Rendern für einen Bereich der Größe Null. Dieses Verhalten sollte beim Animieren des Erscheinens von Elementen berücksichtigt werden.

Leistungsoptimierung von CustomPainter

Die Hauptregel für die Leistung von CustomPainter ist, keine Objekte innerhalb der paint-Methode zu erstellen. Canvas, Paint, Path, Rect, Offset und andere Zeichenobjekte sollten im Konstruktor von CustomPainter erstellt oder zwischengespeichert werden. Das Erstellen von Objekten innerhalb von paint führt zu Allokationen bei jedem Frame, was bei 60 Bildern pro Sekunde häufige Garbage Collection und Animationsruckeln (Jank) verursacht.

Path-Zwischenspeicherung beschleunigt das Rendern wiederholter komplexer Pfade erheblich. Wenn sich der Pfad zwischen Frames nicht ändert (z. B. ein Hintergrundraster), erstellen Sie den Path einmal und verwenden Sie ihn mehrfach wieder. RepaintBoundary ist ein Wrapper-Widget, das das Neuzeichnen von CustomPainter verhindert, wenn sich der übergeordnete Widget-Baum ändert. Wenn CustomPainter statisch ist, umschließen Sie es zur Isolierung mit einem RepaintBoundary.

Für animierte CustomPainter mit häufigen Neuzeichnungen verwenden Sie Ticker oder AnimationController mit shouldRepaint, das bei jeder Änderung des animierten Werts true zurückgibt. Optimal ist es, das animierte Feld in shouldRepaint zu vergleichen, anstatt unnötig bei jedem Frame neu zu zeichnen. Rect-Zwischenspeicherung für komplexe Farbverläufe: Wenn sich die Farben des Verlaufs nicht ändern, können Sie den Shader über Paint.shader zwischenspeichern.

Häufig gestellte Fragen

Was ist der Unterschied zwischen CustomPainter und Canvas in Flutter?

CustomPainter ist eine Vertragsklasse, die definiert, was und wie auf Canvas gezeichnet wird. Canvas ist das Zeichenobjekt selbst, das Methoden bereitstellt (drawCircle, drawLine usw.). CustomPainter erhält Canvas über die paint-Methode und steuert dessen Verwendung. Eine Canvas kann zu verschiedenen Zeiten von verschiedenen CustomPainter-Objekten verwendet werden.

Kann CustomPainter ohne CustomPaint verwendet werden?

Nein, CustomPainter ergibt ohne CustomPaint keinen Sinn. CustomPaint ist das Widget, das die paint-Methode von CustomPainter aufruft und das Ergebnis auf dem Bildschirm anzeigt. Ohne CustomPaint wird Canvas nicht erstellt und paint nicht ausgeführt. Sie können jedoch ein eigenes RenderObject mit Canvas implementieren, aber dies ist ein Ansatz auf niedrigerer Ebene.

Wie animiert man einen CustomPainter?

Verwenden Sie einen AnimationController mit einem Ticker, wobei Sie den animierten Wert über die Konstruktorparameter an CustomPainter übergeben. Wenn sich der Wert ändert, rufen Sie setState() in dem Widget auf, das CustomPaint enthält, was den shouldRepaint-Aufruf auslöst. Wenn shouldRepaint true zurückgibt, ruft das System paint für den neuen Animationsframe auf.

Warum wird CustomPainter nicht aktualisiert, wenn sich Daten ändern?

Die Ursache ist fast immer shouldRepaint, das false zurückgibt. Überprüfen Sie, ob die oldDelegate-Felder korrekt mit den neuen Werten verglichen werden. Wenn ein veränderbares Objekt verwendet wird, erkennt shouldRepaint möglicherweise keine Änderungen, da die Objektreferenz gleich bleibt. Verwenden Sie == oder unveränderliche Objekte für einen korrekten Vergleich.

Kann CustomPainter für Animationen in ReorderableListView verwendet werden?

Ja, CustomPainter wird zum Rendern benutzerdefinierter Dekorationen in komplexen Listen verwendet. Beachten Sie jedoch, dass beim Neuanordnen von Elementen der RepaintBoundary innerhalb der ListView das Rendern jedes Elements zwischenspeichert. CustomPainter sollte leicht sein und keine schweren Operationen in paint enthalten, um die Ziehanimation nicht zu verlangsamen.

Zusammenfassung

  • CustomPainter — abstrakte Flutter-Klasse für benutzerdefiniertes 2D-Rendering mit den Methoden paint und shouldRepaint
  • CustomPaint — Widget, das painter (Hintergrund) und foregroundPainter (Vordergrund) zur Anzeige von Grafiken akzeptiert
  • Canvas — Objekt mit Zeichenmethoden: drawLine, drawCircle, drawPath, drawRect, drawArc und andere
  • Paint — Klasse, die den Zeichenstil definiert: Farbe, Stärke, Stil (fill/stroke), Deckkraft und Mischmodus
  • shouldRepaint — Optimierungsmethode, die nur dann true zurückgibt, wenn sich die das Rendern beeinflussenden Felder ändern
  • Das Erstellen von Objekten innerhalb von paint ist verboten — alle Paint, Path, Rect müssen für 60 fps zwischengespeichert werden
  • RepaintBoundary — Widget zur Isolierung von CustomPainter vor Neuzeichnungen des übergeordneten Widget-Baums

Wir entwickeln eine mobile Applikation schlüsselfertig

IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.

Projekt besprechen

Lesen Sie auch