Optimum çizim performansı elde etmek için InProgressStrokesView
sınıfının startStroke()
, addToStroke()
ve finishStroke()
yöntemlerini kullanın. Bu yöntemlerde, giriş olarak MotionEvent
nesneleri iletin.
Kullanıcı arayüzü bileşenini ayarlama
InProgressStrokesView
öğesini görünüm hiyerarşinize entegre edin.<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'ı başlatma
Etkinliğinizin veya parçanızın [
onCreate()
][ink-draw-include6] yöntemindeInProgressStrokesView
referansı alın ve kullanıcı girişini yönetmek için bir dokunma dinleyicisi oluşturun.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) }
Dokunma etkinliklerini işleme
Kullanıcı arayüzü bileşenlerini oluşturduktan sonra dokunma etkinliklerine göre çizim başlatabilirsiniz.
MotionEvent
işlemiInProgressStrokesView
yöntemiAçıklama
Vuruş oluşturmaya başlama
Çizgiyi oluşturmaya devam edin
Çizgi oluşturma işlemini tamamlama
Avuç içi reddetme özelliğini uygulayın; çizgiyi iptal edin
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 } }
Bitmiş vuruşları işleme
finishStroke()
çağrıldıktan sonra çizgi tamamlandı olarak işaretlenir. Ancak, tamamlama işlemi anında gerçekleşmez. Vuruş tamamen işlenir vefinishStroke()
çağrıldıktan kısa bir süre sonra, özellikle de devam eden başka vuruş olmadığında uygulamanız tarafından erişilebilir hale gelir. Bu sayede, çizgi bitti olarak istemciye aktarılmadan önce tüm çizim işlemleri tamamlanır.Bitmiş vuruşları almak için iki seçeneğiniz vardır:
- Etkinliğinize veya ViewModel'inize
InProgressStrokesFinishedListener
arayüzünü uygulayın ve dinleyiciyiaddFinishedStrokesListener
ileInProgressStrokesView
'e kaydedin. - Bitmiş tüm vuruşları doğrudan almak için
InProgressStrokesView
getFinishedStrokes()
yöntemini kullanın.
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) } }
Bitmiş vuruşları aldıktan sonra
CanvasStrokeRenderer
'in üzerine inşa edilmiş daha yüksek düzey bir soyutlama olarakViewStrokeRenderer
'i kullanabilirsiniz. Bu, görüntüleme hiyerarşinizdeki oluşturma sürecini daha da basitleştirebilir.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, ... } } }
- Etkinliğinize veya ViewModel'inize