স্পর্শ এবং পয়েন্টার আন্দোলন ট্র্যাক

রচনা পদ্ধতি চেষ্টা করুন
জেটপ্যাক কম্পোজ হল Android এর জন্য প্রস্তাবিত UI টুলকিট। কম্পোজে কীভাবে স্পর্শ এবং ইনপুট ব্যবহার করবেন তা শিখুন।

এই পাঠটি বর্ণনা করে কিভাবে স্পর্শ ইভেন্টে গতিবিধি ট্র্যাক করতে হয়।

একটি নতুন onTouchEvent() একটি ACTION_MOVE ইভেন্টের সাথে ট্রিগার হয় যখনই বর্তমান স্পর্শ যোগাযোগের অবস্থান, চাপ বা আকার পরিবর্তন হয়৷ সাধারণ অঙ্গভঙ্গি সনাক্ত করুন -এ বর্ণিত হিসাবে, এই সমস্ত ঘটনাগুলি onTouchEvent() এর MotionEvent প্যারামিটারে রেকর্ড করা হয়৷

যেহেতু আঙুল-ভিত্তিক স্পর্শ সর্বদা মিথস্ক্রিয়ার সবচেয়ে সুনির্দিষ্ট রূপ নয়, স্পর্শ ইভেন্টগুলি সনাক্ত করা প্রায়শই সাধারণ যোগাযোগের চেয়ে গতিবিধির উপর নির্ভর করে। অ্যাপ্লিকেশানগুলিকে নড়াচড়া-ভিত্তিক অঙ্গভঙ্গি (যেমন একটি সোয়াইপ) এবং নন-মুভমেন্ট অঙ্গভঙ্গি (যেমন একটি ট্যাপ) এর মধ্যে পার্থক্য করতে সহায়তা করার জন্য, Android স্পর্শ স্লপের ধারণা অন্তর্ভুক্ত করে। টাচ স্লপ পিক্সেলের দূরত্বকে বোঝায় যে ইঙ্গিতটিকে আন্দোলন-ভিত্তিক অঙ্গভঙ্গি হিসাবে ব্যাখ্যা করার আগে একজন ব্যবহারকারীর স্পর্শ ঘোরাফেরা করতে পারে। এই বিষয় সম্পর্কে আরও তথ্যের জন্য, একটি ভিউগ্রুপে স্পর্শ ইভেন্টগুলি পরিচালনা করুন দেখুন।

আপনার অ্যাপ্লিকেশনের প্রয়োজনের উপর নির্ভর করে একটি অঙ্গভঙ্গিতে গতিবিধি ট্র্যাক করার বিভিন্ন উপায় রয়েছে৷ নিম্নলিখিত উদাহরণ:

  • একটি পয়েন্টারের শুরু এবং শেষ অবস্থান, যেমন একটি অন-স্ক্রীন বস্তুকে বিন্দু A থেকে বি পয়েন্টে সরানো।
  • X এবং Y স্থানাঙ্ক দ্বারা নির্ধারিত হিসাবে পয়েন্টারটি যে দিকে ভ্রমণ করছে।
  • ইতিহাস। আপনি MotionEvent পদ্ধতি getHistorySize() কল করে একটি অঙ্গভঙ্গির ইতিহাসের আকার খুঁজে পেতে পারেন। তারপরে আপনি মোশন ইভেন্টের getHistorical <Value> পদ্ধতি ব্যবহার করে প্রতিটি ঐতিহাসিক ইভেন্টের অবস্থান, আকার, সময় এবং চাপ পেতে পারেন। ব্যবহারকারীর আঙুলের একটি লেজ রেন্ডার করার সময় ইতিহাস দরকারী, যেমন স্পর্শ অঙ্কনের জন্য। বিস্তারিত জানার জন্য MotionEvent রেফারেন্স দেখুন।
  • টাচস্ক্রিন জুড়ে চলার সময় পয়েন্টারটির বেগ।

নিম্নলিখিত সম্পর্কিত সংস্থান পড়ুন:

ট্র্যাক বেগ

আপনি একটি নড়াচড়া-ভিত্তিক অঙ্গভঙ্গি করতে পারেন যা পয়েন্টারটি যে দূরত্ব বা দিকটি ভ্রমণ করে তার উপর ভিত্তি করে। যাইহোক, বেগ প্রায়শই একটি অঙ্গভঙ্গির বৈশিষ্ট্যগুলি ট্র্যাক করার বা অঙ্গভঙ্গি ঘটেছে কিনা তা নির্ধারণ করার জন্য একটি নির্ধারক কারণ। বেগ গণনা সহজ করতে, Android VelocityTracker ক্লাস প্রদান করে। VelocityTracker আপনাকে স্পর্শ ইভেন্টের বেগ ট্র্যাক করতে সহায়তা করে। এটি এমন অঙ্গভঙ্গির জন্য উপযোগী যেখানে বেগ অঙ্গভঙ্গির মানদণ্ডের অংশ, যেমন ফ্লিং।

