یک سکته مغزی بکشید

در طرح‌بندی‌های مبتنی بر نما، شما باید ورودی‌های لمسی کاربران را علاوه بر MotionEventPredictor ، درون یک InProgressStrokesView نیز مدیریت کنید.

برای دستیابی به عملکرد بهینه در ترسیم، از متدهای startStroke() ، addToStroke() و finishStroke() از کلاس InProgressStrokesView استفاده کنید و اشیاء MotionEvent را به عنوان ورودی ارسال کنید:

  1. تنظیم کامپوننت رابط کاربری

    برای طرح‌بندی‌های مبتنی بر نما، 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>
    
  2. نمونه‌سازی 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)
    }
    
  3. مدیریت رویدادهای لمسی

    پس از ایجاد اجزای رابط کاربری، می‌توانید طراحی را بر اساس رویدادهای لمسی آغاز کنید.

    اکشن MotionEvent

    InProgressStrokesView

    توضیحات

    ACTION_DOWN

    startStroke()

    شروع رندرینگ استروک

    ACTION_MOVE

    addToStroke()

    سکته مغزی را گسترش دهید

    ACTION_UP

    finishStroke()

    تکمیل ورودی‌ها، آماده شدن برای نهایی کردن هندسه‌ی خط‌کشی

    ACTION_CANCEL یا FLAG_CANCELED

    cancelStroke()

    سکته مغزی را لغو کنید

    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. سکته های پایان یافته را کنترل کنید

    پس از finishStroke() ، ترسیم تقریباً کامل شده است. ترسیم به طور کامل پردازش شده و زمانی که هیچ ترسیم دیگری در حال انجام نباشد، برای برنامه شما قابل دسترسی خواهد بود. این امر تضمین می‌کند که تمام عملیات ترسیم قبل از تحویل ترسیم به کلاینت، تکمیل شده است.

    برای بازیابی stroke های تکمیل شده، دو گزینه دارید:

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