कैनवस ऑब्जेक्ट पर ड्रॉइंग करना

यह कोडलैब, Kotlin में बेहतर Android का हिस्सा है. अगर आप कोडलैब के क्रम में काम करते हैं, लेकिन यह ज़रूरी नहीं है, तो आपको इस कोर्स का पूरा फ़ायदा मिलेगा. सभी कोर्स कोडलैब Kotlin कोडलैब के लैंडिंग पेज पर बेहतर Android पेज पर दिए गए हैं.

परिचय

Android में, आपके पास व्यू में कस्टम 2D ग्राफ़िक और ऐनिमेशन लागू करने के लिए कई तकनीकें उपलब्ध हैं.

ड्रॉ करने लायक के इस्तेमाल के अलावा, आप Canvas क्लास के ड्रॉइंग के तरीकों का इस्तेमाल करके 2D ड्रॉइंग भी बना सकते हैं. Canvas 2D ड्रॉइंग प्लैटफ़ॉर्म है, जो ड्रॉइंग के तरीके बताता है. यह तब काम आता है, जब आपके ऐप्लिकेशन को लगातार अपने-आप फिर से काम करने की ज़रूरत होती है, क्योंकि उपयोगकर्ता को समय के साथ बदलाव दिखते हैं. इस कोडलैब में, आप View में दिखाए गए कैनवस को बनाने और बनाने का तरीका जान सकते हैं.

आप कैनवस पर, ये कार्रवाइयां कर सकते हैं:

  • पूरे कैनवस को रंग से भरें.
  • आयत, आकार, और पाथ जैसे आकार बनाने में मदद करें, जैसा कि Paint ऑब्जेक्ट में बताया गया है. Paint ऑब्जेक्ट में ज्यामिति को बनाने के तरीके (जैसे कि लाइन, आयत, अंडाकार, और पाथ) की शैली और रंग की जानकारी होती है. जैसे, टेक्स्ट का टाइपफ़ेस.
  • अनुवाद, स्केलिंग या कस्टम ट्रांसफ़ॉर्मेशन जैसे ट्रांसफ़ॉर्मेशन लागू करें.
  • क्लिप यानी कि कैनवस के आकार या पाथ को चुनकर, उसके दिखने वाले हिस्सों की जानकारी दें.

आप Android ड्रॉइंग के बारे में कैसे सोच सकते हैं (सुपर-आसान!)

Android या किसी दूसरे आधुनिक सिस्टम पर ड्रॉइंग करना, एक मुश्किल प्रोसेस है. इसमें, ऐब्स्ट्रैक्शन की लेयर, और हार्डवेयर के ऑप्टिमाइज़ेशन शामिल हैं. Android का ड्रॉ किस तरह एक दिलचस्प विषय है जिसके बारे में लिखा गया है. साथ ही, इसमें दी गई जानकारी भी इस कोडलैब के दायरे से बाहर है.

इस कोडलैब और उसके ऐप्लिकेशन के संदर्भ में, जो फ़ुल-स्क्रीन व्यू में कैनवस पर दिखता है, आप इस तरीके से इसे समझ सकते हैं.

  1. आप जो ड्रॉ कर रहे हैं उसे दिखाने के लिए आपको एक व्यू चाहिए. यह Android सिस्टम के उपलब्ध कराए गए व्यू में से एक हो सकता है. इसके अलावा, आप इस कोडलैब में, एक ऐसा कस्टम व्यू बनाते हैं जो आपके ऐप्लिकेशन (MyCanvasView) के कॉन्टेंट व्यू के तौर पर काम करता है.
  2. सभी व्यू की तरह, यह व्यू अपने कैनवस (canvas) के साथ आता है.
  3. किसी व्यू के कैनवस पर ड्रॉ करने के सबसे बुनियादी तरीके के लिए, आप उसके onDraw() तरीके को ओवरराइड करके उसके कैनवस पर ड्रॉ करते हैं.
  4. ड्रॉइंग बनाते समय, आपको पहले बनाई गई चीज़ों को कैश मेमोरी में सेव करना होगा. आपके डेटा को कैश करने के कई तरीके हैं, एक बिट मैप में है (extraBitmap). दूसरा तरीका है कि अपने संग्रह का इतिहास, निर्देशांक और निर्देशों के तौर पर सेव करना.
  5. कैनवस ड्रॉइंग API का इस्तेमाल करके, अपने कैशिंग बिट मैप (extraBitmap) पर ड्रॉइंग बनाने के लिए, आप कैश मेमोरी में सेव किए गए बिट मैप के लिए कैश मेमोरी में सेव करने वाला कैनवस (extraCanvas) बनाते हैं.
  6. इसके बाद, आप कैश मेमोरी में सेव किए गए कैनवस (extraCanvas) पर ड्रॉ करते हैं, जो आपके कैश मेमोरी बिट मैप (extraBitmap) पर दिखता है.
  7. स्क्रीन पर ड्रॉ की गई हर चीज़ को दिखाने के लिए, आप व्यू और #39;s कैनवस (canvas) को कैशिंग बिट मैप (extraBitmap) बनाने के लिए कहते हैं.

