CustomPainter — bu nədir, paint və shouldRepaint metodları Flutter-da

Müəllif: IT Sectr Dərc olunub: 2026-07-22 Oxuma vaxtı: 10 dəq

CustomPainter — Flutter SDK-dan abstrakt sinifdir, tərtibatçılara Canvas-da xüsusi 2D qrafikasının çəkilməsi üzərində tam nəzarət verir. Tərtibatçı CustomPainter alt sinfini yaradır və iki məcburi metodu həyata keçirir: paint(Canvas, Size) və shouldRepaint(covariant CustomPainter oldDelegate). Flutter API Documentation (2026) məlumatına görə, CustomPainter CustomPaint vidjeti ilə birlikdə istifadə olunur, o, hər animasiya kadrında və ya vəziyyət dəyişikliyində çəkməni CustomPainter obyektinə həvalə edir.

Əsas məqamlar

  • CustomPainter — Flutter-ın abstrakt sinfi, paint və shouldRepaint metodları vasitəsilə Canvas-da xüsusi çəkməni təyin edir
  • CustomPaint — CustomPainter-i painter və ya foregroundPainter parametri kimi qəbul edən və nəticəni ekranda göstərən vidjet
  • Canvas — rəsm metodları təqdim edən obyekt (drawLine, drawCircle, drawPath, drawRect, drawArc və digərləri)
  • shouldRepaint — yeniləmə zamanı obyektin yenidən çəkilməsinin lazım olub-olmadığını təyin edən optimallaşdırma metodu
  • size — valideyn vidjetdən paint(Canvas canvas, Size size) metoduna ötürülən rəsm sahəsinin ölçüsü

CustomPainter nədir?

CustomPainter — Flutter-da ixtiyari 2D qrafikasının tətbiqi üçün əsas sinifdir. O, Android-də onDraw-ı ləğv etmək yanaşmasını əvəz edərək, daha çevik və deklarativ çəkmə modeli təqdim edir. Tərtibatçı CustomPainter alt sinfini yaradır, paint metodunu ləğv edir, orada Canvas və Size alır və Canvas-da bütün rəsm əməliyyatlarını yerinə yetirir. CustomPaint vidjeti paint-in çağırılmasını idarə edir və nəticəni vidjet ağacına inteqrasiya edir.

CustomPainter ilə birbaşa Canvas vasitəsilə rəsm çəkmə arasında əsas fərq — çəkmə məntiqinin (paint) və yenidən çəkmə tetikleyicisinin (shouldRepaint) ayrılmasıdır. Flutter sistemi valideyn vidjet hər dəyişdikdə shouldRepaint-i çağırır. shouldRepaint false qaytarırsa, paint çağırılmır, bu da resurslara qənaət edir. Bu mexanizm RenderObject-də shouldRebuild-ə bənzəyir və Flutter memarlığının üç ağacının (Widget, Element, RenderObject) bir hissəsidir.

CustomPaintpainter (fon qatı) və foregroundPainter (ön qat) parametrlərini qəbul edən vidjetdir. Hər iki parametr CustomPainter obyektlərini qəbul edir. Fon painteri CustomPaint-in uşaq vidjetindən əvvəl çəkir, foregroundPainter isə ondan sonra. Bu, CustomPaint-i dekorativ fon və ya örtük ilə konteyner kimi istifadə etməyə imkan verir, adi vidjetləri içəridə yerləşdirmək imkanını itirmədən.

Canvas və Paint Flutter-da

Canvas — Flutter-da rəsm üçün mərkəzi obyektdir, qrafik səthi inkapsulyasiya edir. O, təxminən 40 rəsm metodu təqdim edir: drawLine, drawCircle, drawRect, drawPath, drawArc, drawImage, drawPicture, drawPoints və digərləri. Flutter-də Canvas Android Canvas-dəki analoji sinfə uyğundur, lakin Dart və Flutter Engine memarlığına uyğunlaşdırılmışdır. Canvas koordinat sistemində işləyir, burada başlanğıc (0, 0) yuxarı sol küncdür.

