onDraw() — यह क्या है, कॉल तंत्र और विधि ओवरराइड

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

onDraw() Android SDK में View क्लास का एक महत्वपूर्ण मेथड है, जो किसी व्यू की सामग्री को ड्रा करने के लिए जिम्मेदार है। सिस्टम onDraw को View की उपस्थिति के हर अपडेट पर कॉल करता है — शुरुआती रेंडरिंग के दौरान, invalidate() के बाद या आयाम बदलने पर। Android Developers Documentation (2026) के अनुसार, Canvas API का उपयोग करके onDraw को ओवरराइड करना Android एप्लिकेशनों में कस्टम ग्राफिक्स बनाने का प्राथमिक तरीका है।

मुख्य बातें

  • onDraw(Canvas) — View का एक मेथड जिसे सिस्टम Canvas पर सामग्री खींचने के लिए कॉल करता है
  • invalidate() — View को दोबारा खींचने का अनुरोध, जो अगले फ्रेम साइकल में onDraw को कॉल करता है
  • Canvas API ड्राइंग के लिए drawCircle, drawBitmap, drawText, drawPath और अन्य मेथड प्रदान करता है
  • Android सिस्टम UI थ्रड पर ड्राइंग करता है, इसलिए onDraw हल्का और तेज़ होना चाहिए
  • Hardware acceleration Android 3.0 (API 11) से शुरू करके GPU के माध्यम से ड्राइंग को स्वचालित रूप से तेज़ करता है

onDraw() क्या है?

onDraw(Canvas canvas) android.view.View क्लास का एक protected मेथड है, जिसे Android सिस्टम तब कॉल करता है जब View को खींचने की आवश्यकता होती है। डेवलपर कस्टम ड्राइंग को लागू करने के लिए इस मेथड को ओवरराइड करता है: आकार, टेक्स्ट, छवियां, ग्रैडिएंट, एनिमेशन। Canvas पैरामीटर एक ग्राफिकल सतह है जिस पर सभी ड्राइंग ओपरेशन किए जाते हैं।

मेथड पर हस्ताक्षर सरल है: override fun onDraw(canvas: Canvas)। इस मेथड के अंदर नए ऑब्जेक्ट नहीं बनाने चाहिए (GC के बोझ से बचने के लिए), लंबे ओपरेशन नहीं करने चाहिए या नेटवर्क के साथ काम नहीं करना चाहिए। View अपने लाइफसाइकल में onLayout (स्थिति गणना) और dispatchDraw (चाइल्ड एलिमेंट खींचना) के बीच onDraw मेथड को भी शामिल करता है।

View से इनहैरिट करने पर, कोई भी सामग्री प्रदर्शित करने के लिए onDraw को ओवरराइड करना अनिवार्य है — अन्यथा View खाली होगी। मौजूदा उपवर्गों (TextView, ImageView, Button) से इनहैरिट करने पर, onDraw को ओवरराइड करना ऐच्छिक है और मानक सामग्री के ऊपर अतिरिक्त ग्राफिक्स जोड़ने के लिए उपयोग किया जाता है।

View ड्राइंग साइकल

Android मुख्य थ्रड (UI thread) से बुलाए गए सख्त रूप से परिभाषित अनुक्रम में View ड्राइंग करता है। पूर्ण साइकल में तीन चरण होते हैं: measure (आयाम मापना), layout (स्थिति गणना) और draw (रेंडरिंग)। onDraw draw चरण का हिस्सा है और View के आयाम और स्थिति निर्धारित होने के बाद बुलाया जाता है।

draw चरण: dispatchDraw और onDraw

draw(Canvas canvas) View का एक सार्वजनिक मेथड है जो onDraw और dispatchDraw को कॉल करता है। draw मेथड को ओवरराइड करने के लिए डिजाइन नहीं किया गया है — इसके बजाय, onDraw को ओवरराइड किया जाता है। वर्तमान View के लिए onDraw निष्पादित होने के बाद, dispatchDraw को बुलाया जाता है, जो सभी चाइल्ड View के लिए draw को पुनरावर्ती रूप से बुलाता है (यदि वर्तमान View एक ViewGroup कंटेनर है)।