आपको क्या पता होना चाहिए

  • गतिविधि और बेसिक लेआउट की मदद से ऐप्लिकेशन बनाने और Android Studio का इस्तेमाल करके उसे चलाने का तरीका.
  • इवेंट हैंडलर को व्यू से जोड़ने का तरीका.
  • पसंद के मुताबिक व्यू बनाने का तरीका.

आप इन चीज़ों के बारे में जानेंगे

  • Canvas बनाने और उपयोगकर्ता के टच के जवाब में उसे बनाने का तरीका.

आप क्या कर पाएंगे!

  • ऐसा ऐप्लिकेशन बनाएं जो स्क्रीन को छूने वाले उपयोगकर्ता के जवाब में, स्क्रीन पर लाइन बनाता हो.
  • मोशन इवेंट को कैप्चर करें. साथ ही, स्क्रीन पर फ़ुल-स्क्रीन कस्टम व्यू में दिखने वाले कैनवस पर लाइन बनाएं.

MiniPaint ऐप्लिकेशन, उपयोगकर्ता के छूने के जवाब में एक लाइन दिखाने के लिए, कस्टम व्यू का इस्तेमाल करता है, जैसा कि नीचे स्क्रीनशॉट में दिखाया गया है.

पहला चरण. MiniPaint प्रोजेक्ट बनाएं

  1. मिनीपेंट नाम का एक नया Kotlin प्रोजेक्ट बनाएं, जो खाली गतिविधि टेंप्लेट का इस्तेमाल करता है.
  2. app/res/values/colors.xml फ़ाइल खोलें और यहां दिए गए दो रंगों को जोड़ें.
<color name="colorBackground">#FFFF5500</color>
<color name="colorPaint">#FFFFEB3B</color>
  1. styles.xml खोलें
  2. दी गई AppTheme शैली के पैरंट में, DarkActionBar को NoActionBar से बदलें. इससे ऐक्शन बार हट जाता है, ताकि आप फ़ुलस्क्रीन कर सकें.
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">

दूसरा चरण. MyCanvasView क्लास बनाएं

इस कदम में, आप ड्रॉइंग के लिए, एक कस्टम व्यू MyCanvasView बनाते हैं.

  1. app/java/com.example.android.minipaint पैकेज में, MyCanvasView नाम से एक नया > Kotlin फ़ाइल/क्लास बनाएं.
  2. MyCanvasView क्लास को View क्लास बढ़ाएं और context: Context में पास करें. सुझाए गए इंपोर्ट स्वीकार करें.
import android.content.Context
import android.view.View

class MyCanvasView(context: Context) : View(context) {
}

तीसरा चरण. MyCanvasView को कॉन्टेंट व्यू के तौर पर सेट करें

आप MyCanvasView में क्या बनाएंगे, यह दिखाने के लिए आपको इसे MainActivity के कॉन्टेंट व्यू के तौर पर सेट करना होगा.

  1. strings.xml खोलें और एक स्ट्रिंग तय करें, ताकि व्यू और #39; के कॉन्टेंट की जानकारी के लिए इस्तेमाल किया जा सके.
<string name="canvasContentDescription">Mini Paint is a simple line drawing app.
   Drag your fingers to draw. Rotate the phone to clear.</string>
  1. MainActivity.kt खोलें
  2. onCreate() में जाकर, setContentView(R.layout.activity_main) को मिटाएं.
  3. MyCanvasView का इंस्टेंस बनाएं.
