Strich zeichnen

In viewbasierten Layouts müssen Sie die Berührungseingaben der Nutzer zusätzlich zu MotionEventPredictor auch in einem InProgressStrokesView verarbeiten.

Verwenden Sie die Methoden startStroke(), addToStroke() und finishStroke() der Klasse InProgressStrokesView, um eine optimale Zeichenleistung zu erzielen. Übergeben Sie MotionEvent-Objekte als Eingabe:

  1. UI-Komponente einrichten

    Fügen Sie für ansichtsbasierte Layouts InProgressStrokesView in Ihre Ansichtshierarchie ein.

    <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. Instanziieren InProgressStrokesView

    Rufen Sie in der Methode onCreate() Ihrer Aktivität oder Ihres Fragments eine Referenz zu InProgressStrokesView ab und legen Sie einen Touch-Listener fest, um Nutzereingaben zu verarbeiten.

    Innerhalb der [onCreate()][ink-draw-include6]-Methode Ihrer Aktivität oder Ihres Fragments auf die InProgressStrokesView verweisen und eine Touch-Listener zum Verwalten von Nutzereingaben.

    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. Touch-Ereignisse verarbeiten

    Nachdem Sie die UI-Komponenten eingerichtet haben, können Sie das Zeichnen basierend auf Touch-Ereignissen starten.

    MotionEvent Aktion

    InProgressStrokesView-Methode

    Beschreibung

    ACTION_DOWN

    startStroke()

    Strichrendering starten

    ACTION_MOVE

    addToStroke()

    Strich verlängern

    ACTION_UP

    finishStroke()

    Eingaben abschließen, um die Geometrie des Strichs fertigzustellen

    ACTION_CANCEL oder FLAG_CANCELED

    cancelStroke()

    Strich abbrechen

    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. Abgeschlossene Striche verarbeiten

    Nach finishStroke() ist der Strich fast fertig. Der Strich wird vollständig verarbeitet und ist für Ihre Anwendung verfügbar, sobald keine anderen Striche mehr ausgeführt werden. So wird sichergestellt, dass alle Zeichenvorgänge abgeschlossen sind, bevor der Strich an den Client übergeben wird.

    Sie haben zwei Möglichkeiten, abgeschlossene Striche abzurufen:

    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)
      }
    }
    

    Nachdem Sie die fertigen Striche abgerufen haben, können Sie sie mit ViewStrokeRenderer zeichnen:

    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, ...
        }
      }
    }