सिस्टम onDraw कब बुलाता है

onDraw निम्नलिखित स्थितियों में बुलाया जाता है: 1) View पहली बार दिखाई देती है (setVisibility(VISIBLE) के बाद); 2) एप्लिकेशन इस View या इसके पैरेंट पर invalidate() कॉल करता है; 3) View का आकार बदलता है (नया layout); 4) View से संबंधित एनिमेशन बदलता है (ValueAnimator या ObjectAnimator के माध्यम से); 5) View की स्थिति बदलती है (pressed, focused, enabled)।

हार्डवेयर एक्सेलरेशन

Android 3.0 (API 11) से, अधिकांश Canvas ओपरेशन GPU के माध्यम से हार्डवेयर एक्सेलरेटेड होते हैं। डेवलपर canvas.isHardwareAccelerated() के माध्यम से जाँच सकता है कि एक्सेलरेशन सक्षम है या नहीं। हार्डवेयर एक्सेलरेशन के साथ, कुछ Canvas ओपरेशन समर्थित नहीं होते (जैसे कि गैर-आयताकार क्षेत्र के साथ clipPath) और उन्हें अनुदेशित किया जा सकता है या वे त्रुटियाँ पैदा कर सकते हैं।

कस्टम ग्राफिक्स के लिए Canvas API

Canvas ड्राइंग मेथड्स का एक समृद्ध सेट प्रदान करता है। सभी मेथड वर्तमान निर्देशांक प्रणाली में काम करते हैं, जिसे रूपांतरणों (translate, rotate, scale, skew) के माध्यम से बदला जा सकता है। प्रत्येक मेथड एक Paint ऑब्जेक्ट स्वीकार करता है जो रंग, शैली, रेखा मोटाई, प्रभाव और एंटी-एलियसिंग को परिभाषित करता है।

Canvas मेथडउद्देश्यPaint के मुख्य पैरामीटर
drawCircleवृत्त खींचनाcenterX, centerY, radius, paint
drawRectआयत खींचनाleft, top, right, bottom, paint
drawLineरेखा खींचनाstartX, startY, endX, endY, paint
drawPathमनमाना पथ खींचनाpath, paint
drawBitmapबिटमैप छवि खींचनाbitmap, srcRect, dstRect, paint
drawTextटेक्स्ट खींचनाtext, x, y, paint
drawArcचाप या सेक्टर खींचनाovalRect, startAngle, sweepAngle, useCenter, paint
drawOvalअंडाकार खींचनाovalRect, paint

Paint ऑब्जेक्ट

Paint ड्राइंग शैली को परिभाषित करता है: रंग (setColor), रेखा मोटाई (setStrokeWidth), भरने की शैली (setStyle — FILL, STROKE, FILL_AND_STROKE), एंटी-एलियसिंग (setAntiAlias), प्रभाव (setShadowLayer, setMaskFilter) और ग्रैडिएंट (setShader)। Paint को View कंस्ट्रक्टर में एक बार बनाने और कॉन्फ़िगर करने की अनुशंसा की जाती है, onDraw के अंदर नहीं, ताकि ड्राइंग लूप में ऑब्जेक्ट निर्माण से बचा जा सके।

निर्देशांक और रूपांतरण

Canvas एक निर्देशांक प्रणाली का उपयोग करता है जहाँ X-अक्ष दाएँ और Y-अक्ष नीचे की ओर इशारा करता है। मूल बिंदु (0, 0) View का ओपरी बाएँ कोना है। draw मेथड कॉल करने से पहले, डेवलपर canvas.translate(dx, dy), canvas.rotate(degrees, px, py), canvas.scale(sx, sy, px, py) के माध्यम से निर्देशांक प्रणाली को बदल सकता है। सभी बाद के ड्राइंग ओपरेशन रूपांतरित प्रणाली में किए जाएँगे।

onDraw का प्रदर्शन

