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 ایپلیکیشنز بناتا ہے۔ ہم آپ کو مشورہ دیں گے اور بہترین حل تجویز کریں گے۔

پروجیکٹ پر بحث کریں

مزید پڑھیں