Dalam tata letak berbasis tampilan, Anda perlu menangani input sentuh pengguna di dalam
InProgressStrokesView selain
MotionEventPredictor.
Untuk mencapai performa gambar yang optimal, gunakan metode
startStroke(), addToStroke(),
dan finishStroke() dari class
InProgressStrokesView, dengan meneruskan
objek MotionEvent sebagai input:
Menyiapkan komponen UI
Untuk tata letak berbasis tampilan, tambahkan
InProgressStrokesViewke hierarki tampilan Anda.<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>Buat instance
InProgressStrokesViewDalam metode
onCreate()aktivitas atau fragmen Anda, dapatkan referensi keInProgressStrokesViewdan tetapkan pemroses sentuh untuk mengelola input pengguna.Dalam metode [
onCreate()][ink-draw-include6] aktivitas atau fragmen, dapatkan referensi keInProgressStrokesViewdan buat pemroses sentuh untuk mengelola input pengguna.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) }Menangani peristiwa sentuhan
Setelah menetapkan komponen UI, Anda dapat memulai gambar berdasarkan peristiwa sentuhan.
Tindakan
MotionEventMetode
InProgressStrokesViewDeskripsi
Mulai rendering goresan
Memperpanjang goresan
Selesaikan input, bersiap untuk menyelesaikan geometri goresan
Membatalkan goresan
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 } }Menangani goresan yang selesai
Setelah
finishStroke(), stroke hampir selesai. Goresan diproses sepenuhnya dan dapat diakses oleh aplikasi Anda setelah tidak ada goresan lain yang sedang berlangsung. Hal ini memastikan semua operasi penggambaran selesai sebelum goresan diserahkan ke klien.Untuk mengambil goresan yang telah selesai, Anda memiliki dua opsi:
- Terapkan antarmuka
InProgressStrokesFinishedListenerdalam aktivitas atau ViewModel, dan daftarkan pemroses denganInProgressStrokesViewdengan memanggiladdFinishedStrokesListener. - Panggil
InProgressStrokesView.getFinishedStrokes()untuk mendapatkan semua goresan yang telah selesai secara langsung.
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) } }Setelah mengambil goresan yang telah selesai, Anda dapat menggunakan
ViewStrokeRendereruntuk menggambarnya: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, ... } } }- Terapkan antarmuka