CustomPainter — mi ez, a paint és shouldRepaint metódusok a Flutter-ben

Szerző: IT Sectr Megjelenés: 2026-07-22 Olvasási idő: 10 perc

CustomPainter — egy absztrakt osztály a Flutter SDK-ból, amely teljes körű vezérlést biztosít a fejlesztőknek az egyedi 2D grafika Canvas-on történő megjelenítéséhez. A fejlesztő létrehozza a CustomPainter alosztályát és implementál két kötelező metódust: paint(Canvas, Size) és shouldRepaint(covariant CustomPainter oldDelegate). A Flutter API Documentation (2026) szerint a CustomPainter a CustomPaint widget-tel együtt használatos, amely a megjelenítést a átadott CustomPainter objektumra delegálja minden animációs képkockánál vagy állapotváltozásnál.

Főbb pontok

  • CustomPainter — Flutter absztrakt osztály, amely egyedi megjelenítést definiál a Canvas-on a paint és shouldRepaint metódusokon keresztül
  • CustomPaint — widget, amely CustomPainter-t fogad painter vagy foregroundPainter paraméterként és megjeleníti az eredményt a képernyőn
  • Canvas — objektum, amely rajzolási metódusokat biztosít (drawLine, drawCircle, drawPath, drawRect, drawArc és mások)
  • shouldRepaint — optimalizációs metódus, amely meghatározza, hogy az objektumot újra kell-e rajzolni frissítéskor
  • size — a rajzolási terület mérete, amely a paint(Canvas canvas, Size size) metódusba kerül a szülő widget-től

Mi az a CustomPainter?

CustomPainter — a Flutter alaposztálya tetszőleges 2D grafika implementálásához. Felváltja az onDraw felülírásának megközelítését Android-ban, rugalmasabb és deklaratívabb megjelenítési modellt biztosítva. A fejlesztő létrehozza a CustomPainter alosztályát, felülírja a paint metódust, ahol megkapja a Canvas-t és Size-t, és végrehajtja az összes rajzolási műveletet a Canvas-on. A CustomPaint widget kezeli a paint meghívását és integrálja az eredményt a widget-fába.

A legfontosabb különbség a CustomPainter és a közvetlen Canvas-on keresztüli rajzolás között — a megjelenítési logika (paint) és az újrarajzolás triggerének (shouldRepaint) szétválasztása. A Flutter rendszer shouldRepaint-et hív minden alkalommal, amikor a szülő widget megváltozik. Ha a shouldRepaint false-t ad vissza, a paint nem kerül meghívásra, ami erőforrásokat takarít meg. Ez a mechanizmus analóg a shouldRebuild-del a RenderObject-ban, és része a Flutter architektúrájának a három fájával (Widget, Element, RenderObject).

CustomPaint — egy widget, amely a painter (háttérréteg) és foregroundPainter (előtérréteg) paramétereket fogadja. Mindkét paraméter CustomPainter objektumokat fogad. A háttér painter a CustomPaint gyermeke előtt rajzol, a foregroundPainter pedig utána. Ez lehetővé teszi a CustomPaint használatát dekoratív háttérrel vagy fedőréteggel rendelkező konténerként, anélkül hogy elveszítené a szokásos widgetek beágyazásának lehetőségét.

Canvas és Paint a Flutter-ben

Canvas — a központi objektum a rajzoláshoz a Flutter-ben, amely a grafikus felületet inkapszulálja. Körülbelül 40 rajzolási metódust biztosít: drawLine, drawCircle, drawRect, drawPath, drawArc, drawImage, drawPicture, drawPoints és mások. A Flutter-ben a Canvas megfelel az Android Canvas analóg osztályának, de a Dart és a Flutter Engine architektúrájához igazították. A Canvas egy koordináta-rendszerben működik, ahol a kezdőpont (0, 0) a bal felső sarok.

Paint — nem összetévesztendő a paint() metódussal — egy osztály, amely meghatározza a rajzolási stílust: szín (color), vonalvastagság (strokeWidth), stílus (style: fill vagy stroke), átlátszóság, keverési mód (blendMode) és simító maszk. A Paint a rajzolás előtt van konfigurálva, és átadásra kerül a Canvas metódusainak. Fontos: A Paint egy változtatható objektum, de ajánlott egyszer létrehozni és újrahasználni, csak a szükséges paramétereket módosítva.

Canvas metódusRendeltetésParaméterek
drawCircleKör rajzolásaOffset center, double radius, Paint paint
drawLineVonal rajzolásaOffset p1, Offset p2, Paint paint
drawRectTéglalap rajzolásaRect rect, Paint paint
drawPathTetszőleges kontúr rajzolásaPath path, Paint paint
drawArcÍv vagy szektor rajzolásaRect rect, double startAngle, double sweepAngle, bool useCenter, Paint paint
drawRRectLekerekített sarkú téglalapRRect rrect, Paint paint
drawOvalOvális rajzolásaRect rect, Paint paint
drawImageKép rajzolása Image-bőlImage image, Offset p, Paint paint