Paint — paint() metodu ilə qarışdırmayın — rəsm stilini təyin edən sinifdir: rəng (color), xətt qalınlığı (strokeWidth), stil (style: fill və ya stroke), şəffaflıq, qarışdırma rejimi (blendMode) və hamarlama maskası. Paint rəsmdən əvvəl konfiqurasiya edilir və Canvas metodlarına ötürülür. Vacib: Paint dəyişdirilə bilən obyektdir, lakin onu bir dəfə yaradıb təkrar istifadə etmək, yalnız lazımi parametrləri dəyişmək tövsiyə olunur.

Canvas metoduTəyinatParametrlər
drawCircleDairə çəkməkOffset center, double radius, Paint paint
drawLineXətt çəkməkOffset p1, Offset p2, Paint paint
drawRectDüzbucaqlı çəkməkRect rect, Paint paint
drawPathİxtiyari kontur çəkməkPath path, Paint paint
drawArcQövs və ya sektor çəkməkRect rect, double startAngle, double sweepAngle, bool useCenter, Paint paint
drawRRectDairəvi künclü düzbucaqlıRRect rrect, Paint paint
drawOvalOval çəkməkRect rect, Paint paint
drawImageImage-dən şəkil çəkməkImage image, Offset p, Paint paint

Canvas transformasiyaları

Canvas koordinat sisteminin transformasiyalarını dəstəkləyir: translate(double dx, double dy) koordinat başlanğıcını yerdəyişdirir; rotate(double radians) sistemi fırladır; scale(double sx, double sy) miqyaslayır; skew(double sx, double sy) əyir. Transformasiyadan əvvəl Canvas vəziyyətini save() ilə saxlamaq, bitdikdən sonra isə restore() ilə bərpa etmək tövsiyə olunur. Bu, sonrakı paint çağırışlarında transformasiyaların yığılmasının qarşısını alır.

paint və shouldRepaint metodları

paint(Canvas canvas, Size size) — bütün çəkmə məntiqinin həyata keçirildiyi məcburi metoddur. canvas parametri — rəsm üçün qrafik səthdir. size parametri — rəsm üçün ayrılmış sahənin ölçüsüdür (en və hündürlük məntiqi piksellərdə). Canvas əvvəlcədən konfiqurasiya edilmişdir ki, koordinat başlanğıcı (0,0) rəsm sahəsinin yuxarı sol küncünə uyğun gəlir. Bütün koordinatlar bu başlanğıca nisbətən təyin edilir.

shouldRepaint(covariant CustomPainter oldDelegate) — yenidən çəkmə tezliyini optimallaşdıran məcburi metoddur. Flutter vidjet ağacının CustomPainter-ə təsir edən hər yeniləməsində shouldRepaint-i çağırır. Metod false qaytarırsa, artıq çəkilmiş şəkil etibarlı sayılır və paint çağırılmır. Tipik tətbiq: return oldDelegate.someField != someField — yenidən çəkmə ehtiyacını müəyyən etmək üçün köhnə və yeni painter-in sahələrinin müqayisəsi.

Animasiya olunan və ya daim dəyişən şəkillər üçün (saatlar, yüklənmə göstəriciləri, qrafiklər) shouldRepaint hər vəziyyət dəyişikliyində true qaytarmalıdır. Obyekt statikdirsə (loqo, ikon, fon), shouldRepaint ilk çəkmədən sonra false qaytarır. Flutter paint nəticəsini avtomatik keşləyir və yalnız ölçü, şəffaflıq dəyişdikdə və ya shouldRepaint çağırıldıqda yenidən çəkir.

CustomPainter ilə Dart-da xüsusi rəsm nümunəsi

