در طرحبندیهای مبتنی بر نما، شما باید ورودیهای لمسی کاربران را علاوه بر MotionEventPredictor ، درون یک InProgressStrokesView نیز مدیریت کنید.
برای دستیابی به عملکرد بهینه در ترسیم، از متدهای 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>نمونهسازی
InProgressStrokesViewدرون متد
onCreate()مربوط به اکتیویتی یا فرگمنت خود، یک ارجاع بهInProgressStrokesViewدریافت کنید و یک شنوندهی لمسی برای مدیریت ورودی کاربر تنظیم کنید.در روش [
onCreate()][ink-draw-include6] در فعالیت یا قطعه خود، یک مرجع بهInProgressStrokesViewدریافت کنید و یک شنونده لمسی برای مدیریت ورودی کاربر ایجاد کنید.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) }مدیریت رویدادهای لمسی
پس از ایجاد اجزای رابط کاربری، میتوانید طراحی را بر اساس رویدادهای لمسی آغاز کنید.
اکشن
MotionEventInProgressStrokesViewتوضیحات
شروع رندرینگ استروک
سکته مغزی را گسترش دهید
تکمیل ورودیها، آماده شدن برای نهایی کردن هندسهی خطکشی
سکته مغزی را لغو کنید
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()، ترسیم تقریباً کامل شده است. ترسیم به طور کامل پردازش شده و زمانی که هیچ ترسیم دیگری در حال انجام نباشد، برای برنامه شما قابل دسترسی خواهد بود. این امر تضمین میکند که تمام عملیات ترسیم قبل از تحویل ترسیم به کلاینت، تکمیل شده است.برای بازیابی stroke های تکمیل شده، دو گزینه دارید:
- رابط
InProgressStrokesFinishedListenerرا درون activity یا ViewModel خود پیادهسازی کنید و با فراخوانیaddFinishedStrokesListener، شنونده را درInProgressStrokesViewثبت کنید. - برای دریافت مستقیم تمام stroke های تکمیل شده،
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) } }پس از بازیابی stroke های نهایی، میتوانید
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, ... } } }- رابط