CustomPainter — यह क्या है, Flutter में paint और shouldRepaint विधियाँ

लेखक: IT Sectr प्रकाशित: 2026-07-22 पढ़ने का समय: 10 मिनट

CustomPainter Flutter SDK का एक एब्सट्रैक्ट क्लास है जो डेवलपर्स को Canvas पर कस्टम 2D ग्राफिक्स रेंडर करने का पूर्ण नियंत्रण देता है। डेवलपर CustomPainter का उपवर्ग बनाता है और दो अनिवार्य विधियाँ लागू करता है: paint(Canvas, Size) और shouldRepaint(covariant CustomPainter oldDelegate)। Flutter API डॉक्यूमेंटेशन (2026) के अनुसार, CustomPainter का उपयोग CustomPaint विजेट के साथ किया जाता है, जो प्रत्येक एनिमेशन फ्रेम या स्थिति परिवर्तन पर प्रदान किए गए CustomPainter ऑब्जेक्ट को रेंडरिंग सौंपता है।

मुख्य बातें

  • CustomPainter — Flutter का एब्सट्रैक्ट क्लास जो paint और shouldRepaint विधियों के माध्यम से Canvas पर कस्टम रेंडरिंग परिभाषित करता है
  • CustomPaint — विजेट जो CustomPainter को painter या foregroundPainter पैरामीटर के रूप में स्वीकार करता है और परिणाम स्क्रीन पर प्रदर्शित करता है
  • Canvas — ऑब्जेक्ट जो ड्रॉइंग विधियाँ प्रदान करता है (drawLine, drawCircle, drawPath, drawRect, drawArc और अन्य)
  • shouldRepaint — ऑप्टिमाइज़ेशन विधि जो यह निर्धारित करती है कि अपडेट होने पर ऑब्जेक्ट को पुनः चित्रित करने की आवश्यकता है या नहीं
  • size — पैरेंट विजेट से paint(Canvas canvas, Size size) में पास किए जाने वाले ड्रॉइंग क्षेत्र का आकार

CustomPainter क्या है?

CustomPainter कस्टम 2D ग्राफिक्स लागू करने के लिए Flutter का आधार क्लास है। यह Android में onDraw को ओवरराइड करने के दृष्टिकोण को बदलता है, जो अधिक लचीला और घोषणात्मक रेंडरिंग मॉडल प्रदान करता है। डेवलपर CustomPainter का उपवर्ग बनाता है, paint विधि को ओवरराइड करता है जहाँ वह Canvas और Size प्राप्त करता है, और Canvas पर सभी ड्रॉइंग ऑपरेशन करता है। CustomPaint विजेट paint कॉल का प्रबंधन करता है और परिणाम को विजेट ट्री में एकीकृत करता है।

CustomPainter और Canvas के माध्यम से सीधे ड्रॉइंग के बीच मुख्य अंतर रेंडरिंग लॉजिक (paint) और पुनः चित्रण ट्रिगर (shouldRepaint) का पृथक्करण है। Flutter सिस्टम हर बार जब पैरेंट विजेट बदलता है तो shouldRepaint को कॉल करता है। यदि shouldRepaint false लौटाता है, तो paint कॉल नहीं किया जाता है, जिससे संसाधन बचते हैं। यह तंत्र RenderObject में shouldRebuild के समान है और अपने तीन पेड़ों (Widget, Element, RenderObject) के साथ Flutter आर्किटेक्चर का हिस्सा है।

CustomPaint एक विजेट है जो painter (पृष्ठभूमि परत) और foregroundPainter(अग्रभूमि परत) पैरामीटर स्वीकार करता है। दोनों पैरामीटर CustomPainter ऑब्जेक्ट स्वीकार करते हैं। पृष्ठभूमि painter CustomPaint के चाइल्ड विजेट से पहले चित्रित किया जाता है, और foregroundPainter बाद में। यह CustomPaint को सजावटी पृष्ठभूमि या ओवरले वाले कंटेनर के रूप में उपयोग करने की अनुमति देता है, बिना अंदर सामान्य विजेट एम्बेड करने की क्षमता खोए।

Flutter में Canvas और Paint

Canvas Flutter में केंद्रीय ड्रॉइंग ऑब्जेक्ट है, जो ग्राफिक्स सतह को समाहित करता है। यह लगभग 40 ड्रॉइंग विधियाँ प्रदान करता है: drawLine, drawCircle, drawRect, drawPath, drawArc, drawImage, drawPicture, drawPoints और अन्य। Flutter में Canvas Android Canvas में समान क्लास से मेल खाता है लेकिन Dart आर्किटेक्चर और Flutter Engine के अनुकूल है। Canvas एक समन्वय प्रणाली में काम करता है जहाँ मूल बिंदु (0, 0) ऊपरी बाएँ कोना है।