val myCanvasView = MyCanvasView(this)
  1. इसके नीचे, myCanvasView के लेआउट के लिए फ़ुल स्क्रीन का अनुरोध करें. myCanvasView पर SYSTEM_UI_FLAG_FULLSCREEN फ़्लैग सेट करके ऐसा करें. इस तरह, व्यू पूरी तरह से स्क्रीन को भर देता है.
myCanvasView.systemUiVisibility = SYSTEM_UI_FLAG_FULLSCREEN
  1. कॉन्टेंट की जानकारी जोड़ें.
myCanvasView.contentDescription = getString(R.string.canvasContentDescription)
  1. इसके नीचे, कॉन्टेंट व्यू को myCanvasView पर सेट करें.
setContentView(myCanvasView)
  1. अपना ऐप्लिकेशन चलाएं. आपको पूरी तरह से सफ़ेद स्क्रीन दिखेगी, क्योंकि कैनवस का कोई साइज़ नहीं है और आपने अब तक कुछ भी नहीं बनाया है.

पहला चरण. onSizeChanged() बदलें

जब भी किसी व्यू का साइज़ बदलता है, तब Android सिस्टम onSizeChanged() तरीके का इस्तेमाल करता है. व्यू की शुरुआत बिना साइज़ के होती है, इसलिए ऐक्टिविटी के पहली बार बनाए जाने और उसे बढ़ाने के बाद, व्यू के onSizeChanged() तरीके को भी कॉल किया जाता है. इसलिए, व्यू और #39 साइज़ के कैनवस बनाने और सेट अप करने के लिए, यह onSizeChanged() तरीका सबसे सही जगह है.

  1. MyCanvasView में, क्लास लेवल पर, कैनवस और बिट मैप के लिए वैरिएबल तय करें. extraCanvas और extraBitmap को कॉल करें. ये पहले बनाई गई चीज़ों को कैश मेमोरी में सेव करने के लिए आपके बिट मैप और कैनवस हैं.
private lateinit var extraCanvas: Canvas
private lateinit var extraBitmap: Bitmap
  1. कैनवस के बैकग्राउंड के रंग के लिए, क्लास लेवल का वैरिएबल backgroundColor तय करें और उसे पहले तय किए गए colorBackground से शुरू करें.
private val backgroundColor = ResourcesCompat.getColor(resources, R.color.colorBackground, null)
  1. MyCanvasView में, onSizeChanged() वाले तरीके को बदलें. इस कॉलबैक तरीके को Android सिस्टम कहते हैं जिसमें बदले गए स्क्रीन डाइमेंशन होते हैं. इसका मतलब है कि नई चौड़ाई और ऊंचाई (जिसमें बदलाव करना है) और पुरानी चौड़ाई और ऊंचाई (जिससे बदलाव करना है).
override fun onSizeChanged(width: Int, height: Int, oldWidth: Int, oldHeight: Int) {
   super.onSizeChanged(width, height, oldWidth, oldHeight)
}
  1. onSizeChanged() के अंदर, नई चौड़ाई और ऊंचाई वाले Bitmap का एक इंस्टेंस बनाएं. ये स्क्रीन के आकार होते हैं और इन्हें extraBitmap को असाइन करें. तीसरा तर्क बिट मैप कलर कॉन्फ़िगरेशन है. ARGB_8888 हर रंग को 4 बाइट में स्टोर करता है और इसका सुझाव दिया जाता है.
extraBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
  1. extraBitmap से Canvas इंस्टेंस बनाएं और इसे extraCanvas को असाइन करें.
 extraCanvas = Canvas(extraBitmap)
  1. बैकग्राउंड का रंग बताएं, जिसमें extraCanvas को भरना है.
extraCanvas.drawColor(backgroundColor)
  1. onSizeChanged() को देखकर, हर बार फ़ंक्शन के काम करने पर एक नया बिट मैप और कैनवस बनाया जाता है. आपको एक नया बिट मैप चाहिए, क्योंकि साइज़ बदल गया है. हालांकि, यह मेमोरी का लीक होना है, जो पुराने बिट मैप के आस-पास ही रह गया है. इसे ठीक करने के लिए, super में कॉल के ठीक बाद यह कोड जोड़कर अगला कोड बनाने से पहले extraBitmap को रीसाइकल करें.
if (::extraBitmap.isInitialized) extraBitmap.recycle()