onDraw मुख्य UI थ्रड पर निष्पादित होता है, और इसकी अवधि सीधे फ्रेम दर (fps) को प्रभावित करती है। 60 fps बनाए रखने के लिए, onDraw मेथड को 16 मिलीसेकंड के भीतर पूरा होना चाहिए। कोई भी मन्दी फ्रेम ड्रॉप (jank) का कारण बनती है, जो दृश्य रूप से एनिमेशन हॅटकने या स्क्रॉल में देरी के रूप में दिखाई देती है।

onDraw प्रदर्शन के नियम

मुख्य नियम onDraw ऑप्टिमाइजेशन के लिए: 1) onDraw के अंदर ऑब्जेक्ट न बनाएं — सभी Paint, Path, Rect ऑब्जेक्ट क्लास फ़ील्ड होने चाहिए; 2) मेमरी आवंटित (new) न करें — यह गार्बेज कलेक्शन (GC) और फ्रेम ड्रॉप का कारण बनता है; 3) जटिल ओपरेशनों को Bitmap.createBitmap के माध्यम से Bitmap में कैश करें और तैयार Bitmap को ड्रा करें; 4) I/O ओपरेशन या संसाधन लोडिंग न करें।

ऑप्टिमाइजेशन के लिए clipRect का उपयोग

clipRect ड्राइंग क्षेत्र को एक निर्दिष्ट आयत तक सीमित करता है। इसका उपयोग Canvas को दृश्य क्षेत्र के बाहर पिक्सल खींचने में समय बर्बाद करने से रोकने के लिए किया जाता है। यह विशेष रूप से बड़ी सूचियों को स्क्रॉल करते समय या जूम करते समय प्रभावी होता है: clipRect को दृश्य क्षेत्र (dirty rect) पर सेट करें, और Canvas केवल वही खींचेगा जो दिखाई देता है।

Layer — सहेज और पुनर्स्थापन

canvas.save() Canvas की वर्तमान स्थिति (रूपांतरण और clip) को एक स्टैक पर सहेज करता है। canvas.restore() अंतिम सहेजित स्थिति को पुनर्स्थापित करता है। यह अस्थायी रूपांतरणों के लिए आवश्यक है: स्थिति सहेज करें, translate/rotate लागू करें, ड्रा करें, फिर पुनर्स्थापित करें। save और restore हल्के होते हैं और उचित उपयोग (10–15 से कम नेस्टिंग स्तर) पर प्रदर्शन को प्रभावित नहीं करते।

invalidate और postInvalidate

invalidate() View का एक मेथड है जो सिस्टम को बताता है कि View की सामग्री पुरानी हो गई है और उसे दोबारा खींचने की आवश्यकता है। invalidate कॉल करने से एक नया draw साइकल शुरू होता है जिसमें onDraw बुलाया जाएगा। invalidate को केवल UI थ्रड (मुख्य थ्रड) से ही बुलाया जाना चाहिए। पृष्ठभूमि थ्रड से बुलाने के लिए postInvalidate का उपयोग किया जाता है।

postInvalidate() invalidate का एक थ्रड-सेफ संस्करण है जो Handler के माध्यम से मुख्य थ्रड की क्यू में पुनर्लेखन अनुरोध भेजता है। इसका उपयोग पृष्ठभूमि कार्यों में किया जाता है जब डेटा लोडिंग या गणनाओं के बाद View को अपडेट करने की आवश्यकता होती है। इसे UI सिंक्रोनिजेशन के लिए runOnUiThread के साथ जोड़ा जा सकता है।

आंशिक पुनर्लेखन के लिए, invalidate(Rect dirty) या invalidate(int l, int t, int r, int b) का उपयोग करें। यह सिस्टम को बताता है कि पूरे View में नहीं, बल्कि केवल निर्दिष्ट क्षेत्र बदला है। Android केवल dirty rect को पुनर्लेखित करके ड्राइंग को ऑप्टिमइज़ करता है, जो आंशिक अपडेट के साथ एनिमेशन में प्रदर्शन में काफी सुधार करता है।

Kotlin में कोड उदाहरण

आइए Kotlin का उपयोग करके Android में कस्टम View बनाने के लिए onDraw को ओवरराइड करने के व्यावहारिक उदाहरण देखें।

कस्टम View — वृत्ताकार प्रगति