Paint — paint() विधि से भ्रमित न हों — एक क्लास है जो ड्रॉइंग शैली को परिभाषित करता है: रंग (color), रेखा मोटाई (strokeWidth), शैली (style: fill या stroke), अपारदर्शिता, सम्मिश्रण मोड (blendMode) और एंटी-अलियासिंग मास्क। Paint ड्रॉइंग से पहले कॉन्फ़िगर किया जाता है और Canvas विधियों में पास किया जाता है। महत्वपूर्ण: Paint एक परिवर्तनीय ऑब्जेक्ट है, लेकिन इसे एक बार बनाने और केवल आवश्यक पैरामीटर बदलकर पुनः उपयोग करने की अनुशंसा की जाती है।

Canvas विधिउद्देश्यपैरामीटर
drawCircleवृत्त बनानाOffset center, double radius, Paint paint
drawLineरेखा खंड बनानाOffset p1, Offset p2, Paint paint
drawRectआयत बनानाRect rect, Paint paint
drawPathमनमाना पथ बनानाPath path, Paint paint
drawArcचाप या सेक्टर बनानाRect rect, double startAngle, double sweepAngle, bool useCenter, Paint paint
drawRRectगोल कोनों वाला आयतRRect rrect, Paint paint
drawOvalअंडाकार बनानाRect rect, Paint paint
drawImageImage से चित्र बनानाImage image, Offset p, Paint paint

Canvas रूपांतरण

Canvas समन्वय प्रणाली रूपांतरण का समर्थन करता है: translate(double dx, double dy) मूल बिंदु को स्थानांतरित करता है; rotate(double radians) सिस्टम को घुमाता है; scale(double sx, double sy) स्केल करता है; skew(double sx, double sy) झुकाता है। रूपांतरण से पहले, save() के माध्यम से Canvas स्थिति को सहेजने और पूरा होने के बाद restore() के माध्यम से इसे पुनर्स्थापित करने की अनुशंसा की जाती है। यह बाद के paint कॉल में रूपांतरणों के संचय को रोकता है।

paint और shouldRepaint विधियाँ

paint(Canvas canvas, Size size) अनिवार्य विधि है जो सभी ड्रॉइंग लॉजिक को लागू करती है। canvas पैरामीटर ड्रॉइंग के लिए ग्राफिक्स सतह है। size पैरामीटर ड्रॉइंग के लिए आवंटित क्षेत्र का आकार है (तार्किक पिक्सेल में चौड़ाई और ऊँचाई)। Canvas पूर्व-कॉन्फ़िगर किया गया है ताकि मूल बिंदु (0,0) ड्रॉइंग क्षेत्र के ऊपरी बाएँ कोने से मेल खाए। सभी निर्देशांक इस मूल बिंदु के सापेक्ष निर्दिष्ट किए जाते हैं।

shouldRepaint(covariant CustomPainter oldDelegate) एक अनिवार्य विधि है जो पुनः चित्रण आवृत्ति को अनुकूलित करती है। Flutter प्रत्येक विजेट ट्री अपडेट पर shouldRepaint को कॉल करता है जो CustomPainter को प्रभावित करता है। यदि विधि false लौटाती है, तो पहले से रेंडर की गई छवि को मान्य माना जाता है और paint कॉल नहीं किया जाता है। सामान्य कार्यान्वयन: return oldDelegate.someField != someField — पुनः चित्रण की आवश्यकता निर्धारित करने के लिए पुराने और नए painter के फ़ील्ड की तुलना।

एनिमेटेड या लगातार बदलती छवियों (घड़ियाँ, लोडिंग संकेतक, चार्ट) के लिए shouldRepaint को प्रत्येक स्थिति परिवर्तन पर true लौटाना चाहिए। यदि ऑब्जेक्ट स्थिर है (लोगो, आइकन, पृष्ठभूमि), तो shouldRepaint पहले रेंडर के बाद false लौटाता है। Flutter स्वचालित रूप से paint परिणाम को कैश करता है और केवल आकार, अपारदर्शिता या shouldRepaint कॉल बदलने पर पुनः चित्रित करता है।

Dart में CustomPainter के साथ कस्टम ड्रॉइंग का उदाहरण

आइए GaugePainter बनाएँ — एनिमेटेड भराव वाला एक कस्टम वृत्ताकार गेज। CustomPainter वर्तमान मान (0.0 से 1.0 तक प्रगति) स्वीकार करता है और ग्रेडिएंट के साथ एक चाप बनाता है। shouldRepaint विधि अनुकूलन के लिए प्रगति मान की तुलना करती है। CustomPaint को ड्रॉइंग क्षेत्र को सीमित करने के लिए size पैरामीटर के साथ विजेट ट्री में रखा जाता है।

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

