Çizgi çizme

Görünüme dayalı düzenlerde, kullanıcıların dokunma girişlerini MotionEventPredictor'a ek olarak InProgressStrokesView içinde de işlemeniz gerekir.

Çizim performansını en iyi şekilde elde etmek için startStroke(), addToStroke() ve finishStroke() yöntemlerini kullanın. InProgressStrokesView sınıfının MotionEvent nesnelerini giriş olarak iletin:

  1. Kullanıcı arayüzü bileşenini ayarlama

    Görünüme dayalı düzenler için görünüm hiyerarşinize InProgressStrokesView ekleyin.

    <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>
    
  2. Instantiate InProgressStrokesView

    Etkinliğinizin veya parçanızın onCreate() yönteminde, InProgressStrokesView öğesine referans alın ve kullanıcı girişini yönetmek için dokunma işleyicisi ayarlayın.

    Etkinliğinizin veya parçanızın [onCreate()][ink-draw-include6] yönteminde bir InProgressStrokesView referansı elde edebilir ve kullanıcı girişini yönetmek için dokunma dinleyicisi.

    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)
    }
    
  3. Dokunma etkinliklerini işleme

    Kullanıcı arayüzü bileşenlerini oluşturduktan sonra dokunma etkinliklerine göre çizim başlatabilirsiniz.

    MotionEvent action

    InProgressStrokesView yöntemi

    Açıklama

    ACTION_DOWN

    startStroke()

    Çizim oluşturmaya başlama

    ACTION_MOVE

    addToStroke()

    Fırça darbesini uzatma

    ACTION_UP

    finishStroke()

    Girişleri tamamlayın, konturun geometrisini sonlandırmaya hazırlanın

    ACTION_CANCEL veya FLAG_CANCELED

    cancelStroke()

    Çizgiyi iptal etme

    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
      }
    }
    
  4. Tamamlanan vuruşları işleme

    finishStroke() sonrasında vuruş neredeyse tamamlanır. Çizim tamamen işlenir ve başka çizimler işlenmediğinde uygulamanız tarafından erişilebilir hale gelir. Bu sayede, kontur istemciye aktarılmadan önce tüm çizim işlemlerinin tamamlanması sağlanır.

    Bitmiş vuruşları almak için iki seçeneğiniz vardır:

    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)
      }
    }
    

    Tamamlanmış vuruşları aldıktan sonra bunları çizmek için ViewStrokeRenderer simgesini kullanabilirsiniz:

    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, ...
        }
      }
    }