Dans les mises en page basées sur des vues, vous devez gérer les entrées tactiles des utilisateurs dans un InProgressStrokesView en plus de MotionEventPredictor.
Pour obtenir des performances de dessin optimales, utilisez les méthodes startStroke(), addToStroke() et finishStroke() de la classe InProgressStrokesView, en transmettant des objets MotionEvent en entrée :
Configurer le composant d'UI
Pour les mises en page basées sur les vues, ajoutez
InProgressStrokesViewà votre hiérarchie de vues.<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>Instancier
InProgressStrokesViewDans la méthode
onCreate()de votre activité ou fragment, obtenez une référence àInProgressStrokesViewet définissez un écouteur tactile pour gérer la saisie utilisateur.Dans la méthode [
onCreate()][ink-draw-include6] de votre activité ou fragment, obtenir une référence àInProgressStrokesViewet établir une écouteur tactile pour gérer les entrées utilisateurclass 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) }Gérer les événements tactiles
Une fois les composants d'UI établis, vous pouvez commencer à dessiner en fonction des événements tactiles.
MotionEventactionMéthode
InProgressStrokesViewDescription
Début du rendu du tracé
Étendre le trait
Terminer les entrées, se préparer à finaliser la géométrie du tracé
Annuler le trait
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 } }Gérer les traits terminés
Après
finishStroke(), le tracé est presque terminé. Le tracé est entièrement traité et devient accessible à votre application une fois qu'il n'y a plus d'autres tracés en cours. Cela garantit que toutes les opérations de dessin sont terminées avant que le trait ne soit transmis au client.Pour récupérer les traits terminés, vous avez deux options :
- Implémentez l'interface
InProgressStrokesFinishedListenerdans votre activité ou ViewModel, puis enregistrez l'écouteur avecInProgressStrokesViewen appelantaddFinishedStrokesListener. - Appelez
InProgressStrokesView.getFinishedStrokes()pour obtenir directement tous les traits terminés.
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) } }Une fois que vous avez récupéré les traits terminés, vous pouvez utiliser
ViewStrokeRendererpour les dessiner :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, ... } } }- Implémentez l'interface