Android में Canvas — android.graphics पैकेज का एक क्लास है जो View पर 2D रेंडरिंग के लिए API प्रदान करता है। Canvas एक कैनवास की तरह काम करता है जिस पर डेवलपर विभिन्न draw* विधियों का उपयोग करके ज्यामितीय आकार, टेक्स्ट, इमेज और पथ बनाता है। Android डेवलपर्स डॉक्यूमेंटेशन (2025) के अनुसार, Canvas Android में कस्टम रेंडरिंग के लिए प्राथमिक उपकरण है और शैलियों और रंगों को परिभाषित करने के लिए Paint क्लास के साथ उपयोग किया जाता है। प्रत्येक onDraw() कॉल को View के bitmap बफर से जुड़ा एक तैयार Canvas इंस्टेंस प्राप्त होता है।
मुख्य बातें
Canvas — Android में केंद्रीय 2D ग्राफ़िक्स क्लास है जो एक प्लेन पर ड्राइंग के लिए विधियाँ प्रदान करता है। प्रत्येक Canvas एक Bitmap से जुड़ा होता है — एक मेमोरी क्षेत्र जहाँ ड्राइंग ऑपरेशन के परिणाम रिकॉर्ड किए जाते हैं। जब View को फिर से रेंडर किया जाता है, सिस्टम onDraw() में एक Canvas पास करता है जो पहले से उस View के बफर से जुड़ा होता है।
Canvas एक कोऑर्डिनेट सिस्टम में काम करता है जहाँ (0,0) ऊपरी बाएँ कोना है, X अक्ष दाएँ जाता है, Y अक्ष नीचे जाता है। सभी ड्राइंग ऑपरेशन Canvas की वर्तमान स्थिति का उपयोग करते हैं, जिसमें ट्रांसफ़ॉर्मेशन मैट्रिक्स, क्लिपिंग क्षेत्र और Paint शैली शामिल है। Android डॉक्यूमेंटेशन (2025) के अनुसार, Canvas API में विभिन्न प्रकार के ग्राफ़िक प्रिमिटिव के लिए 30 से अधिक draw* विधियाँ शामिल हैं।
Android 3.0 (API 11) से Canvas DisplayList के माध्यम से हार्डवेयर एक्सेलेरेशन का समर्थन करता है। एक्सेलेरेटेड मोड में, Canvas ऑपरेशन DisplayList में रिकॉर्ड किए जाते हैं और फिर GPU पर निष्पादित होते हैं। यह महत्वपूर्ण प्रदर्शन लाभ देता है लेकिन सीमाएँ लगाता है: कुछ Canvas ऑपरेशन (गैर-Path क्लिप के साथ clipPath) एक्सेलेरेटेड मोड में समर्थित नहीं हैं।
Canvas बुनियादी प्रिमिटिव ड्राइंग के लिए विधियों का एक सेट प्रदान करता है। प्रत्येक विधि ज्यामितीय पैरामीटर और एक Paint ऑब्जेक्ट स्वीकार करती है जो दृश्य शैली को परिभाषित करता है।
| विधि | उद्देश्य | उदाहरण |
|---|---|---|
| drawRect() | आयत बनाता है | canvas.drawRect(10f, 10f, 100f, 100f, paint) |
| drawCircle() | वृत्त बनाता है | canvas.drawCircle(50f, 50f, 30f, paint) |
| drawLine() | रेखा बनाता है | canvas.drawLine(0f, 0f, 100f, 100f, paint) |
| drawText() | टेक्स्ट बनाता है | canvas.drawText(“Hello”, 10f, 20f, paint) |
| drawBitmap() | इमेज बनाता है | canvas.drawBitmap(bitmap, 0f, 0f, paint) |
| drawPath() | मनमाना पथ बनाता है | canvas.drawPath(path, paint) |
| drawOval() | अंडाकार बनाता है | canvas.drawOval(rectF, paint) |
| drawArc() | चाप या सेक्टर बनाता है | canvas.drawArc(rectF, 0f, 90f, true, paint) |
प्रत्येक विधि को किसी भी क्रम में बुलाया जा सकता है — Canvas कॉल के क्रम में बनाता है, नए तत्वों को पिछले वाले के ऊपर रखता है। जटिल रचनाओं के लिए, Canvas स्थिति को सहेजने और पुनर्स्थापित करने के साथ मल्टी-लेयर रेंडरिंग तकनीक का उपयोग किया जाता है।
Paint — वह क्लास है जो यह परिभाषित करता है कि Canvas कैसे बनाएगा। Paint के बिना, Canvas विधियाँ बेकार हैं — यह रंग, रेखा मोटाई, भराव शैली, टेक्स्ट आकार, प्रभाव (छाया, ग्रेडिएंट, धुंधलापन) और ब्लेंडिंग मोड सेट करता है।
Paint के मुख्य गुण हैं: color (रंग), style (FILL, STROKE या FILL_AND_STROKE), strokeWidth (रेखा मोटाई), textSize (टेक्स्ट आकार), isAntiAlias (एंटी-एलियासिंग), shader (ग्रेडिएंट या इमेज)। Paint ऑब्जेक्ट बनाना एक महँगा ऑपरेशन है, इसलिए इसे एक बार बनाकर पुनः उपयोग करना चाहिए।
private val fillPaint = Paint().apply {
color = Color.parseColor("#FF6200EE")
style = Paint.Style.FILL
isAntiAlias = true
}
private val strokePaint = Paint().apply {
color = Color.WHITE
style = Paint.Style.STROKE
strokeWidth = 4f
isAntiAlias = true
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
canvas.drawCircle(100f, 100f, 80f, fillPaint)
canvas.drawCircle(100f, 100f, 80f, strokePaint)
}
इस उदाहरण में, दो Paint ऑब्जेक्ट का उपयोग किया गया है: एक वृत्त को बैंगनी रंग से भरने के लिए, दूसरा सफेद रेखा के लिए। भराव और रेखा को अलग करना एक मानक अभ्यास है जो ऑब्जेक्ट को पुनः बनाए बिना दिखावट पर लचीला नियंत्रण प्रदान करता है।
ग्रेडिएंट भराव के लिए, Paint एक Shader स्वीकार करता है — उपवर्ग LinearGradient, RadialGradient, SweepGradient। Shader setShader() विधि के माध्यम से Paint से जुड़ता है और यह परिभाषित करता है कि रंग ड्राइंग क्षेत्र में कैसे बदलता है।
Canvas कोऑर्डिनेट सिस्टम के मैट्रिक्स ट्रांसफ़ॉर्मेशन का समर्थन करता है: translate() (स्थानांतरण), rotate() (घूर्णन), scale() (स्केलिंग) और skew() (तिरछापन)। ट्रांसफ़ॉर्मेशन संचित होते हैं: प्रत्येक बाद का कॉल पिछले वाले के ऊपर लागू होता है।
ट्रांसफ़ॉर्मेशन स्टैक का प्रबंधन save() और restore() के माध्यम से किया जाता है। save() वर्तमान Canvas स्थिति (मैट्रिक्स, क्लिप) को स्टैक में सहेजता है, restore() अंतिम सहेजी गई स्थिति को पुनर्स्थापित करता है। save() और restore() के बीच नेस्टेड ट्रांसफ़ॉर्मेशन लागू किए जा सकते हैं।
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
canvas.save() // Save initial state
canvas.translate(100f, 100f) // Translate origin
// First square
canvas.drawRect(0f, 0f, 50f, 50f, fillPaint)
canvas.save() // Save after translate
canvas.rotate(45f, 25f, 25f) // Rotate around square center
// Rotated square
canvas.drawRect(0f, 0f, 50f, 50f, strokePaint)
canvas.restore() // Restore after rotate
canvas.restore() // Restore initial state
}
हमेशा ट्रांसफ़ॉर्मेशन शुरू करने से पहले save() और उन्हें पूरा करने के बाद restore() का उपयोग करें। असंतुलित save/restore मैट्रिक्स संचय और बाद के तत्वों के गलत रेंडरिंग की ओर ले जाता है।
जटिल ग्राफ़िक्स के लिए, Canvas को Bitmap और Path के साथ जोड़ा जाता है। Bitmap का उपयोग इमेज लोड करने और रेंडर किए गए फ्रेम को कैश करने के लिए किया जाता है। Path का उपयोग मनमाने बेज़ियर वक्र, बहुभुज और जटिल आकृति बनाने के लिए किया जाता है।
ऑफ़स्क्रीन रेंडरिंग तकनीक: एक Bitmap बनाया जाता है, उस पर एक अलग Canvas के माध्यम से एक जटिल दृश्य बनाया जाता है, और फिर तैयार Bitmap को drawBitmap() के माध्यम से onDraw() में आउटपुट किया जाता है। यह प्रत्येक फ्रेम पर पूर्ण पुनः रेंडरिंग के बिना जटिल ग्राफ़िक्स को अपडेट करने की अनुमति देता है।
private var offscreenBitmap: Bitmap? = null
private var offscreenCanvas: Canvas? = null
fun buildOffscreenScene(width: Int, height: Int) {
offscreenBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
offscreenCanvas = Canvas(offscreenBitmap)
// Render scene once
offscreenCanvas!!.drawColor(Color.WHITE)
drawGrid(offscreenCanvas!!)
drawComplexShape(offscreenCanvas!!)
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
offscreenBitmap?.let { canvas.drawBitmap(it, 0f, 0f, null) }
}
Path का उपयोग जटिल आकृति बनाने के लिए किया जाता है: बेज़ियर वक्र (quadTo, cubicTo), चाप (arcTo), रेखाएँ (lineTo)। Path भरे हुए आकार के लिए बंद (close()) या रेखाओं के लिए खुला हो सकता है। मुख्य drawPath() विधि अंतिम रेंडरिंग के लिए Path और Paint को जोड़ती है।
Canvas रेंडरिंग प्रदर्शन सीधे एप्लिकेशन FPS को प्रभावित करता है। मुख्य समस्याएँ: onDraw() में अत्यधिक आवंटन, बार-बार invalidate() कॉल और हार्डवेयर एक्सेलेरेशन का उप-इष्टतम उपयोग।
Paint, Path, Rect, RectF और अन्य ऑब्जेक्ट एक बार इनिशियलाइज़र या setup() विधि में बनाए जाने चाहिए। onDraw() में प्रत्येक आवंटन गार्बेज कलेक्टर पर दबाव बनाता है, जिससे माइक्रो-लैग होते हैं। अपवाद अपरिवर्तनीय ऑब्जेक्ट के लिए static या companion object है।
यदि अधिकांश View दृश्य क्षेत्र के बाहर छिपा है (उदाहरण के लिए, ScrollView में), तो रेंडरिंग सीमित करने के लिए canvas.clipRect() का उपयोग करें। इस मामले में हार्डवेयर एक्सेलेरेशन अदृश्य पिक्सेल की क्लिपिंग को अतिरिक्त रूप से अनुकूलित करता है।
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
// Clip to visible area
canvas.save()
canvas.clipRect(scrollX, scrollY, scrollX + width, scrollY + height)
// Render large scene
renderScene(canvas)
canvas.restore()
}
जटिल Canvas ग्राफ़िक्स वाले Views के लिए जो शायद ही कभी अपडेट होते हैं, LAYER_TYPE_HARDWARE के साथ View.setLayerType() का उपयोग करें। बार-बार अपडेट होने वाले एनिमेशन के लिए, महँगे हार्डवेयर लेयर अपडेट से बचने के लिए LAYER_TYPE_NONE का उपयोग करें। GPU Profile Rendering और Android Studio Profiler का उपयोग करके प्रोफ़ाइल करें।
अक्सर पूछे जाने वाले प्रश्न
हाँ, आप Canvas(Bitmap) बना सकते हैं — एक कंस्ट्रक्टर जो Bitmap स्वीकार करता है। इसका उपयोग ऑफ़स्क्रीन रेंडरिंग के लिए किया जाता है: आप Bitmap पर बनाते हैं, फिर इसे drawBitmap() के माध्यम से आउटपुट करते हैं। Canvas Surface (SurfaceView के लिए) या Picture के माध्यम से भी बनाया जा सकता है।
Canvas — UI थ्रेड में View पर ड्राइंग के लिए API है। SurfaceView — एक अलग Surface है जो अपने स्वयं के Canvas (lockCanvas() / unlockCanvasAndPost()) के माध्यम से बैकग्राउंड थ्रेड से अपडेट हो सकता है। SurfaceView गेम और वीडियो के लिए प्राथमिकता है।
सबसे आम कारण असंतुलित save() और restore() है। यदि ट्रांसफ़ॉर्मेशन (translate, rotate) के बाद restore() नहीं बुलाया जाता है, तो Canvas एक संशोधित कोऑर्डिनेट सिस्टम में रहता है, और बाद के तत्व ऑफ़सेट के साथ बनाए जाते हैं। अपने save()/restore() जोड़े जाँचें।
क्षैतिज केंद्रीकरण के लिए Paint.setTextAlign(Paint.Align.CENTER) और ऊर्ध्वाधर के लिए Paint.getTextBounds() या Paint.descent() / ascent() का उपयोग करें। केंद्रीकरण: canvas.drawText(टेक्स्ट, centerX, centerY - (ascent + descent) / 2, paint).
Canvas स्वयं एनिमेट नहीं करता — यह केवल वर्तमान स्थिति बनाता है। एनिमेशन invalidate() (या postInvalidateOnAnimation()) के क्रमिक कॉल के माध्यम से प्राप्त होता है, हर बार onDraw() में एक नया फ्रेम बनाता है। स्मूथ एनिमेशन के लिए Vsync के साथ सिंक करने के लिए ValueAnimator या Choreographer का उपयोग करें।
सारांश
हम एक मोबाइल एप्लिकेशन टर्नकी विकसित करेंगे
IT Sectr 2017 से स्टार्टअप और व्यवसायों के लिए iOS और Android एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।
यह भी पढ़ें