GaugePainter yaradaq — animasiya olunan doldurma ilə xüsusi dairəvi göstərici. CustomPainter cari dəyəri (progress 0.0-dan 1.0-a qədər) qəbul edir və gradientlə qövs çəkir. shouldRepaint metodunda optimallaşdırma üçün progress dəyəri müqayisə edilir. CustomPaint vidjet ağacına rəsm sahəsini məhdudlaşdırmaq üçün size parametri ilə yerləşdirilir.

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;
    }
}

Mürəkkəb fiqurlar üçün Path ilə CustomPainter

Nümunə Path istifadə edərək dalğa qrafiki çəkir. Path xətlərdən, Bezier əyrilərindən və qövslərdən ixtiyari konturlar qurmağa imkan verir. Kontur qurulduqdan sonra rənglə doldurulur və ya xətt ilə konturlanır. Nümunədə qrafik dalğa formasını təqlid edən nöqtələr massivi əsasında qurulur.

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 və backgroundPainter: fərq

painter (fon) CustomPaint-in uşaq vidjetindən əvvəl çəkir. CustomPaint-in uşaq vidjeti varsa (child parametri), fon painteri onun altında göstərilir. Bu, dekorasiya üçün uyğundur: gedişat zolaqları, fon naxışları, su nişanları. foregroundPainter uşaq vidjetdən sonra, yəni onun üstündə çəkir. Üst qatlar üçün istifadə olunur: parıltılar, maskalar, ölçü xətləri, annotasiyalar.

Fərq painter və foregroundPainter arasında Z-order üçün kritikdir. Məzmunun arxasında bir şey çəkmək lazımdırsa — painter istifadə edin. Məzmunun üstündədirsə — foregroundPainter. Bəzi hallarda hər iki painter-dən eyni vaxtda istifadə etmək olar: fon painter vasitəsilə, etiket-örtük foregroundPainter vasitəsilə. Bu, müxtəlif qrafik qatlarının məntiqini iki ayrı CustomPainter sinfinə ayırmağa imkan verir.

size parametri paint metodunda hər iki painter üçün eynidir və CustomPaint üçün ayrılmış sahənin ölçüsü ilə müəyyən edilir. Ölçü CustomPaint-də size parametri ilə açıq şəkildə və ya valideyn konteyner vasitəsilə gizli şəkildə təyin edilə bilər. size Size.zero-a bərabərdirsə, paint çağırılmır — Flutter sıfır sahə üçün çəkməni buraxır. Bu davranış elementin animasiya olunan görünməsində nəzərə alınmalıdır.

CustomPainter performans optimallaşdırması

Əsas qayda CustomPainter performansı — paint metodu daxilində obyektlər yaratmamaqdır. Canvas, Paint, Path, Rect, Offset və digər rəsm obyektləri CustomPainter konstruktorunda yaradılmalı və ya keşlənməlidir. paint daxilində obyekt yaratmaq hər kadrda alokasiyalara gətirib çıxarır ki, bu da saniyədə 60 kadrda tez-tez zibil yığımına və animasiyanın sıçrayışına (jank) səbəb olur.

Path keşlənməsi təkrarlanan mürəkkəb konturların çəkilməsini əhəmiyyətli dərəcədə sürətləndirir. Kontur kadrlar arasında dəyişmirsə (məsələn, fon toru), Path-i bir dəfə yaradın və dəfələrlə istifadə edin. RepaintBoundary — CustomPainter-in yuxarıdakı vidjet ağacı dəyişdikdə yenidən çəkilməsinin qarşısını alan sarğıcı vidjetdir. CustomPainter statikdirsə, onu təcrid etmək üçün RepaintBoundary-ə sarın.

Tez-tez yenidən çəkilən animasiya olunan CustomPainter üçün Ticker və ya AnimationController istifadə edin, shouldRepaint animasiya olunan dəyər dəyişdikdə true qaytarsın. Optimal olaraq shouldRepaint-də animasiya olunan sahəni müqayisə edin, hər kadrda lazımsız yerə yenidən çəkməyin. Mürəkkəb gradientlər üçün Rect keşlənməsi: gradient rəngləri dəyişmirsə, Paint.shader vasitəsilə Shader-i keşləmək olar.