जटिल आकृतियों के लिए Path के साथ CustomPainter

उदाहरण Path का उपयोग करके तरंग चार्ट बनाता है। Path रेखाओं, बेज़ियर वक्रों और चापों से मनमाने आकार बनाने की अनुमति देता है। आकार बनाने के बाद, इसे रंग से भरा जाता है या रेखा से रेखांकित किया जाता है। उदाहरण में, चार्ट तरंग आकार का अनुकरण करने वाले बिंदुओं की एक सरणी से बनाया गया है।

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 और backgroundPainter: अंतर

painter (पृष्ठभूमि) CustomPaint के चाइल्ड विजेट से पहले चित्रित किया जाता है। यदि CustomPaint में चाइल्ड विजेट (child पैरामीटर) है, तो पृष्ठभूमि painter उसके नीचे प्रदर्शित होता है। यह सजावट के लिए उपयुक्त है: प्रगति पट्टियाँ, पृष्ठभूमि पैटर्न, वॉटरमार्क। foregroundPainter चाइल्ड विजेट के बाद चित्रित किया जाता है, अर्थात उसके ऊपर। इसका उपयोग ओवरले के लिए किया जाता है: हाइलाइट, मास्क, मापने वाले रूलर, एनोटेशन।

painter और foregroundPainter के बीच अंतर Z-क्रम के लिए महत्वपूर्ण है। यदि आपको सामग्री के पीछे कुछ चित्रित करना है — painter का उपयोग करें। यदि सामग्री के ऊपर — foregroundPainter का। कुछ मामलों में, आप दोनों painter का एक साथ उपयोग कर सकते हैं: painter के माध्यम से पृष्ठभूमि, foregroundPainter के माध्यम से ओवरले लेबल। यह विभिन्न ग्राफिक परतों के तर्क को दो अलग CustomPainter क्लास में विभाजित करने की अनुमति देता है।

paint विधि में size पैरामीटर दोनों painter के लिए समान है और CustomPaint के लिए आवंटित क्षेत्र के आकार से निर्धारित होता है। आकार CustomPaint में size पैरामीटर के माध्यम से स्पष्ट रूप से या पैरेंट कंटेनर के माध्यम से अप्रत्यक्ष रूप से सेट किया जा सकता है। यदि आकार Size.zero है, तो paint कॉल नहीं किया जाता है — Flutter शून्य आकार वाले क्षेत्र के लिए रेंडरिंग छोड़ देता है। तत्व प्रकटन को एनिमेट करते समय इस व्यवहार पर विचार किया जाना चाहिए।

CustomPainter प्रदर्शन अनुकूलन

CustomPainter प्रदर्शन का मुख्य नियम paint विधि के अंदर ऑब्जेक्ट नहीं बनाना है। Canvas, Paint, Path, Rect, Offset और अन्य ड्रॉइंग ऑब्जेक्ट CustomPainter कंस्ट्रक्टर में बनाए जाने चाहिए या कैश किए जाने चाहिए। paint के अंदर ऑब्जेक्ट बनाने से प्रत्येक फ्रेम पर आवंटन होता है, जो 60 फ्रेम प्रति सेकंड पर बार-बार कचरा संग्रह और एनिमेशन जर्क (jank) का कारण बनता है।

Path कैशिंग दोहराए जाने वाले जटिल पथों के रेंडरिंग को काफी तेज करता है। यदि पथ फ्रेम के बीच नहीं बदलता है (उदाहरण के लिए, पृष्ठभूमि ग्रिड), तो Path को एक बार बनाएँ और इसे कई बार पुनः उपयोग करें। RepaintBoundary एक रैपर विजेट है जो ऊपरी विजेट ट्री बदलने पर CustomPainter को पुनः चित्रित होने से रोकता है। यदि CustomPainter स्थिर है, तो इसे अलग करने के लिए RepaintBoundary में लपेटें।

बार-बार पुनः चित्रण वाले एनिमेटेड CustomPainter के लिए, shouldRepaint के साथ Ticker या AnimationController का उपयोग करें जो एनिमेटेड मान के प्रत्येक परिवर्तन पर true लौटाता है। shouldRepaint में एनिमेटेड फ़ील्ड की तुलना करना इष्टतम है, न कि बिना आवश्यकता के प्रत्येक फ्रेम पर पुनः चित्रित करना। जटिल ग्रेडिएंट के लिए Rect कैशिंग: यदि ग्रेडिएंट रंग नहीं बदलते हैं, तो आप Paint.shader के माध्यम से Shader को कैश कर सकते हैं।