दूसरा चरण. onDraw() बदलें

MyCanvasView के लिए सभी ड्रॉइंग onDraw() में होती हैं.

शुरू करने के लिए, कैनवस दिखाएं. साथ ही, स्क्रीन को बैकग्राउंड के रंग से भरें जिसे आपने onSizeChanged() में सेट किया है.

  1. onDraw() को ओवरराइड करें और व्यू से जुड़े कैनवस पर extraBitmap कैश की गई सामग्री को ड्रॉ करें. drawBitmap() Canvas तरीका कई वर्शन में उपलब्ध है. इस कोड में, आप ऊपर बाएं कोने में बिट मैप, x और y निर्देशांक (और पिक्सल में) देते हैं, और Paint के लिए null, क्योंकि आप इसे बाद में सेट करेंगे.
override fun onDraw(canvas: Canvas) {
   super.onDraw(canvas)
canvas.drawBitmap(extraBitmap, 0f, 0f, null)
}


ध्यान दें कि onDraw() को भेजा गया कैनवस और सिस्टम, बिट मैप को दिखाने के लिए जिस कैनवस का इस्तेमाल करते हैं वह onSizeChanged() तरीके में बनाए गए कैनवस से अलग होता है. आप बिटमैप पर ड्रॉ करने के लिए भी इसका इस्तेमाल करते हैं.

  1. अपना ऐप्लिकेशन चलाएं. आपको बैकग्राउंड के खास रंग से पूरी स्क्रीन दिखाई देनी चाहिए.

ड्रॉ करने के लिए, आपको एक Paint ऑब्जेक्ट की ज़रूरत होती है, जो बताता है कि ड्रॉ किए जाने पर स्टाइल कैसे बनाई जाती है और Path, जो ड्रॉ की जा रही है.

पहला चरण. पेंट ऑब्जेक्ट शुरू करना

  1. MyCanvasView.kt में, सबसे ऊपर फ़ाइल लेवल पर, स्ट्रोक की चौड़ाई के लिए एक कॉन्सटेंट तय करें.
private const val STROKE_WIDTH = 12f // has to be float
  1. MyCanvasView के क्लास लेवल पर, जिस वैरिएबल के साथ ड्रॉ करना है उसे कलर होल्ड करने के लिए, एक वैरिएबल drawColor तय करें और इसे उस colorPaint रिसॉर्स से शुरू करें जिसे आपने पहले तय किया था.
private val drawColor = ResourcesCompat.getColor(resources, R.color.colorPaint, null)
  1. नीचे दिए गए क्लास लेवल पर, Paint ऑब्जेक्ट के लिए एक वैरिएबल paint जोड़ें और उसे इस तरह शुरू करें.
// Set up the paint with which to draw.
private val paint = Paint().apply {
   color = drawColor
   // Smooths out edges of what is drawn without affecting shape.
   isAntiAlias = true
   // Dithering affects how colors with higher-precision than the device are down-sampled.
   isDither = true
   style = Paint.Style.STROKE // default: FILL
   strokeJoin = Paint.Join.ROUND // default: MITER
   strokeCap = Paint.Cap.ROUND // default: BUTT
   strokeWidth = STROKE_WIDTH // default: Hairline-width (really thin)
}
  • paint का color, वह drawColor है जिसे आपने पहले तय किया था.
  • isAntiAlias से पता चलता है कि एज स्मूदिंग लागू करनी है या नहीं. isAntiAlias को true पर सेट करने से, आकार पर असर डाले बिना ड्रॉइंग के किनारों को साफ़ किया जाता है.
  • isDither, जब true, डिवाइस के मुकाबले ज़्यादा सटीक रंगों वाले नमूनों को प्रभावित करता है, तो इसका नमूना लिया जाता है. उदाहरण के लिए, इमेज की कलर रेंज को 256 (या उससे कम) रंग कम करने का सबसे आम तरीका है.
  • style, स्ट्रोक में सेट की जाने वाली पेंटिंग के टाइप को सेट करता है. यह एक लाइन है. Paint.Style से पता चलता है कि बनाया गया प्रिमिटिव, भरे गए, स्ट्रोक या दोनों (एक ही रंग में) है या नहीं. जिस ऑब्जेक्ट पर पेंट लागू किया जाता है उसे डिफ़ॉल्ट रूप से भरना होता है. (&kot&Fit&कोटेशन; आकार के अंदर का रंग, जबकि &kot;स्ट्रोक&कोटेशन; अपनी आउटलाइन के मुताबिक होता है.)
  • Paint.Join में से strokeJoin बताती है कि किसी स्ट्रोक पाथ पर लाइन और कर्व सेगमेंट कैसे जुड़ते हैं. डिफ़ॉल्ट रूप से, MITER होती है.
  • strokeCap, लाइन के अंत के आकार को कैप के तौर पर सेट करता है. Paint.Cap बताता है कि स्ट्रोक और लाइन के शुरू और खत्म होने का तरीका कैसे होता है. डिफ़ॉल्ट रूप से, BUTT होती है.
  • strokeWidth, स्ट्रोक की चौड़ाई को पिक्सल में बताता है. डिफ़ॉल्ट रूप से, हेयरलाइन की चौड़ाई बहुत कम होती है. इसलिए, यह पहले से तय STROKE_WIDTH कॉन्सटेंट पर सेट होता है.