यह उदाहरण एनिमेटेड भरने के साथ एक वृत्ताकार प्रगति संकेतक बनाता है। onDraw दो वृत्त खींचता है: एक ग्रे पृष्ठभूमि वृत्त और एक रंगीन भरने वाला वृत्त जिसका चाप वर्तमान प्रगति द्वारा निर्धारित होता है। setProgress में invalidate कॉल करने से मान बदलने पर पुनर्लेखन सुनिश्चित होता है।

kotlin
class CircularProgressView
    @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null
) : View(context, attrs) {

    private val bgPaint = Paint().apply {
        style = Paint.Style.STROKE
        strokeWidth = 12f
        color = Color.parseColor("#E0E0E0")
        isAntiAlias = true
    }

    private val progressPaint = Paint().apply {
        style = Paint.Style.STROKE
        strokeWidth = 12f
        color = Color.BLUE
        isAntiAlias = true
        strokeCap = Paint.Cap.ROUND
    }

    var progress: Float = 0f
        set(value) {
            field = value.coerceIn(0f, 1f)
            invalidate()
        }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        val size = minOf(width, height) - 24f
        val oval = RectF(12f, 12f,
                          12f + size, 12f + size)

        canvas.drawArc(oval, 270f, 360f, false, bgPaint)
        canvas.drawArc(oval, 270f,
                        progress * 360f,
                        false, progressPaint)
    }
}

कस्टम View — टेक्स्ट के साथ ग्रैडिएंट पृष्ठभूमि

यह उदाहरण ग्रैडिएंट के साथ एक आयत और उसके ऊपर टेक्स्ट खींचता है। ग्रैडिएंट LinearGradient (Shader) के माध्यम से बनाया जाता है, और टेक्स्ट drawText के माध्यम से। दोनों Paint ऑब्जेक्ट कंस्ट्रक्टर में एक बार बनाए जाते हैं, जबकि onDraw केवल View की वर्तमान चौड़ाई के आधार पर आयत का आकार अपडेट करता है।

kotlin
class GradientTextView(context: Context)
    : View(context) {

    private val shaderPaint = Paint().apply {
        isAntiAlias = true
    }

    private val textPaint = Paint().apply {
        color = Color.WHITE
        textSize = 48f
        isAntiAlias = true
        textAlign = Paint.Align.CENTER
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)

        val gradient = LinearGradient(
            0f, 0f, width.toFloat(), 0f,
            Color.parseColor("#FF6B35"),
            Color.parseColor("#FF0040"),
            Shader.TileMode.CLAMP
        )
        shaderPaint.shader = gradient
        canvas.drawRect(0f, 0f,
                        width.toFloat(),
                        height.toFloat(), shaderPaint)

        val xCenter = width / 2f
        val yCenter = height / 2f
        val yOffset = (textPaint.descent() +
                        textPaint.ascent()) / 2f

        canvas.drawText("Hello from Canvas",
                      xCenter, yCenter - yOffset,
                      textPaint)
    }
}

invalidate का उपयोग करके एनिमेटेड घड़ी

यह उदाहरण एक एनिमेटेड घड़ी बनाता है जो हर 1000 मिलीसेकंड में ड्राइंग को अपडेट करती है। onDraw के अंदर postDelayed एक सेकंड के बाद invalidate को कॉल करता है, एक अनंत पुनर्लेखन लूप बनाता है। घड़ी की सुईयां अलग-अलग लंबाई और मोटाई के साथ drawLine के माध्यम से खींची जाती हैं।

kotlin
class AnalogClockView(context: Context)
    : View(context) {

    private val handPaint = Paint().apply {
        style = Paint.Style.STROKE
        isAntiAlias = true
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        val cx = width / 2f
        val cy = height / 2f
        val radius = minOf(cx, cy) - 20f

        val now = Calendar.getInstance()
        val hours = now.get(Calendar.HOUR) % 12
        val minutes = now.get(Calendar.MINUTE)
        val seconds = now.get(Calendar.SECOND)

        val secondAngle = Math.toRadians(
            seconds * 6f - 90f)
        handPaint.strokeWidth = 2f
        handPaint.color = Color.RED
        canvas.drawLine(cx, cy,
            cx + cos(secondAngle) * radius * 0.8f,
            cy + sin(secondAngle) * radius * 0.8f,
            handPaint)

        postDelayed({ invalidate() }, 1000)
    }
}

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