अक्सर पूछे जाने वाले प्रश्न

Flutter में CustomPainter और Canvas में क्या अंतर है?

CustomPainter एक अनुबंध क्लास है जो परिभाषित करता है कि Canvas पर क्या और कैसे चित्रित करना है। Canvas स्वयं ड्रॉइंग ऑब्जेक्ट है, जो विधियाँ प्रदान करता है (drawCircle, drawLine आदि)। CustomPainter paint विधि के माध्यम से Canvas प्राप्त करता है और इसके उपयोग को नियंत्रित करता है। एक Canvas का उपयोग अलग-अलग समय पर विभिन्न CustomPainter द्वारा किया जा सकता है।

क्या CustomPainter का उपयोग CustomPaint के बिना किया जा सकता है?

नहीं, CustomPainter का CustomPaint के बिना कोई अर्थ नहीं है। CustomPaint वह विजेट है जो CustomPainter की paint विधि को कॉल करता है और परिणाम स्क्रीन पर प्रदर्शित करता है। CustomPaint के बिना, Canvas नहीं बनेगा और paint निष्पादित नहीं होगा। हालांकि, आप Canvas के साथ अपना स्वयं का RenderObject लागू कर सकते हैं, लेकिन यह निम्न-स्तरीय दृष्टिकोण है।

CustomPainter को कैसे एनिमेट करें?

कंस्ट्रक्टर पैरामीटर के माध्यम से एनिमेटेड मान CustomPainter में पास करते हुए, Ticker के साथ AnimationController का उपयोग करें। जब मान बदलता है, तो CustomPaint वाले विजेट में setState() कॉल करें, जो shouldRepaint कॉल को ट्रिगर करता है। यदि shouldRepaint true लौटाता है, तो सिस्टम नए एनिमेशन फ्रेम के लिए paint कॉल करता है।

डेटा बदलने पर CustomPainter अपडेट क्यों नहीं होता?

कारण लगभग हमेशा shouldRepaint का false लौटाना है। जाँच करें कि oldDelegate फ़ील्ड नए मानों के साथ सही ढंग से तुलना की जा रही हैं या नहीं। यदि परिवर्तनीय ऑब्जेक्ट का उपयोग किया जाता है, तो shouldRepaint परिवर्तनों का पता नहीं लगा सकता क्योंकि ऑब्जेक्ट संदर्भ समान रहता है। सही तुलना के लिए == या अपरिवर्तनीय ऑब्जेक्ट का उपयोग करें।

क्या ReorderableListView में एनिमेशन के लिए CustomPainter का उपयोग किया जा सकता है?

हाँ, CustomPainter का उपयोग जटिल सूचियों में कस्टम सजावट चित्रित करने के लिए किया जाता है। हालांकि, ध्यान दें कि आइटम पुनर्क्रमित करते समय, ListView के अंदर RepaintBoundary प्रत्येक आइटम की रेंडरिंग कैश करता है। CustomPainter हल्का होना चाहिए और ड्रैग एनिमेशन को धीमा न करने के लिए paint में भारी ऑपरेशन नहीं होने चाहिए।

सारांश

  • CustomPainter — paint और shouldRepaint विधियों के साथ कस्टम 2D रेंडरिंग के लिए Flutter का एब्सट्रैक्ट क्लास
  • CustomPaint — विजेट जो ग्राफिक्स प्रदर्शित करने के लिए painter (पृष्ठभूमि) और foregroundPainter (अग्रभूमि) स्वीकार करता है
  • Canvas — ड्रॉइंग विधियों वाला ऑब्जेक्ट: drawLine, drawCircle, drawPath, drawRect, drawArc और अन्य
  • Paint — क्लास जो ड्रॉइंग शैली को परिभाषित करता है: रंग, मोटाई, शैली (fill/stroke), अपारदर्शिता और सम्मिश्रण मोड
  • shouldRepaint — अनुकूलन विधि जो केवल तभी true लौटाती है जब रेंडरिंग को प्रभावित करने वाले फ़ील्ड बदलते हैं
  • paint के अंदर ऑब्जेक्ट बनाना निषिद्ध है — 60 fps के लिए सभी Paint, Path, Rect कैश किए जाने चाहिए
  • RepaintBoundary — CustomPainter को ऊपरी विजेट ट्री के पुनः चित्रण से अलग करने के लिए विजेट

हम एक मोबाइल एप्लिकेशन टर्नकी विकसित करेंगे

IT Sectr 2017 से स्टार्टअप और व्यवसायों के लिए iOS और Android एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।

परियोजना पर चर्चा करें

यह भी पढ़ें