दूसरा चरण. पाथ ऑब्जेक्ट को शुरू करें

Path उपयोगकर्ता के ड्रॉइंग का पाथ है.

  1. MyCanvasView में, एक वैरिएबल path जोड़ें. इसे Path ऑब्जेक्ट की मदद से शुरू करें. इससे, उपयोगकर्ता के पेज को फ़ॉलो करते समय ड्रॉ किए जाने वाले पाथ को सेव किया जा सकता है. Path के लिए android.graphics.Path इंपोर्ट करें.
private var path = Path()

पहला चरण. डिसप्ले पर होने वाली हलचल पर जवाब दें

जब भी उपयोगकर्ता डिसप्ले को छूता है, तब व्यू पर onTouchEvent() तरीके को कॉल किया जाता है.

  1. MyCanvasView में, event में पास किए गए x और y निर्देशांकों को कैश करने के लिए, onTouchEvent() तरीके को बदलें. इसके बाद, स्क्रीन पर नीचे की ओर छूने, स्क्रीन पर ले जाने, और स्क्रीन को छूने के लिए मोशन इवेंट को हैंडल करने के लिए, एक when एक्सप्रेशन का इस्तेमाल करें. ये इवेंट, स्क्रीन पर लाइन बनाने के लिए दिलचस्पी दिखाने वाले इवेंट हैं. हर इवेंट टाइप के लिए, Utility से जुड़े किसी तरीके पर कॉल करें, जैसा कि नीचे कोड में दिखाया गया है. टच इवेंट की पूरी सूची के लिए, MotionEvent क्लास के दस्तावेज़ देखें.
override fun onTouchEvent(event: MotionEvent): Boolean {
   motionTouchEventX = event.x
   motionTouchEventY = event.y

   when (event.action) {
       MotionEvent.ACTION_DOWN -> touchStart()
       MotionEvent.ACTION_MOVE -> touchMove()
       MotionEvent.ACTION_UP -> touchUp()
   }
   return true
}
  1. क्लास लेवल पर, मौजूदा टच इवेंट (MotionEvent कोऑर्डिनेट) के x और y काेऑर्डिनेट में कैश मेमोरी में सेव करने के लिए, motionTouchEventX और motionTouchEventY वैरिएबल जोड़ें. उन्हें 0f के साथ शुरू करें.
private var motionTouchEventX = 0f
private var motionTouchEventY = 0f
  1. तीन फ़ंक्शन touchStart(), touchMove(), और touchUp() के लिए स्टब बनाएं.
private fun touchStart() {}

private fun touchMove() {}

private fun touchUp() {}
  1. आपका कोड बन जाना चाहिए और चलना चाहिए, लेकिन आपको रंगीन बैकग्राउंड से कुछ अलग नहीं दिखेगा.

दूसरा चरण. TouchStart() लागू करें

यह तरीका तब कॉल किया जाता है, जब उपयोगकर्ता पहली बार स्क्रीन को छूता है.

  1. क्लास लेवल पर, नई x और y वैल्यू को कैश मेमोरी में सेव करने के लिए वैरिएबल जोड़ें. जब उपयोगकर्ता हिलना-डुलना बंद कर देता है और अपना टच हटा लेता है, तो अगले पाथ की शुरुआत यहां से होती है (लाइन का अगला सेगमेंट).
