หากต้องการประสิทธิภาพการวาดที่ดีที่สุด ให้ใช้เมธอดของคลาส InProgressStrokesView
ซึ่งได้แก่ startStroke()
, addToStroke()
และ finishStroke()
โดยส่งออบเจ็กต์ MotionEvent
เป็นอินพุต
ตั้งค่าคอมโพเนนต์ UI
ผสาน
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>
สร้างอินสแตนซ์ InProgressStrokesView
ภายในเมธอด [
onCreate()
][ink-draw-include6] ของกิจกรรมหรือ Fragment ให้รับการอ้างอิงInProgressStrokesView
และสร้าง 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)
}จัดการเหตุการณ์การสัมผัส
เมื่อสร้างคอมโพเนนต์ UI แล้ว คุณจะเริ่มต้นการวาดตามเหตุการณ์การสัมผัสได้
MotionEvent
actionInProgressStrokesView
methodคำอธิบาย
เริ่มแสดงผลเส้นวาด
แสดงผลเส้นต่อ
แสดงผลเส้นให้เสร็จสมบูรณ์
ใช้การปฏิเสธฝ่ามือ ยกเลิกการเขียน
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()
ระบบจะทำเครื่องหมายเส้นว่าเสร็จสมบูรณ์ อย่างไรก็ตาม กระบวนการสรุปจะไม่เกิดขึ้นในทันที ระบบจะประมวลผลเส้นทั้งหมดและเข้าถึงแอปพลิเคชันของคุณได้ภายในเวลาอันสั้นหลังจากเรียกใช้finishStroke()
โดยเฉพาะอย่างยิ่งเมื่อไม่มีเส้นอื่นๆ ที่กำลังดำเนินการอยู่ วิธีนี้ช่วยให้มั่นใจได้ว่าการดำเนินการวาดทั้งหมดจะเสร็จสิ้นก่อนที่จะส่งเส้นให้กับไคลเอ็นต์ในสถานะเสร็จสิ้นหากต้องการเรียกดูเส้นที่วาดเสร็จแล้ว คุณมี 2 ตัวเลือกดังนี้
- ใช้อินเตอร์เฟซ
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
เป็นภาพนามธรรมระดับสูงขึ้นที่สร้างขึ้นจากCanvasStrokeRenderer
ได้ วิธีนี้ช่วยให้กระบวนการแสดงผลภายในลําดับชั้นของมุมมองง่ายขึ้น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, ...
}
}
}- ใช้อินเตอร์เฟซ