Canvas transzformációk

Canvas támogatja a koordináta-rendszer transzformációit: translate(double dx, double dy) eltolja a koordináták kezdőpontját; rotate(double radians) forgatja a rendszert; scale(double sx, double sy) skáláz; skew(double sx, double sy) ferde. A transzformáció előtt ajánlott a Canvas állapotának mentése a save() segítségével, majd befejezés után visszaállítása a restore() segítségével. Ez megakadályozza a transzformációk felhalmozódását a paint későbbi meghívásaiban.

A paint és shouldRepaint metódusok

paint(Canvas canvas, Size size) — a kötelező metódus, amelyben a teljes rajzolási logika implementálva van. A canvas paraméter — a grafikus felület a rajzoláshoz. A size paraméter — a rajzoláshoz allokált terület mérete (szélesség és magasság logikai pixelekben). A Canvas előre úgy van konfigurálva, hogy a koordináta kezdőpont (0,0) megfeleljen a rajzolási terület bal felső sarkának. Minden koordináta ehhez a kezdőponthoz viszonyítva van meghatározva.

shouldRepaint(covariant CustomPainter oldDelegate) — a kötelező metódus, amely optimalizálja az újrarajzolás gyakoriságát. A Flutter shouldRepaint-et hív a widget-fa minden olyan frissítésekor, amely érinti a CustomPainter-t. Ha a metódus false-t ad vissza, a már megrajzolt kép érvényesnek tekintendő, és a paint nem kerül meghívásra. Tipikus implementáció: return oldDelegate.someField != someField — a régi és új painter mezőinek összehasonlítása az újrarajzolás szükségességének meghatározásához.

Animált vagy folyamatosan változó képek esetén (órák, töltésjelzők, grafikonok) a shouldRepaint-nek true-t kell visszaadnia minden állapotváltozásnál. Ha az objektum statikus (logó, ikon, háttér), a shouldRepaint false-t ad vissza az első megjelenítés után. A Flutter automatikusan gyorsítótárazza a paint eredményét, és csak a méret, átlátszóság változásakor vagy a shouldRepaint meghívásakor rajzol újra.

Példa egyedi rajzolásra CustomPainter-rel Dart-ban

Hozzunk létre GaugePainter-t — egy egyedi kör alakú jelzőt animált kitöltéssel. A CustomPainter fogadja az aktuális értéket (progress 0.0-tól 1.0-ig), és egy ívet rajzol gradienst alkalmazva. A shouldRepaint metódusban a progress érték összehasonlítása történik az optimalizáció érdekében. A CustomPaint a widget-fába kerül a size paraméterrel a rajzolási terület korlátozásához.

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 Path-tel összetett alakzatokhoz

A példa egy hullámgrafikont rajzol Path segítségével. A Path lehetővé teszi tetszőleges kontúrok építését vonalakból, Bezier-görbékből és ívekből. Az építés után a kontúr kitöltésre kerül színnel vagy körvonalazásra vonallal. A példában a grafikon egy hullámformát imitáló pontok tömbje alapján épül fel.

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 és backgroundPainter: különbség

painter (háttér) a CustomPaint gyermeke előtt rajzol. Ha a CustomPaint-nek van gyermeke (child paraméter), a háttér painter alatta jelenik meg. Ez dekorációhoz alkalmas: folyamatjelző sávok, háttérminták, vízjelek. foregroundPainter a CustomPaint gyermeke után, azaz fölötte rajzol. Fedőrétegekhez használatos: tükröződések, maszkok, mérővonalzók, megjegyzések.

A különbség a painter és foregroundPainter között kritikus a Z-order szempontjából. Ha valamit a tartalom mögé kell rajzolni — használja a painter-t. Ha a tartalom fölé — foregroundPainter-t. Bizonyos esetekben mindkét painter használható egyszerre: háttér a painter-en keresztül, címke-fedőréteg a foregroundPainter-en keresztül. Ez lehetővé teszi a különböző grafikus rétegek logikájának szétválasztását két külön CustomPainter osztályba.

A size paraméter a paint metódusban mindkét painter esetében azonos, és a CustomPaint számára allokált terület mérete határozza meg. A méret explicit módon beállítható a size paraméteren keresztül a CustomPaint-ben, vagy implicit módon a szülő konténeren keresztül. Ha a size egyenlő Size.zero-val, a paint nem kerül meghívásra — a Flutter kihagyja a megjelenítést nulla terület esetén. Ezt a viselkedést figyelembe kell venni az elem animált megjelenésekor.

CustomPainter teljesítmény optimalizálása