private var currentX = 0f
private var currentY = 0f
  1. touchStart() तरीके को इस तरह लागू करें. path को रीसेट करें, टच इवेंट (motionTouchEventX और motionTouchEventY) के x-y निर्देशांक पर जाएं, और उस मान के लिए currentX और currentY असाइन करें.
private fun touchStart() {
   path.reset()
   path.moveTo(motionTouchEventX, motionTouchEventY)
   currentX = motionTouchEventX
   currentY = motionTouchEventY
}

तीसरा चरण. Touchmove() लागू करना

  1. कक्षा के लेवल पर, touchTolerance वैरिएबल जोड़ें और उसे ViewConfiguration.get(context).scaledTouchSlop पर सेट करें.
private val touchTolerance = ViewConfiguration.get(context).scaledTouchSlop

पाथ का इस्तेमाल करके, हर पिक्सल को ड्रॉ नहीं करना होता और हर बार डिसप्ले को रीफ़्रेश करने के लिए अनुरोध करना पड़ता है. इसके बजाय, आप ज़्यादा बेहतर परफ़ॉर्मेंस के लिए पॉइंट के बीच के पाथ को इंटरपोलेट कर सकते हैं और ऐसा करेंगे.

  • अगर उंगली मुश्किल से ही हिल रही है, तो इसका इस्तेमाल करने की कोई ज़रूरत नहीं है.
  • अगर उंगली को touchTolerance से कम दूरी पर ले जाया गया है, तो ड्रॉइंग न करें.
  • इससे पहले कि scaledTouchSlop सिस्टम को यह लगे कि उपयोगकर्ता स्क्रोल कर रहा है, टच की गई दूरी को पिक्सल में बदल सकता है.
  1. touchMove() तरीका तय करें. यात्रा में तय की गई दूरी का हिसाब लगाएं, dx, dy), दोनों पॉइंट के बीच में एक कर्व बनाएं और उसे path में सेव करें. इसके बाद, रनिंग currentX और currentY टैल को अपडेट करें और path ड्रॉ करें. फिर अपडेट किए गए path के साथ, स्क्रीन को ज़बरदस्ती फिर से खींचने के लिए invalidate() को कॉल करें.
private fun touchMove() {
   val dx = Math.abs(motionTouchEventX - currentX)
   val dy = Math.abs(motionTouchEventY - currentY)
   if (dx >= touchTolerance || dy >= touchTolerance) {
       // QuadTo() adds a quadratic bezier from the last point,
       // approaching control point (x1,y1), and ending at (x2,y2).
       path.quadTo(currentX, currentY, (motionTouchEventX + currentX) / 2, (motionTouchEventY + currentY) / 2)
       currentX = motionTouchEventX
       currentY = motionTouchEventY
       // Draw the path in the extra bitmap to cache it.
       extraCanvas.drawPath(path, paint)
   }
   invalidate()
}

इस तरीके के बारे में ज़्यादा जानकारी:

  1. तय की गई दूरी का हिसाब लगाएं (dx, dy).
  2. अगर हलचल, टच टॉलरेंस से ज़्यादा थी, तो पाथ में एक सेगमेंट जोड़ें.
  3. अगले सेगमेंट के लिए, इस सेगमेंट के एंडपॉइंट पर शुरुआती पॉइंट सेट करें.
  4. lineTo() के बजाय quadTo() का इस्तेमाल करने पर, कोनों के बिना आसानी से ड्रॉ की जा सकने वाली लाइन बनाएं. बेज़ियर कर्व्स देखें.
  5. invalidate() को कॉल करें (कुल onDraw() को कॉल करें और) व्यू को फिर से ड्रॉ करें.

चौथा चरण: TouchUp() लागू करना

जब उपयोगकर्ता अपना टच वापस लेता है, तो सिर्फ़ पाथ को रीसेट करना होता है, ताकि वह फिर से ड्रॉ न हो. कुछ भी तैयार नहीं किया गया है, इसलिए किसी अमान्य जानकारी की ज़रूरत नहीं है.

  1. touchUp() तरीका लागू करें.