Tez-tez verilən suallar

Flutter-da CustomPainter və Canvas arasında fərq nədir?

CustomPainter — Canvas-da nə və necə çəkiləcəyini təyin edən kontrakt sinifdir. Canvas — metodlar təqdim edən (drawCircle, drawLine və s.) rəsm obyektinin özüdür. CustomPainter Canvas-ı paint metodu vasitəsilə alır və onun istifadəsini idarə edir. Bir Canvas müxtəlif vaxtlarda müxtəlif CustomPainter tərəfindən istifadə edilə bilər.

CustomPainter-i CustomPaint olmadan istifadə etmək olar?

Xeyr, CustomPainter CustomPaint olmadan məna kəsb etmir. CustomPaint — CustomPainter-in paint metodunu çağıran və nəticəni ekranda göstərən vidjetdir. CustomPaint olmadan Canvas yaradılmayacaq və paint icra olunmayacaq. Bununla belə, Canvas ilə öz RenderObject-unuzu tətbiq etmək olar, lakin bu, daha aşağı səviyyəli yanaşmadır.

CustomPainter-i necə animasiya etmək olar?

AnimationController ilə Ticker istifadə edin, animasiya olunan dəyəri CustomPainter-ə konstruktor parametrləri vasitəsilə ötürün. Dəyər dəyişdikdə CustomPaint-i ehtiva edən vidjetdə setState() çağırın, bu shouldRepaint-i tetikleyir. shouldRepaint true qaytarırsa, sistem animasiyanın yeni kadrı üçün paint çağırır.

Niyə CustomPainter məlumat dəyişdikdə yenilənmir?

Səbəb demək olar ki, həmişə false qaytaran shouldRepaint-dir. oldDelegate sahələrinin yeni dəyərlərlə düzgün müqayisə edilib-edilmədiyini yoxlayın. Dəyişdirilə bilən obyekt istifadə olunursa, shouldRepaint dəyişiklikləri görməyə bilər, çünki obyektə istinad eyni qalır. Düzgün müqayisə üçün == və ya dəyişməz obyektlərdən istifadə edin.

ReorderableListView-da animasiya üçün CustomPainter istifadə etmək olar?

Bəli, CustomPainter mürəkkəb siyahılarda xüsusi dekorasiyaların çəkilməsi üçün istifadə olunur. Bununla belə, elementlərin sıralanması zamanı ListView daxilində RepaintBoundary hər elementin çəkilməsini keşləyir. CustomPainter yüngül olmalı və paint-də ağır əməliyyatlar ehtiva etməməlidir ki, sürükləmə animasiyasını yavaşlatmasın.

Xülasə

  • CustomPainter — paint və shouldRepaint metodları ilə xüsusi 2D çəkmə üçün Flutter-ın abstrakt sinfi
  • CustomPaint — qrafikanı göstərmək üçün painter (fon) və foregroundPainter (ön plan) qəbul edən vidjet
  • Canvas — drawLine, drawCircle, drawPath, drawRect, drawArc və digər çəkmə metodları olan obyekt
  • Paint — çəkmə stilini təyin edən sinif: rəng, qalınlıq, stil (fill/stroke), şəffaflıq və qarışdırma rejimi
  • shouldRepaint — yalnız çəkməyə təsir edən sahələr dəyişdikdə true qaytaran optimallaşdırma metodu
  • paint daxilində obyekt yaratmaq qadağandır — bütün Paint, Path, Rect 60 fps üçün keşlənməlidir
  • RepaintBoundary — CustomPainter-i yuxarıdakı vidjet ağacının yenidən çəkilmələrindən təcrid etmək üçün vidjet

Açar təslim mobil tətbiq hazırlayacağıq

IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.

Layihəni müzakirə et

Həm də oxuyun