W układach opartych na widokach musisz obsługiwać dane wejściowe dotyku użytkowników w InProgressStrokesView oprócz MotionEventPredictor.
Aby uzyskać optymalną wydajność rysowania, użyj metod startStroke(), addToStroke() i finishStroke() klasy InProgressStrokesView, przekazując obiekty MotionEvent jako dane wejściowe:
Konfigurowanie komponentu interfejsu
W przypadku układów opartych na widokach dodaj
InProgressStrokesViewdo hierarchii widoków.<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>Utwórz instancję
InProgressStrokesViewW metodzie
onCreate()działania lub fragmentu uzyskaj odwołanie do elementuInProgressStrokesViewi ustaw detektor dotyku, aby zarządzać danymi wejściowymi użytkownika.W ramach metody [
onCreate()][ink-draw-include6] Twojej aktywności lub fragmentu uzyskać odniesienie doInProgressStrokesViewi ustalić detektor dotyku do zarządzania danymi wejściowymi użytkownika.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) }Obsługa zdarzeń dotknięcia
Po utworzeniu komponentów interfejsu możesz rozpocząć rysowanie na podstawie zdarzeń dotykowych.
MotionEventdziałanieMetoda
InProgressStrokesViewOpis
Rozpoczęcie renderowania pociągnięcia
Wydłużanie pociągnięcia
Zakończ wprowadzanie danych, przygotuj się do sfinalizowania geometrii pociągnięcia
Anulowanie pociągnięcia
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 } }Obsługa ukończonych pociągnięć
Po
finishStroke()pociągnięcie jest prawie gotowe. Gdy nie ma innych trwających pociągnięć, pociągnięcie jest w pełni przetworzone i staje się dostępne dla aplikacji. Dzięki temu wszystkie operacje rysowania zostaną ukończone, zanim pociągnięcie zostanie przekazane do klienta.Aby odzyskać ukończone pociągnięcia, masz 2 możliwości:
- Zaimplementuj interfejs
InProgressStrokesFinishedListenerw ramach działania lub ViewModel i zarejestruj detektor wInProgressStrokesView, wywołującaddFinishedStrokesListener. - Zadzwoń pod numer
InProgressStrokesView.getFinishedStrokes(), aby uzyskać bezpośredni dostęp do wszystkich gotowych pociągnięć.
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) } }Po pobraniu gotowych pociągnięć możesz je narysować za pomocą funkcji
ViewStrokeRenderer: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, ... } } }- Zaimplementuj interfejs