private fun touchUp() {
   // Reset the path so it doesn't get drawn again.
   path.reset()
}
  1. अपना कोड चलाएं और स्क्रीन पर ड्रॉ करने के लिए, अपनी उंगली का इस्तेमाल करें. ध्यान दें कि अगर डिवाइस को घुमाते हैं, तो स्क्रीन से पूरा डेटा मिट जाता है, क्योंकि ड्रॉइंग की स्थिति सेव नहीं होती है. इस सैंपल ऐप्लिकेशन के लिए, इस डिज़ाइन को इस तरह बनाया गया है कि उपयोगकर्ता आसानी से स्क्रीन को मिटा सके.

पांचवां चरण: स्केच के चारों ओर फ़्रेम बनाना

जैसे ही उपयोगकर्ता स्क्रीन पर ड्रॉ करता है, आपका ऐप्लिकेशन पाथ बनाता है और उसे बिट मैप extraBitmap में सेव करता है. onDraw() तरीके से, व्यू और #39; कैनवस में ज़्यादा बिट मैप दिखता है. आप onDraw() में और ड्रॉइंग कर सकते हैं. उदाहरण के लिए, आप बिट मैप बनाने के बाद आकार बना सकते हैं.

इस चरण में, तस्वीर के किनारे पर एक फ़्रेम बनाया जाता है.

  1. MyCanvasView में, frame नाम का एक वैरिएबल जोड़ें, जिसमें Rect ऑब्जेक्ट होता है.
private lateinit var frame: Rect
  1. onSizeChanged() के आखिर में, इनसेट सेट करें. साथ ही, नए डाइमेंशन और इनसेट का इस्तेमाल करके, फ़्रेम बनाने के लिए इस्तेमाल किया जाने वाला Rect बनाने के लिए कोड जोड़ें.
// Calculate a rectangular frame around the picture.
val inset = 40
frame = Rect(inset, inset, width - inset, height - inset)
  1. onDraw() में, बिट मैप बनाने के बाद, एक आयत बनाएं.
// Draw a frame around the canvas.
canvas.drawRect(frame, paint)
  1. अपना ऐप्लिकेशन चलाएं. फ़्रेम पर ध्यान दें.

टास्क (ज़रूरी नहीं): पाथ में डेटा सेव करना

मौजूदा ऐप्लिकेशन में, ड्रॉइंग की जानकारी बिट मैप में सेव की जाती है. हालांकि, यह एक अच्छा समाधान है, लेकिन ड्रॉइंग की जानकारी सेव करने के लिए, सिर्फ़ यही एक तरीका नहीं है. आप अपना ड्रॉइंग इतिहास कैसे सेव करते हैं, यह ऐप्लिकेशन और आपकी अलग-अलग ज़रूरतों पर निर्भर करता है. उदाहरण के लिए, अगर आप आकार बना रहे हैं, तो आप जगह और डाइमेंशन के साथ आकारों की सूची सेव कर सकते हैं. MiniPaint ऐप्लिकेशन के लिए, पाथ को Path के तौर पर सेव किया जा सकता है. अगर आप इसे आज़माना चाहते हैं, तो नीचे इसका तरीका बताया गया है.

  1. MyCanvasView में मौजूद, extraCanvas और extraBitmap के सभी कोड हटाएं.
  2. अब तक पाथ के लिए वैरिएबल जोड़ें और मौजूदा पाथ के लिए पाथ जोड़ें.
// Path representing the drawing so far
private val drawing = Path()

// Path representing what's currently being drawn
private val curPath = Path()
  1. onDraw() में बिट मैप बनाने के बजाय, स्टोर किए गए और मौजूदा पाथ बनाएं.
// Draw the drawing so far
canvas.drawPath(drawing, paint)
// Draw any current squiggle
canvas.drawPath(curPath, paint)
// Draw a frame around the canvas
canvas.drawRect(frame, paint)
  1. touchUp() में मौजूदा पाथ को मौजूदा पाथ में जोड़ें और मौजूदा पाथ को रीसेट करें.
// Add the current path to the drawing so far
drawing.addPath(curPath)
// Rewind the current path for the next touch
curPath.reset()
  1. अपना ऐप्लिकेशन चलाएं. इसके बाद, आपको कुछ खास फ़र्क़ नहीं डालना होगा.

अब खत्म हो चुके कोडलैब के लिए कोड डाउनलोड करें.

$  git clone https://github.com/googlecodelabs/android-kotlin-drawing-canvas