এখানে একটি উদাহরণ রয়েছে যা VelocityTracker এপিআই-এর পদ্ধতিগুলির উদ্দেশ্য ব্যাখ্যা করে:

কোটলিন

private const val DEBUG_TAG = "Velocity"

class MainActivity : Activity() {
    private var mVelocityTracker: VelocityTracker? = null

    override fun onTouchEvent(event: MotionEvent): Boolean {

        when (event.actionMasked) {
            MotionEvent.ACTION_DOWN -> {
                // Reset the velocity tracker back to its initial state.
                mVelocityTracker?.clear()
                // If necessary, retrieve a new VelocityTracker object to watch
                // the velocity of a motion.
                mVelocityTracker = mVelocityTracker ?: VelocityTracker.obtain()
                // Add a user's movement to the tracker.
                mVelocityTracker?.addMovement(event)
            }
            MotionEvent.ACTION_MOVE -> {
                mVelocityTracker?.apply {
                    val pointerId: Int = event.getPointerId(event.actionIndex)
                    addMovement(event)
                    // When you want to determine the velocity, call
                    // computeCurrentVelocity(). Then, call getXVelocity() and
                    // getYVelocity() to retrieve the velocity for each pointer
                    // ID.
                    computeCurrentVelocity(1000)
                    // Log velocity of pixels per second. It's best practice to
                    // use VelocityTrackerCompat where possible.
                    Log.d("", "X velocity: ${getXVelocity(pointerId)}")
                    Log.d("", "Y velocity: ${getYVelocity(pointerId)}")
                }
            }
            MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
                // Return a VelocityTracker object back to be re-used by others.
                mVelocityTracker?.recycle()
                mVelocityTracker = null
            }
        }
        return true
    }
}

জাভা

public class MainActivity extends Activity {
    private static final String DEBUG_TAG = "Velocity";
        ...
    private VelocityTracker mVelocityTracker = null;
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int index = event.getActionIndex();
        int action = event.getActionMasked();
        int pointerId = event.getPointerId(index);

        switch(action) {
            case MotionEvent.ACTION_DOWN:
                if(mVelocityTracker == null) {
                    // Retrieve a new VelocityTracker object to watch the
                    // velocity of a motion.
                    mVelocityTracker = VelocityTracker.obtain();
                }
                else {
                    // Reset the velocity tracker back to its initial state.
                    mVelocityTracker.clear();
                }
                // Add a user's movement to the tracker.
                mVelocityTracker.addMovement(event);
                break;
            case MotionEvent.ACTION_MOVE:
                mVelocityTracker.addMovement(event);
                // When you want to determine the velocity, call
                // computeCurrentVelocity(). Then call getXVelocity() and
                // getYVelocity() to retrieve the velocity for each pointer ID.
                mVelocityTracker.computeCurrentVelocity(1000);
                // Log velocity of pixels per second. It's best practice to use
                // VelocityTrackerCompat where possible.
                Log.d("", "X velocity: " + mVelocityTracker.getXVelocity(pointerId));
                Log.d("", "Y velocity: " + mVelocityTracker.getYVelocity(pointerId));
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                // Return a VelocityTracker object back to be re-used by others.
                mVelocityTracker.recycle();
                break;
        }
        return true;
    }
}

পয়েন্টার ক্যাপচার ব্যবহার করুন

কিছু অ্যাপ, যেমন গেমস এবং রিমোট ডেস্কটপ এবং ভার্চুয়ালাইজেশন ক্লায়েন্ট, মাউস পয়েন্টারের উপর নিয়ন্ত্রণ পেয়ে উপকৃত হয়। পয়েন্টার ক্যাপচার হল Android 8.0 (API লেভেল 26) এবং উচ্চতর সংস্করণে উপলব্ধ একটি বৈশিষ্ট্য যা আপনার অ্যাপে একটি ফোকাসড ভিউতে সমস্ত মাউস ইভেন্ট সরবরাহ করে এই নিয়ন্ত্রণ প্রদান করে।

পয়েন্টার ক্যাপচার অনুরোধ

আপনার অ্যাপের একটি ভিউ পয়েন্টার ক্যাপচারের অনুরোধ করতে পারে শুধুমাত্র তখনই যখন এটিতে থাকা ভিউ হায়ারার্কিতে ফোকাস থাকে। এই কারণে, ভিউতে একটি নির্দিষ্ট ব্যবহারকারীর অ্যাকশন থাকলে পয়েন্টার ক্যাপচারের অনুরোধ করুন, যেমন একটি onClick() ইভেন্টের সময় বা আপনার কার্যকলাপের onWindowFocusChanged() ইভেন্ট হ্যান্ডলারে।

