CustomPainter — nedir, Flutter'da paint ve shouldRepaint metotları

Yazar: IT Sectr Yayınlanma: 2026-07-22 Okuma süresi: 10 dk

CustomPainter, Flutter SDK'dan soyut bir sınıftır ve geliştiricilere Canvas üzerinde özel 2D grafikleri işleme konusunda tam kontrol sağlar. Geliştirici, CustomPainter'ın bir alt sınıfını oluşturur ve iki zorunlu metodu uygular: paint(Canvas, Size) ve shouldRepaint(covariant CustomPainter oldDelegate). Flutter API Dokümantasyonu'na (2026) göre CustomPainter, her animasyon karesinde veya durum değişikliğinde işlemeyi sağlanan CustomPainter nesnesine devreden CustomPaint widget'ı ile birlikte kullanılır.

Ana Noktalar

  • CustomPainter — paint ve shouldRepaint metotları aracılığıyla Canvas üzerinde özel işlemeyi tanımlayan Flutter soyut sınıfı
  • CustomPaint — CustomPainter'ı painter veya foregroundPainter parametresi olarak kabul eden ve sonucu ekranda görüntüleyen widget
  • Canvas — çizim metotları (drawLine, drawCircle, drawPath, drawRect, drawArc ve diğerleri) sağlayan nesne
  • shouldRepaint — güncelleme sırasında nesnenin yeniden çizilmesi gerekip gerekmediğini belirleyen optimizasyon metodu
  • size — üst widget'tan paint(Canvas canvas, Size size) öğesine iletilen çizim alanının boyutu

CustomPainter Nedir?

CustomPainter, özel 2D grafikler uygulamak için Flutter'ın temel sınıfıdır. Android'de onDraw'ı geçersiz kılma yaklaşımının yerine daha esnek ve bildirimsel bir işleme modeli sağlar. Geliştirici, CustomPainter'ın bir alt sınıfını oluşturur, Canvas ve Size aldığı paint metodunu geçersiz kılar ve Canvas üzerinde tüm çizim işlemlerini gerçekleştirir. CustomPaint widget'ı paint çağrısını yönetir ve sonucu widget ağacına entegre eder.

CustomPainter ile Canvas üzerinden doğrudan çizim arasındaki temel fark, işleme mantığının (paint) ve yeniden çizim tetikleyicisinin (shouldRepaint) ayrılmasıdır. Flutter sistemi, üst widget her değiştiğinde shouldRepaint'i çağırır. shouldRepaint false döndürürse, paint çağrılmaz ve kaynaklar korunur. Bu mekanizma, RenderObject'teki shouldRebuild'e benzer ve üç ağacı (Widget, Element, RenderObject) ile Flutter mimarisinin bir parçasıdır.

CustomPaint, painter (arka plan katmanı) ve foregroundPainter (ön plan katmanı) parametrelerini kabul eden bir widget'tır. Her iki parametre de CustomPainter nesnelerini kabul eder. Arka plan painter'ı, CustomPaint'in alt widget'ından önce çizilir ve foregroundPainter sonra çizilir. Bu, CustomPaint'in içine normal widget'lar yerleştirme yeteneğini kaybetmeden dekoratif arka plan veya kaplamalı bir kapsayıcı olarak kullanılmasını sağlar.

Flutter'da Canvas ve Paint

Canvas Flutter'da merkezi çizim nesnesidir ve grafik yüzeyini kapsüller. Yaklaşık 40 çizim metodu sağlar: drawLine, drawCircle, drawRect, drawPath, drawArc, drawImage, drawPicture, drawPoints ve diğerleri. Flutter'daki Canvas, Android Canvas'daki benzer bir sınıfa karşılık gelir ancak Dart mimarisi ve Flutter Engine'e uyarlanmıştır. Canvas, orijin (0, 0) sol üst köşe olan bir koordinat sisteminde çalışır.

Paint — paint() metodu ile karıştırılmamalıdır — çizim stilini tanımlayan bir sınıftır: renk (color), çizgi kalınlığı (strokeWidth), stil (style: fill veya stroke), opaklık, karışım modu (blendMode) ve kenar yumuşatma maskesi. Paint çizimden önce yapılandırılır ve Canvas metotlarına iletilir. Önemli: Paint değiştirilebilir bir nesnedir, ancak bir kez oluşturulup yalnızca gerekli parametreler değiştirilerek yeniden kullanılması önerilir.

Canvas MetoduAmaçParametreler
drawCircleDaire çizerOffset center, double radius, Paint paint
drawLineÇizgi parçası çizerOffset p1, Offset p2, Paint paint
drawRectDikdörtgen çizerRect rect, Paint paint
drawPathİsteğe bağlı yol çizerPath path, Paint paint
drawArcYay veya dilim çizerRect rect, double startAngle, double sweepAngle, bool useCenter, Paint paint
drawRRectYuvarlak köşeli dikdörtgenRRect rrect, Paint paint
drawOvalOval çizerRect rect, Paint paint
drawImageImage'dan resim çizerImage image, Offset p, Paint paint