इसके अलावा, आप रिपॉज़िटरी को एक ZIP फ़ाइल के रूप में डाउनलोड कर सकते हैं, इसे अनज़िप कर सकते हैं, और Android Studio में खोल सकते हैं.

पिन डाउनलोड करें

  • Canvas 2D ड्रॉइंग प्लैटफ़ॉर्म है, जो ड्रॉइंग के तरीके बताता है.
  • इसे दिखाने वाले Canvas को View इंस्टेंस से जोड़ा जा सकता है.
  • Paint ऑब्जेक्ट में ज्यामिति को बनाने के तरीके (जैसे कि लाइन, आयत, अंडाकार, और पाथ) और टेक्स्ट की शैली और रंग की जानकारी होती है.
  • कैनवस के साथ काम करने का एक आम पैटर्न यह है कि आप कस्टम व्यू बनाएं और onDraw() और onSizeChanged() तरीकों को बदल दें.
  • उपयोगकर्ता के हाथ के जेस्चर (हाव-भाव) कैप्चर करने के लिए, onTouchEvent() का तरीका बदलें. इसके बाद, चीज़ों का ड्रॉइंग बनाकर उनका जवाब दें.
  • समय के साथ बदलने वाली ड्रॉइंग की जानकारी कैश मेमोरी में रखने के लिए, आप एक और बिट मैप का इस्तेमाल कर सकते हैं. इसके अलावा, आप आकार या पाथ सेव कर सकते हैं.

Udcity कोर्स:

Android डेवलपर दस्तावेज़:

इस सेक्शन में उन छात्र-छात्राओं के लिए गृहकार्य की असाइनमेंट की सूची दी गई है जो इस कोडलैब के ज़रिए एक शिक्षक की देखरेख में कोर्स में काम कर रहे हैं. यह क्रिएटर का काम #33 पर निर्भर करता है:

  • अगर ज़रूरी हो, तो होमवर्क असाइन करें.
  • छात्र-छात्राओं को होमवर्क के असाइनमेंट सबमिट करने के तरीके के बारे में बताएं.
  • होमवर्क असाइनमेंट को ग्रेड दें.

शिक्षक इन सुझावों का इस्तेमाल जितनी चाहें उतनी कम या ज़्यादा कर सकते हैं. साथ ही, उन्हें अपने हिसाब से कोई भी होमवर्क असाइन करना चाहिए.

अगर आप इस कोडलैब के ज़रिए खुद काम कर रहे हैं, तो बेझिझक इन होमवर्क असाइनमेंट का इस्तेमाल करें.

इन सवालों के जवाब दें

पहला सवाल

Canvas के साथ काम करने के लिए, इनमें से कौनसा कॉम्पोनेंट ज़रूरी है? लागू होने वाले सभी विकल्प चुनें.

Bitmap

Paint

Path

View

दूसरा सवाल

invalidate() के लिए कॉल क्या करता है (सामान्य शब्दों में)?

▢ अमान्य है और आपके ऐप्लिकेशन को रीस्टार्ट करता है.

▢ बिटमैप से ड्रॉइंग मिटाता है.

▢ बताता है कि पिछला कोड नहीं चलाना चाहिए.

▢ सिस्टम को बताता है कि उसे स्क्रीन को फिर से लाल करना होगा.

तीसरा सवाल

Canvas, Bitmap, और Paint ऑब्जेक्ट का फ़ंक्शन क्या है?

▢ 2D ड्रॉइंग प्लैटफ़ॉर्म, स्क्रीन पर बिट मैप दिखाया जाता है, ड्रॉइंग के लिए स्टाइलिंग की जानकारी.

▢ 3D ड्रॉइंग प्लैटफ़ॉर्म, पाथ को कैश करने के लिए बिट मैप, ड्रॉइंग के लिए स्टाइल की जानकारी.

▢ 2D ड्रॉइंग प्लैटफ़ॉर्म, स्क्रीन पर बिट मैप दिखाया जाता है, जो व्यू के लिए स्टाइल होता है.

▢ ड्रॉइंग के लिए कैश मेमोरी, ड्रॉइंग के लिए बिटमैप, ड्रॉइंग के लिए स्टाइल की जानकारी.

इस कोर्स में दिए गए दूसरे कोडलैब के लिंक के लिए, Kotlin कोडलैब के लैंडिंग पेज में ऐडवांस्ड Android देखें.