Verwenden Sie für eine optimale Zeichenleistung die Methoden startStroke()
, addToStroke()
und finishStroke()
der Klasse InProgressStrokesView
und geben Sie MotionEvent
-Objekte als Eingabe an.
UI-Komponente einrichten
InProgressStrokesView
in die Ansichtshierarchie einbinden.<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>
InProgressStrokesView instanziieren
Rufen Sie in der [
onCreate()
][ink-draw-include6]-Methode Ihrer Aktivität oder Ihres Fragments einen Verweis aufInProgressStrokesView
ab und legen Sie einen Touch-Listener zum Verwalten der Nutzereingabe fest.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) }
Touch-Ereignisse verarbeiten
Nachdem Sie die UI-Komponenten eingerichtet haben, können Sie jetzt das Zeichnen basierend auf Touch-Ereignissen initiieren.
MotionEvent
-AktionInProgressStrokesView
-MethodeBeschreibung
Stroke-Rendering starten
Stroke-Rendering fortsetzen
Stroke-Rendering abschließen
Implementieren Sie die Handflächenerkennung und brechen Sie den Strich ab.
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 } }
Abgeschlossene Striche verarbeiten
Wenn
finishStroke()
aufgerufen wird, wird der Strich als abgeschlossen markiert. Der Abschlussvorgang dauert jedoch einige Zeit. Der Strich wird vollständig verarbeitet und ist kurz nach dem Aufruf vonfinishStroke()
für Ihre Anwendung verfügbar, insbesondere wenn keine anderen Striche ausgeführt werden. So wird sichergestellt, dass alle Zeichenvorgänge abgeschlossen sind, bevor der Strich als fertig an den Client übergeben wird.Sie haben zwei Möglichkeiten, fertige Striche abzurufen:
- Implementieren Sie die
InProgressStrokesFinishedListener
-Schnittstelle in Ihrer Aktivität oder Ihrem ViewModel und registrieren Sie den Listener bei derInProgressStrokesView
mitaddFinishedStrokesListener
. - Verwenden Sie die Methode
getFinishedStrokes()
vonInProgressStrokesView
, um alle fertigen Striche direkt 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 die
ViewStrokeRenderer
als Abstraktion auf höherer Ebene verwenden, die auf derCanvasStrokeRenderer
basiert. Dies kann den Rendering-Prozess in Ihrer Ansichtshierarchie weiter vereinfachen.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, ... } } }
- Implementieren Sie die