स्ट्रोक बनाना

बेहतर ड्रॉइंग परफ़ॉर्मेंस पाने के लिए, InProgressStrokesView क्लास के startStroke(), addToStroke(), और finishStroke() तरीकों का इस्तेमाल करें. साथ ही, इनपुट के तौर पर MotionEvent ऑब्जेक्ट पास करें.

  1. यूज़र इंटरफ़ेस (यूआई) कॉम्पोनेंट सेट अप करना

    अपनी व्यू हैरारकी में InProgressStrokesView को इंटिग्रेट करें.

    <FrameLayout>
    
      <ScrollView
        android:id="@+id/my_content"
        android:width="match_parent"
        android:height="match_parent"
        >
        <!-- Your content here. -->
      </ScrollView>
    
      <androidx.ink.authoring.InProgressStrokesView
        android:id="@+id/in_progress_strokes_view"
        android:width="match_parent"
        android:height="match_parent"
        />
    
    </FrameLayout>
    

  2. InProgressStrokesView को इंस्टैंशिएट करना

    अपनी ऐक्टिविटी या फ़्रैगमेंट के [onCreate()][ink-draw-include6] तरीके में, InProgressStrokesView का रेफ़रंस पाएं और उपयोगकर्ता के इनपुट को मैनेज करने के लिए, टच लिसनर सेट अप करें.

    class MyActivity : View.OnTouchListener {
        private lateinit var contentView: ScrollView
        private lateinit var inProgressStrokesView: InProgressStrokesView
        private lateinit var predictor: MotionEventPredictor
    
        // ... other variables
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
          predictor = MotionEventPredictor.newInstance(contentView)
            contentView = findViewById(R.id.my_content)
            contentView.setOnTouchListener(touchListener)
            inProgressStrokesView = findViewById(R.id.in_progress_strokes_view)
        }
    
        // ... (touchListener implementation)
    }
    

  3. हैंडल टच इवेंट

    यूज़र इंटरफ़ेस (यूआई) कॉम्पोनेंट सेट अप करने के बाद, अब टच इवेंट के आधार पर ड्रॉइंग शुरू की जा सकती है.

    MotionEvent कार्रवाई

    InProgressStrokesView तरीका

    ब्यौरा

    ACTION_DOWN

    startStroke()

    स्ट्रोक रेंडर करना शुरू करना

    ACTION_MOVE

    addToStroke()

    स्ट्रोक को रेंडर करना जारी रखना

    ACTION_UP

    finishStroke()

    स्ट्रोक रेंडरिंग को पूरा करें

    ACTION_CANCEL या FLAG_CANCELED

    cancelStroke()

    हथेली के स्पर्श को अस्वीकार करने की सुविधा लागू करना; स्ट्रोक रद्द करना

    class MyActivity : View.OnTouchListener {
      private lateinit var contentView: ScrollView
      private lateinit var inProgressStrokesView: InProgressStrokesView
    
      private var pointerId = -1
      private var strokeId: InProgressStrokeId? = null
      private lateinit var predictor: MotionEventPredictor
    
      override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    
        contentView = findViewById(R.id.my_content)
        predictor = MotionEventPredictor.create(contentView)
        contentView.setOnTouchListener(touchListener)
        inProgressStrokesView = findViewById(R.id.in_progress_strokes_view)
      }
    
      private val touchListener = { view: View, event: MotionEvent ->
        predictor.record(event)
          when (event.actionMasked) {
            MotionEvent.ACTION_DOWN -> {
              // First pointer - treat it as inking.
              view.requestUnbufferedDispatch(event)
              val pointerIndex = event.actionIndex
              pointerIdToStrokeId[event.getPointerId(pointerIndex)] =
                inProgressStrokesView.startStroke(event, pointerId)
              return true
            }
            MotionEvent.ACTION_POINTER_DOWN -> {
              val stroke = strokeId ?: return false
              inProgressStrokesView.cancelStroke(stroke, event)
              strokeId = null
              pointerId = -1
              return false
            }
            MotionEvent.ACTION_MOVE -> {
              val predictedEvent = predictor.predict()
              try
              {
                for (pointerIndex in 0 until pointerCount) {
                  val strokeId =
                  pointerIdToStrokeId[event.getPointerId(pointerIndex)] ?: continue
                  inProgressStrokesView.addToStroke(event, pointerId, strokeId, predictedEvent)
                } finally {
                  predictedEvent?.recycle()
                }
              }
            }
            MotionEvent.ACTION_UP -> {
              val pointerIndex = event.actionIndex
              val strokeId =
                pointerIdToStrokeId[event.getPointerId(pointerIndex)] ?: return false
              inProgressStrokesView.finishStroke(event, pointerId, strokeId)
              return true
            }
            MotionEvent.ACTION_CANCEL -> {
              val pointerIndex = event.actionIndex
              val strokeId =
                pointerIdToStrokeId[event.getPointerId(pointerIndex)] ?: return false
              inProgressStrokesView.cancelStroke(strokeId, event)
              return true
            }
          }
        return false
      }
    }
    

  4. पूरे हो चुके स्ट्रोक मैनेज करना

    finishStroke() को कॉल करने पर, स्ट्रोक को 'पूरा हो गया' के तौर पर मार्क कर दिया जाता है. हालांकि, प्रोसेस पूरी होने में कुछ समय लगता है. finishStroke() को कॉल करने के कुछ समय बाद, स्ट्रोक पूरी तरह से प्रोसेस हो जाता है और आपके ऐप्लिकेशन के लिए ऐक्सेस हो जाता है. ऐसा तब होता है, जब कोई दूसरा स्ट्रोक प्रोसेस में न हो. इससे यह पक्का होता है कि स्ट्रोक को पूरा हो गया के तौर पर क्लाइंट को सौंपने से पहले, ड्रॉइंग के सभी ऑपरेशन पूरे हो जाएं.

    खत्म हो चुके स्ट्रोक को वापस पाने के लिए आपके पास दो विकल्प हैं:

    • अपनी ऐक्टिविटी या ViewModel में, InProgressStrokesFinishedListener इंटरफ़ेस लागू करें. साथ ही, InProgressStrokesView के साथ addFinishedStrokesListener के साथ, लिसनर को रजिस्टर करें.
    • सीधे तौर पर सभी पूरे किए गए स्ट्रोक पाने के लिए, InProgressStrokesView के getFinishedStrokes() तरीकों का इस्तेमाल करें.
    class MyActivity : ComponentActivity(), InProgressStrokesFinishedListener {
      ...
    
      private val finishedStrokesState = mutableStateOf(emptySet<Stroke>())
    
      override fun onCreate(savedInstanceState: Bundle?) {
        ...
        inProgressStrokesView.addFinishedStrokesListener(this)
      }
    
      // ... (handle touch events)
    
      @UiThread
      override fun onStrokesFinished(strokes: Map<InProgressStrokeId, Stroke>) {
        finishedStrokesState.value += strokes.values
        inProgressStrokesView.removeFinishedStrokes(strokes.keys)
      }
    }
    

    खत्म किए गए स्ट्रोक को हासिल करने के बाद, ViewStrokeRenderer का इस्तेमाल CanvasStrokeRenderer के ऊपर बनाए गए हाई-लेवल ऐब्स्ट्रैक्ट के तौर पर किया जा सकता है. इससे आपके व्यू हैरारकी (व्यू और व्यू ग्रुप के लेआउट का क्रम) में रेंडरिंग की प्रोसेस और आसान हो सकती है.

    class DrawingView(context: Context) : View(context) {
      private val viewStrokeRenderer = ViewStrokeRenderer(myCanvasStrokeRenderer, this)
    
      override fun onDraw(canvas: Canvas) {
        viewStrokeRenderer.drawWithStrokes(canvas) { scope ->
          canvas.scale(myZoomLevel)
          canvas.rotate(myRotation)
          canvas.translate(myPanX, myPanY)
          scope.drawStroke(myStroke)
          // Draw other objects including more strokes, apply more transformations, ...
        }
      }
    }