পয়েন্টার ক্যাপচারের অনুরোধ করতে, ভিউতে requestPointerCapture() পদ্ধতিতে কল করুন। নিম্নলিখিত কোড উদাহরণ দেখায় কিভাবে পয়েন্টার ক্যাপচার অনুরোধ করতে হয় যখন ব্যবহারকারী একটি ভিউ ক্লিক করে:

কোটলিন

fun onClick(view: View) {
    view.requestPointerCapture()
}

জাভা

@Override
public void onClick(View view) {
    view.requestPointerCapture();
}

পয়েন্টার ক্যাপচার করার অনুরোধ সফল হলে, Android কল করে onPointerCaptureChange(true) । সিস্টেমটি মাউস ইভেন্টগুলিকে আপনার অ্যাপে ফোকাসড ভিউতে ডেলিভার করে যতক্ষণ না এটি ক্যাপচারের অনুরোধ করা ভিউটির মতো একই ভিউ হায়ারার্কিতে থাকে। অন্যান্য অ্যাপ্লিকেশানগুলি ACTION_OUTSIDE ইভেন্ট সহ ক্যাপচার প্রকাশ না হওয়া পর্যন্ত মাউস ইভেন্টগুলি গ্রহণ করা বন্ধ করে৷ অ্যান্ড্রয়েড স্বাভাবিক হিসাবে মাউস ব্যতীত অন্য উত্স থেকে পয়েন্টার ইভেন্টগুলি সরবরাহ করে, তবে মাউস পয়েন্টারটি আর দৃশ্যমান নয়৷

ক্যাপচার করা পয়েন্টার ইভেন্টগুলি পরিচালনা করুন

একবার একটি দৃশ্য সফলভাবে পয়েন্টার ক্যাপচার অর্জন করলে, অ্যান্ড্রয়েড মাউস ইভেন্টগুলি সরবরাহ করে৷ আপনার ফোকাসড ভিউ নিম্নলিখিত কাজগুলির একটি সম্পাদন করে ইভেন্টগুলি পরিচালনা করতে পারে:

নিম্নলিখিত কোড উদাহরণ দেখায় কিভাবে onCapturedPointerEvent(MotionEvent) বাস্তবায়ন করতে হয়:

কোটলিন

override fun onCapturedPointerEvent(motionEvent: MotionEvent): Boolean {
    // Get the coordinates required by your app.
    val verticalOffset: Float = motionEvent.y
    // Use the coordinates to update your view and return true if the event is
    // successfully processed.
    return true
}

জাভা

@Override
public boolean onCapturedPointerEvent(MotionEvent motionEvent) {
  // Get the coordinates required by your app.
  float verticalOffset = motionEvent.getY();
  // Use the coordinates to update your view and return true if the event is
  // successfully processed.
  return true;
}

নিম্নলিখিত কোড উদাহরণ দেখায় কিভাবে একটি OnCapturedPointerListener নিবন্ধন করতে হয়:

কোটলিন

myView.setOnCapturedPointerListener { view, motionEvent ->
    // Get the coordinates required by your app.
    val horizontalOffset: Float = motionEvent.x
    // Use the coordinates to update your view and return true if the event is
    // successfully processed.
    true
}

জাভা

myView.setOnCapturedPointerListener(new View.OnCapturedPointerListener() {
  @Override
  public boolean onCapturedPointer (View view, MotionEvent motionEvent) {
    // Get the coordinates required by your app.
    float horizontalOffset = motionEvent.getX();
    // Use the coordinates to update your view and return true if the event is
    // successfully processed.
    return true;
  }
});

আপনি একটি কাস্টম ভিউ ব্যবহার করুন বা একজন শ্রোতা নিবন্ধন করুন না কেন, আপনার ভিউ পয়েন্টার কোঅর্ডিনেট সহ একটি MotionEvent পায় যা আপেক্ষিক গতিবিধি যেমন X বা Y ডেল্টাস নির্দিষ্ট করে, যেমন একটি ট্র্যাকবল ডিভাইস দ্বারা বিতরণ করা স্থানাঙ্কের মতো। আপনি getX() এবং getY() ব্যবহার করে স্থানাঙ্ক পুনরুদ্ধার করতে পারেন।

রিলিজ পয়েন্টার ক্যাপচার

আপনার অ্যাপের ভিউটি releasePointerCapture() কল করে পয়েন্টার ক্যাপচার ছেড়ে দিতে পারে, যেমনটি নিম্নলিখিত কোড উদাহরণে দেখানো হয়েছে:

কোটলিন

override fun onClick(view: View) {
    view.releasePointerCapture()
}

জাভা

@Override
public void onClick(View view) {
    view.releasePointerCapture();
}

আপনি স্পষ্টভাবে releasePointerCapture() কল না করে সিস্টেমটি দৃশ্য থেকে ক্যাপচারটি সরিয়ে নিতে পারে, সাধারণত কারণ যে ভিউটি ক্যাপচারের অনুরোধ করে সেই ভিউ শ্রেণীবিন্যাস ফোকাস হারায়।