Canvas Dönüşümleri

Canvas koordinat sistemi dönüşümlerini destekler: translate(double dx, double dy) orijini kaydırır; rotate(double radians) sistemi döndürür; scale(double sx, double sy) ölçeklendirir; skew(double sx, double sy) eğer. Dönüşümden önce Canvas durumunun save() ile kaydedilmesi ve tamamlandıktan sonra restore() ile geri yüklenmesi önerilir. Bu, sonraki paint çağrılarında dönüşümlerin birikmesini önler.

paint ve shouldRepaint Metotları

paint(Canvas canvas, Size size) tüm çizim mantığını uygulayan zorunlu metottur. canvas parametresi çizim için grafik yüzeyidir. size parametresi çizim için ayrılan alanın boyutudur (mantıksal piksel cinsinden genişlik ve yükseklik). Canvas, orijin (0,0) çizim alanının sol üst köşesine karşılık gelecek şekilde önceden yapılandırılmıştır. Tüm koordinatlar bu orijine göre belirtilir.

shouldRepaint(covariant CustomPainter oldDelegate) yeniden çizim sıklığını optimize eden zorunlu bir metottur. Flutter, CustomPainter'ı etkileyen her widget ağacı güncellemesinde shouldRepaint'i çağırır. Metot false döndürürse, önceden işlenmiş görüntü geçerli kabul edilir ve paint çağrılmaz. Tipik bir uygulama: return oldDelegate.someField != someField — yeniden çizim gereksinimini belirlemek için eski ve yeni painter alanlarının karşılaştırılması.

Animasyonlu veya sürekli değişen görüntüler (saatler, yükleme göstergeleri, grafikler) için shouldRepaint her durum değişikliğinde true döndürmelidir. Nesne statikse (logo, simge, arka plan), shouldRepaint ilk işlemeden sonra false döndürür. Flutter otomatik olarak paint sonucunu önbelleğe alır ve yalnızca boyut, opaklık veya shouldRepaint çağrısı değiştiğinde yeniden çizer.

Dart'ta CustomPainter ile Özel Çizim Örneği

GaugePainter oluşturalım — animasyonlu dolgulu özel bir dairesel gösterge. CustomPainter mevcut değeri (0.0 ile 1.0 arasında ilerleme) kabul eder ve gradyanlı bir yay çizer. shouldRepaint metodu optimizasyon için ilerleme değerini karşılaştırır. CustomPaint, çizim alanını sınırlamak için size parametresiyle widget ağacına yerleştirilir.

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

Karmaşık Şekiller için Path ile CustomPainter

Örnek, Path kullanarak bir dalga grafiği çizer. Path, çizgiler, Bezier eğrileri ve yaylardan isteğe bağlı konturlar oluşturmaya izin verir. Kontur oluşturulduktan sonra renkle doldurulur veya bir çizgiyle ana hatları çizilir. Örnekte, grafik bir dalga formunu simüle eden bir dizi noktadan oluşturulur.

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 ve backgroundPainter: Fark

painter (arka plan) CustomPaint'in alt widget'ından önce çizilir. CustomPaint'in bir alt widget'ı (child parametresi) varsa, arka plan painter'ı onun altında görüntülenir. Bu, dekorasyonlar için uygundur: ilerleme çubukları, arka plan desenleri, filigranlar. foregroundPainter alt widget'tan sonra, yani onun üzerinde çizilir. Kaplamalar için kullanılır: vurgular, maskeler, ölçüm cetvelleri, açıklamalar.

painter ve foregroundPainter arasındaki fark Z-sırası için kritiktir. İçeriğin arkasına bir şey çizmeniz gerekiyorsa — painter kullanın. İçeriğin üzerine ise — foregroundPainter kullanın. Bazı durumlarda, her iki painter'ı aynı anda kullanabilirsiniz: painter aracılığıyla arka plan, foregroundPainter aracılığıyla kaplama etiketi. Bu, farklı grafik katmanlarının mantığını iki ayrı CustomPainter sınıfına ayırmaya olanak tanır.

Paint metodundaki size parametresi her iki painter için de aynıdır ve CustomPaint için ayrılan alanın boyutuna göre belirlenir. Boyut, CustomPaint'teki size parametresiyle açıkça veya üst kapsayıcı aracılığıyla örtük olarak ayarlanabilir. Boyut Size.zero ise, paint çağrılmaz — Flutter sıfır boyutlu bir alan için işlemeyi atlar. Bu davranış, öğe görünümü canlandırılırken dikkate alınmalıdır.

CustomPainter Performans Optimizasyonu