A fő szabály a CustomPainter teljesítményéhez — ne hozzon létre objektumokat a paint metóduson belül. A Canvas, Paint, Path, Rect, Offset és más rajzolási objektumokat a CustomPainter konstruktorában kell létrehozni vagy gyorsítótárazni. Az objektumok létrehozása a paint-en belül allokációkhoz vezet minden képkockánál, ami 60 képkocka/másodpercnél gyakori szemétgyűjtést és animációs akadozást (jank) okoz.

A Path gyorsítótárazása jelentősen felgyorsítja az ismétlődő összetett kontúrok megjelenítését. Ha a kontúr nem változik a képkockák között (pl. háttérrács), hozza létre a Path-t egyszer és használja többször. RepaintBoundary — egy burkoló widget, amely megakadályozza a CustomPainter újrarajzolását a felső widget-fa változásakor. Ha a CustomPainter statikus, csomagolja be RepaintBoundary-ba az elkülönítéshez.

Animált CustomPainter-ekhez gyakori újrarajzolással használjon Ticker-t vagy AnimationController-t, a shouldRepaint pedig adjon vissza true-t az animált érték változásakor. Optimális az animált mező összehasonlítása a shouldRepaint-ben, nem pedig minden képkockán szükségtelenül újrarajzolni. Rect gyorsítótárazás összetett gradiensekhez: ha a gradiens nem változtat színeket, a Shader gyorsítótárazható a Paint.shader-en keresztül.

Gyakran Ismételt Kérdések

Mi a különbség a CustomPainter és a Canvas között a Flutter-ben?

CustomPainter — egy szerződés-osztály, amely meghatározza, mit és hogyan kell rajzolni a Canvas-on. Canvas — maga a rajzolási objektum, amely metódusokat biztosít (drawCircle, drawLine stb.). A CustomPainter a Canvas-t a paint metóduson keresztül kapja meg és kezeli annak használatát. Egy Canvas-t különböző CustomPainter-ek használhatnak különböző időpontokban.

Használható a CustomPainter CustomPaint nélkül?

Nem, a CustomPainter-nek nincs értelme CustomPaint nélkül. A CustomPaint az a widget, amely meghívja a CustomPainter paint metódusát és megjeleníti az eredményt a képernyőn. CustomPaint nélkül a Canvas nem jön létre, és a paint nem hajtódik végre. Lehetséges azonban saját RenderObject implementálása Canvas-szal, de ez egy alacsonyabb szintű megközelítés.

Hogyan animálható a CustomPainter?

Használjon AnimationController-t Ticker-rel, adja át az animált értéket a CustomPainter-nek a konstruktor paraméterein keresztül. Az érték változásakor hívja meg a setState()-t a CustomPaint-et tartalmazó widget-ben, ami kiváltja a shouldRepaint-et. Ha a shouldRepaint true-t ad vissza, a rendszer meghívja a paint-et az animáció új képkockájához.

Miért nem frissül a CustomPainter az adatok változásakor?

Az ok szinte mindig a shouldRepaint, amely false-t ad vissza. Ellenőrizze, hogy az oldDelegate mezői helyesen összehasonlításra kerülnek-e az új értékekkel. Ha változtatható objektumot használ, előfordulhat, hogy a shouldRepaint nem észleli a változásokat, mivel az objektumra való hivatkozás ugyanaz marad. Használjon ==-t vagy megváltoztathatatlan objektumokat a helyes összehasonlításhoz.

Használható a CustomPainter animációhoz ReorderableListView-ban?

Igen, a CustomPainter egyedi dekorációk rajzolására használható összetett listákban. Azonban vegye figyelembe, hogy az elemek átrendezésekor a ListView-n belüli RepaintBoundary gyorsítótárazza az egyes elemek megjelenítését. A CustomPainter-nek könnyűnek kell lennie, és nem szabad nehéz műveleteket tartalmaznia a paint-ben, hogy ne lassítsa a húzási animációt.

Összegzés

  • CustomPainter — Flutter absztrakt osztály egyedi 2D megjelenítéshez a paint és shouldRepaint metódusokkal
  • CustomPaint — widget, amely painter (háttér) és foregroundPainter (előtér) fogadásával jeleníti meg a grafikát
  • Canvas — objektum rajzolási metódusokkal: drawLine, drawCircle, drawPath, drawRect, drawArc és mások
  • Paint — osztály, amely meghatározza a rajzolási stílust: szín, vastagság, stílus (fill/stroke), átlátszóság és keverési mód
  • shouldRepaint — optimalizációs metódus, amely csak a megjelenítést befolyásoló mezők változásakor ad vissza true-t
  • Objektumok létrehozása a paint-en belül tilos — minden Paint, Path, Rect gyorsítótárazandó a 60 fps-hez
  • RepaintBoundary — widget a CustomPainter elkülönítéséhez a felső widget-fa újrarajzolásaitól

Kulcsrakész mobilalkalmazást fejlesztünk

Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.

Projekt megbeszélése

Olvassa el is