क्या onDraw को सीधे बुलाया जा सकता है?

नहीं, onDraw को सीधे नहीं बुलाना चाहिए। पुनर्लेखन का अनुरोध करने के लिए, invalidate() (UI थ्रड से) या postInvalidate() (पृष्ठभूमि थ्रड से) का उपयोग करें। सिस्टम तय करेगा कि onDraw कब बुलाना है और एकाधिक invalidate कॉल को एक पास में विलय करके ड्राइंग को ऑप्टिमइज़ करेगा।

invalidate के बाद onDraw क्यों नहीं बुलाया जाता?

कारण: View छिपी हुई है (setVisibility(GONE) या INVISIBLE); View को Window पदानुक्रम में नहीं जोड़ा गया; View का आकार 0 है (चौड़ाई या ऊंचाई = 0); setWillNotDraw(true) बुलाया गया है (डिफ़ॉल्ट रूप से ViewGroup के लिए true)। डिबग करते समय इनमें से प्रत्येक बिंदु की जाँच करें।

onDraw कितनी बार बुलाया जा सकता है?

60 fps पर, onDraw प्रति सेकंड 60 बार तक बुलाया जा सकता है। 120 fps पर (120 Hz डिस्प्ले वाले उपकरणों पर) — 120 बार तक। प्रत्येक कॉल लगभग 8–16 मिलीसेकंड में पूरा होना चाहिए। ObjectAnimator या ValueAnimator के माध्यम से सक्रिय एनिमेशन के दौरान, आवृत्ति एनिमेशन फ्रेम की संख्या द्वारा निर्धारित की जाती है।

onDraw और dispatchDraw में क्या अंतर है?

onDraw View की स्वयं की सामग्री खींचने के लिए जिम्मेदार है। dispatchDraw चाइल्ड View (ViewGroup में) खींचने के लिए जिम्मेदार है। dispatchDraw onDraw के बाद बुलाया जाता है और सभी चाइल्ड एलिमेंट के लिए पुनरावर्ती रूप से जाता है। एक सामान्य View (कोई ViewGroup नहीं) के लिए, dispatchDraw खाली होता है।

क्या Canvas का उपयोग onDraw के बाहर किया जा सकता है?

हाँ, Canvas को Canvas(bitmap) के माध्यम से Bitmap के लिए बनाया जा सकता है और किसी भी थ्रड पर उस पर ड्रा किया जा सकता है। इसका उपयोग पृष्ठभूमि में जटिल ग्राफिक्स को प्री-रेंडर करने के लिए किया जाता है। हालाँकि, onDraw को पास किया गया Canvas सिस्टम का है और इसे केवल onDraw मेथड के अंदर UI थ्रड पर ही इस्तेमाल किया जा सकता है।

सारांश

  • onDraw(Canvas) — Android में Canvas API का उपयोग करके कस्टम ड्राइंग के लिए मुख्य View मेथड
  • ड्राइंग साइकल में measure, layout और draw चरण होते हैं — onDraw draw चरण पर बुलाया जाता है
  • Canvas API में drawCircle, drawRect, drawPath, drawBitmap, drawText और अन्य मेथड शामिल हैं
  • invalidate() UI थ्रड से पुनर्लेखन का अनुरोध करता है, postInvalidate() पृष्ठभूमि थ्रड से
  • आंशिक पुनर्लेखन invalidate(Rect) के माध्यम से केवल dirty क्षेत्र को अपडेट करके रेंडरिंग को ऑप्टिमइज़ करता है
  • onDraw प्रदर्शन महत्वपूर्ण है: विधि के अंदर ऑब्जेक्ट बनाने से GC और फ्रेम ड्रॉप होती है
  • हार्डवेयर एक्सेलरेशन (API 11 से) GPU के माध्यम से Canvas ओपरेशन को स्वचालित रूप से तेज़ करता है

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

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

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

यह भी पढ़ें