CustomPainter performansının ana kuralı, paint metodu içinde nesne oluşturmamaktır. Canvas, Paint, Path, Rect, Offset ve diğer çizim nesneleri CustomPainter yapıcısında oluşturulmalı veya önbelleğe alınmalıdır. Paint içinde nesne oluşturmak, her karede bellek tahsisine yol açar ve saniyede 60 karede sık sık çöp toplamaya ve animasyon takılmalarına (jank) neden olur.

Path önbelleğe alma, tekrarlanan karmaşık yolların işlenmesini önemli ölçüde hızlandırır. Yol kareler arasında değişmiyorsa (örneğin, bir arka plan ızgarası), Path'i bir kez oluşturun ve birden çok kez yeniden kullanın. RepaintBoundary, üst widget ağacı değiştiğinde CustomPainter'ın yeniden çizilmesini önleyen bir sarmalayıcı widget'tır. CustomPainter statikse, yalıtım için onu bir RepaintBoundary ile sarın.

Sık yeniden çizim içeren animasyonlu CustomPainter için, animasyon değeri her değiştiğinde true döndüren shouldRepaint ile Ticker veya AnimationController kullanın. Gereksiz yere her karede yeniden çizmek yerine shouldRepaint'te animasyon alanını karşılaştırmak en uygunudur. Karmaşık gradyanlar için Rect önbelleğe alma: gradyan renkleri değişmiyorsa, Paint.shader aracılığıyla Shader'ı önbelleğe alabilirsiniz.

Sıkça Sorulan Sorular

Flutter'da CustomPainter ve Canvas arasındaki fark nedir?

CustomPainter, Canvas üzerinde neyin ve nasıl çizileceğini tanımlayan bir sözleşme sınıfıdır. Canvas, metotlar (drawCircle, drawLine vb.) sağlayan çizim nesnesinin kendisidir. CustomPainter, paint metodu aracılığıyla Canvas'ı alır ve kullanımını kontrol eder. Aynı Canvas, farklı zamanlarda farklı CustomPainter'lar tarafından kullanılabilir.

CustomPainter CustomPaint olmadan kullanılabilir mi?

Hayır, CustomPainter'ın CustomPaint olmadan bir anlamı yoktur. CustomPaint, CustomPainter'ın paint metodunu çağıran ve sonucu ekranda görüntüleyen widget'tır. CustomPaint olmadan Canvas oluşturulmaz ve paint yürütülmez. Ancak, Canvas ile kendi RenderObject'unuzu uygulayabilirsiniz, ancak bu daha düşük seviyeli bir yaklaşımdır.

CustomPainter nasıl canlandırılır?

Yapıcı parametreleri aracılığıyla animasyon değerini CustomPainter'a geçirerek bir Ticker ile AnimationController kullanın. Değer değiştiğinde, CustomPaint'i içeren widget'ta setState() çağrısı yapın, bu shouldRepaint çağrısını tetikler. shouldRepaint true döndürürse, sistem yeni animasyon karesi için paint'i çağırır.

Veri değiştiğinde CustomPainter neden güncellenmiyor?

Nedeni neredeyse her zaman shouldRepaint'in false döndürmesidir. oldDelegate alanlarının yeni değerlerle doğru şekilde karşılaştırılıp karşılaştırılmadığını kontrol edin. Değiştirilebilir bir nesne kullanılıyorsa, nesne referansı aynı kaldığı için shouldRepaint değişiklikleri algılamayabilir. Doğru karşılaştırma için == veya değişmez nesneler kullanın.

ReorderableListView'de animasyon için CustomPainter kullanılabilir mi?

Evet, CustomPainter karmaşık listelerde özel dekorasyonlar işlemek için kullanılır. Ancak, öğeleri yeniden sıralarken ListView içindeki RepaintBoundary'in her öğenin işlenmesini önbelleğe aldığını unutmayın. CustomPainter hafif olmalı ve sürükleme animasyonunu yavaşlatmamak için paint'te ağır işlemler içermemelidir.

Özet

  • CustomPainter — paint ve shouldRepaint metotlarıyla özel 2D işleme için Flutter soyut sınıfı
  • CustomPaint — grafik görüntülemek için painter (arka plan) ve foregroundPainter (ön plan) kabul eden widget
  • Canvas — çizim metotlarına sahip nesne: drawLine, drawCircle, drawPath, drawRect, drawArc ve diğerleri
  • Paint — çizim stilini tanımlayan sınıf: renk, kalınlık, stil (fill/stroke), opaklık ve karışım modu
  • shouldRepaint — yalnızca işlemeyi etkileyen alanlar değiştiğinde true döndüren optimizasyon metodu
  • paint içinde nesne oluşturmak yasaktır — 60 fps için tüm Paint, Path, Rect önbelleğe alınmalıdır
  • RepaintBoundary — CustomPainter'ı üst widget ağacının yeniden çizmelerinden yalıtmak için widget

Anahtar teslim bir mobil uygulama geliştireceğiz

IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.

Projeyi tartış

Ayrıca okuyun