בפריסות מבוססות-תצוגה, צריך לטפל בקלט מגע של משתמשים בתוך InProgressStrokesView בנוסף ל-MotionEventPredictor.
כדי להשיג ביצועים אופטימליים של ציור, משתמשים בשיטות startStroke(), addToStroke() ו-finishStroke() של המחלקה InProgressStrokesView, ומעבירים אובייקטים מסוג MotionEvent כקלט:
הגדרת רכיב בממשק המשתמש
בפריסות מבוססות-תצוגה, מוסיפים
InProgressStrokesViewלהיררכיית התצוגה.<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
InProgressStrokesViewבשיטה
onCreate()של הפעילות או של ה-fragment, מקבלים הפניה אלInProgressStrokesViewומגדירים מאזין מגע כדי לנהל את קלט המשתמש.ב-method [
onCreate()][ink-draw-include6] של הפעילות או המקטע שלך, לקבל הפניה אלInProgressStrokesViewוליצור Touch Listener לניהול קלט של משתמשים.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) }טיפול באירועי מגע
אחרי שקובעים את רכיבי ממשק המשתמש, אפשר להתחיל לצייר על סמך אירועי מגע.
MotionEventפעולהInProgressStrokesViewmethodתיאור
התחלת עיבוד של קו
הארכת הקו
מזינים את הנתונים ומכינים את הגיאומטריה של הקו
ביטול הקו
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 } }מה לעשות כשמסיימים חבטות
אחרי
finishStroke(), המילה כמעט מושלמת. התנועה המלאה של העט מעובדת וזמינה לאפליקציה שלכם אחרי שאין עוד תנועות של העט בתהליך. כך מוודאים שכל פעולות הציור הושלמו לפני שהקו מועבר ללקוח.יש שתי דרכים לאחזר משיכות מכחול שהסתיימו:
- מטמיעים את הממשק
InProgressStrokesFinishedListenerבפעילות או ב-ViewModel, ורושמים את ה-listener באמצעותInProgressStrokesViewעל ידי קריאה ל-addFinishedStrokesListener. - כדי לקבל ישירות את כל המשיכות שהסתיימו, מתקשרים אל
InProgressStrokesView.getFinishedStrokes().
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) } }אחרי שמאחזרים את המשיכות המוגמרות, אפשר להשתמש ב-
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, ... } } }- מטמיעים את הממשק