Nei layout basati sulla visualizzazione, devi gestire gli input tocco degli utenti all'interno di un
InProgressStrokesView oltre a
MotionEventPredictor.
Per ottenere prestazioni di disegno ottimali, utilizza i metodi
startStroke(), addToStroke() e
finishStroke() della classe
InProgressStrokesView, passando
oggetti MotionEvent come input:
Configurare il componente UI
Per i layout basati sulla visualizzazione, aggiungi
InProgressStrokesViewalla gerarchia delle visualizzazioni.<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>Instantiate
InProgressStrokesViewAll'interno del metodo
onCreate()dell'attività o del frammento, ottieni un riferimento aInProgressStrokesViewe imposta un listener di tocco per gestire l'input dell'utente.All'interno del metodo [
onCreate()][ink-draw-include6] dell'attività o del frammento, otteni un riferimento aInProgressStrokesViewe stabilisci un listener tocco per gestire l'input dell'utente.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) }Gestire gli eventi touch
Una volta stabiliti i componenti UI, puoi iniziare a disegnare in base agli eventi tocco.
Azione
MotionEventMetodo
InProgressStrokesViewDescrizione
Inizia il rendering del tratto
Estendere il tratto
Termina gli input, preparati a finalizzare la geometria del tratto
Annulla il tratto
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 } }Gestire i colpi terminati
Dopo
finishStroke(), la pennellata è quasi completa. Il tratto viene elaborato completamente e diventa accessibile alla tua applicazione quando non sono presenti altri tratti in corso. In questo modo, tutte le operazioni di disegno vengono completate prima che il tratto venga trasferito al client.Per recuperare i tratti completati, hai due opzioni:
- Implementa l'interfaccia
InProgressStrokesFinishedListenerall'interno dell'attività o del ViewModel e registra il listener conInProgressStrokesViewchiamandoaddFinishedStrokesListener. - Chiama il numero
InProgressStrokesView.getFinishedStrokes()per ricevere direttamente tutti i tratti completati.
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) } }Una volta recuperati i tratti completati, puoi utilizzare
ViewStrokeRendererper disegnarli: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, ... } } }- Implementa l'interfaccia