মাল্টি-টাচ অঙ্গভঙ্গি পরিচালনা করুন

কম্পোজ পদ্ধতিটি চেষ্টা করুন
জেটপ্যাক কম্পোজ হলো অ্যান্ড্রয়েডের জন্য প্রস্তাবিত UI টুলকিট। কম্পোজে কীভাবে টাচ ও ইনপুট ব্যবহার করতে হয় তা জানুন।

মাল্টি-টাচ জেসচার হলো যখন একাধিক পয়েন্টার (আঙুল) দিয়ে একই সময়ে স্ক্রিনে ট্যাপ করা হয়। এই ডকুমেন্টে বর্ণনা করা হয়েছে কীভাবে একাধিক পয়েন্টার জড়িত জেসচার শনাক্ত করতে হয়।

একাধিক পয়েন্টার ট্র্যাক করুন

যখন একাধিক পয়েন্টার একই সময়ে স্ক্রিনে ট্যাপ করে, তখন সিস্টেম নিম্নলিখিত টাচ ইভেন্টগুলি তৈরি করে:

  • ACTION_DOWN : যখন প্রথম পয়েন্টারটি স্ক্রিনে ট্যাপ করে তখন এটি পাঠানো হয়। এর মাধ্যমে জেসচারটি শুরু হয়। এই পয়েন্টারের ডেটা MotionEvent এর ইনডেক্স 0 তে সবসময় থাকে।
  • ACTION_POINTER_DOWN : প্রথমটির পরে অতিরিক্ত পয়েন্টার স্ক্রিনে প্রবেশ করলে এটি পাঠানো হয়। আপনি getActionIndex() ব্যবহার করে এইমাত্র ডাউন হওয়া পয়েন্টারটির ইন্ডেক্স পেতে পারেন।
  • ACTION_MOVE : যেকোনো সংখ্যক পয়েন্টার জড়িত কোনো জেসচারে পরিবর্তন ঘটলে এটি পাঠানো হয়।
  • ACTION_POINTER_UP : যখন কোনো নন-প্রাইমারি পয়েন্টার উপরে যায় তখন এটি পাঠানো হয়। আপনি getActionIndex() ব্যবহার করে সদ্য উপরে যাওয়া পয়েন্টারটির ইন্ডেক্স পেতে পারেন।
  • ACTION_UP : যখন শেষ পয়েন্টারটি স্ক্রিন ছেড়ে যায় তখন এটি পাঠানো হয়।
  • ACTION_CANCEL : এর অর্থ হলো, সমস্ত পয়েন্টার সহ সম্পূর্ণ জেসচারটি বাতিল করা হয়েছে।

শুরু এবং শেষের অঙ্গভঙ্গি

একটি জেসচার হলো ACTION_DOWN ইভেন্ট দিয়ে শুরু হয়ে ACTION_UP বা ACTION_CANCEL ইভেন্টের মাধ্যমে শেষ হওয়া একাধিক ঘটনার একটি সমষ্টি। একবারে একটি জেসচারই সক্রিয় থাকে। DOWN, MOVE, UP এবং CANCEL অ্যাকশনগুলো সম্পূর্ণ জেসচারটির উপর প্রযোজ্য হয়। উদাহরণস্বরূপ, ACTION_MOVE সহ একটি ইভেন্ট সেই মুহূর্তে সমস্ত পয়েন্টারকে নিচের দিকে সরানোর নির্দেশ দিতে পারে।

পয়েন্টারগুলির উপর নজর রাখুন

একটি MotionEvent মধ্যে স্বতন্ত্র পয়েন্টারগুলোর অবস্থান ট্র্যাক করতে পয়েন্টারের ইনডেক্স এবং আইডি ব্যবহার করুন।

  • ইনডেক্স : একটি MotionEvent একটি অ্যারেতে পয়েন্টারের তথ্য সংরক্ষণ করে। একটি পয়েন্টারের ইনডেক্স হলো এই অ্যারের মধ্যে তার অবস্থান। বেশিরভাগ MotionEvent মেথড পয়েন্টার আইডির পরিবর্তে পয়েন্টার ইনডেক্সকে প্যারামিটার হিসেবে গ্রহণ করে।
  • আইডি : প্রতিটি পয়েন্টারের একটি আইডি ম্যাপিংও থাকে যা টাচ ইভেন্ট জুড়ে অপরিবর্তিত থাকে, যার ফলে সম্পূর্ণ জেসচার জুড়ে একটি নির্দিষ্ট পয়েন্টারকে ট্র্যাক করা সম্ভব হয়।

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

কোটলিন

private var mActivePointerId: Int = 0

override fun onTouchEvent(event: MotionEvent): Boolean {
    ...
    // Get the pointer ID.
    mActivePointerId = event.getPointerId(0)

    // ... Many touch events later...

    // Use the pointer ID to find the index of the active pointer
    // and fetch its position.
    val (x: Float, y: Float) = event.findPointerIndex(mActivePointerId).let { pointerIndex ->
        // Get the pointer's current position.
        event.getX(pointerIndex) to event.getY(pointerIndex)
    }
    ...
}

জাভা

private int mActivePointerId;

public boolean onTouchEvent(MotionEvent event) {
    ...
    // Get the pointer ID.
    mActivePointerId = event.getPointerId(0);

    // ... Many touch events later...

    // Use the pointer ID to find the index of the active pointer
    // and fetch its position.
    int pointerIndex = event.findPointerIndex(mActivePointerId);
    // Get the pointer's current position.
    float x = event.getX(pointerIndex);
    float y = event.getY(pointerIndex);
    ...
}

একাধিক টাচ পয়েন্টার সমর্থন করার জন্য, আপনি প্রতিটি ACTION_POINTER_DOWN এবং ACTION_DOWN ইভেন্টের সময় সমস্ত সক্রিয় পয়েন্টারকে তাদের আইডি সহ ক্যাশে করতে পারেন। তাদের ACTION_POINTER_UP এবং ACTION_UP ইভেন্টের সময় আপনার ক্যাশে থেকে পয়েন্টারগুলি সরিয়ে ফেলুন। অন্যান্য অ্যাকশন ইভেন্টগুলি সঠিকভাবে পরিচালনা করার জন্য এই ক্যাশে করা আইডিগুলি আপনার জন্য সহায়ক হতে পারে। উদাহরণস্বরূপ, একটি ACTION_MOVE ইভেন্ট প্রক্রিয়া করার সময়, প্রতিটি ক্যাশে করা সক্রিয় পয়েন্টার আইডির জন্য ইন্ডেক্সটি খুঁজুন, getX() এবং getY() ফাংশন ব্যবহার করে পয়েন্টারটির স্থানাঙ্ক পুনরুদ্ধার করুন, তারপর কোন পয়েন্টারগুলি সরেছে তা খুঁজে বের করতে এই স্থানাঙ্কগুলিকে আপনার ক্যাশে করা স্থানাঙ্কের সাথে তুলনা করুন।

getActionIndex() ফাংশনটি শুধুমাত্র ACTION_POINTER_UP এবং ACTION_POINTER_DOWN ইভেন্টের সাথে ব্যবহার করুন। ACTION_MOVE ইভেন্টের সাথে এই ফাংশনটি ব্যবহার করবেন না, কারণ এটি সর্বদা 0 রিটার্ন করে।

MotionEvent অ্যাকশনগুলি পুনরুদ্ধার করুন

একটি MotionEvent এর অ্যাকশন পেতে getActionMasked() মেথড অথবা এর কম্প্যাটিবিলিটি ভার্সন MotionEventCompat.getActionMasked() ব্যবহার করুন। আগের getAction() মেথডের মতো নয়, getActionMasked() একাধিক পয়েন্টারের সাথে কাজ করার জন্য ডিজাইন করা হয়েছে। এটি পয়েন্টার ইনডেক্স ছাড়া অ্যাকশনটি রিটার্ন করে। বৈধ পয়েন্টার ইনডেক্সযুক্ত অ্যাকশনগুলোর জন্য, অ্যাকশনটির সাথে যুক্ত পয়েন্টারগুলোর ইনডেক্স রিটার্ন করতে getActionIndex() ব্যবহার করুন, যেমনটি নিচের কোড স্নিপেটে দেখানো হয়েছে:

কোটলিন

val (xPos: Int, yPos: Int) = MotionEventCompat.getActionMasked(event).let { action ->
    Log.d(DEBUG_TAG, "The action is ${actionToString(action)}")
    // Get the index of the pointer associated with the action.
    MotionEventCompat.getActionIndex(event).let { index ->
        // The coordinates of the current screen contact, relative to
        // the responding View or Activity.
        MotionEventCompat.getX(event, index).toInt() to MotionEventCompat.getY(event, index).toInt()
    }
}

if (event.pointerCount > 1) {
    Log.d(DEBUG_TAG, "Multitouch event")

} else {
    // Single touch event.
    Log.d(DEBUG_TAG, "Single touch event")
}

...

// Given an action int, returns a string description.
fun actionToString(action: Int): String {
    return when (action) {
        MotionEvent.ACTION_DOWN -> "Down"
        MotionEvent.ACTION_MOVE -> "Move"
        MotionEvent.ACTION_POINTER_DOWN -> "Pointer Down"
        MotionEvent.ACTION_UP -> "Up"
        MotionEvent.ACTION_POINTER_UP -> "Pointer Up"
        MotionEvent.ACTION_OUTSIDE -> "Outside"
        MotionEvent.ACTION_CANCEL -> "Cancel"
        else -> ""
    }
}

জাভা

int action = MotionEventCompat.getActionMasked(event);
// Get the index of the pointer associated with the action.
int index = MotionEventCompat.getActionIndex(event);
int xPos = -1;
int yPos = -1;

Log.d(DEBUG_TAG,"The action is " + actionToString(action));

if (event.getPointerCount() > 1) {
    Log.d(DEBUG_TAG,"Multitouch event");
    // The coordinates of the current screen contact, relative to
    // the responding View or Activity.
    xPos = (int)MotionEventCompat.getX(event, index);
    yPos = (int)MotionEventCompat.getY(event, index);

} else {
    // Single touch event.
    Log.d(DEBUG_TAG,"Single touch event");
    xPos = (int)MotionEventCompat.getX(event, index);
    yPos = (int)MotionEventCompat.getY(event, index);
}
...

// Given an action int, returns a string description
public static String actionToString(int action) {
    switch (action) {

        case MotionEvent.ACTION_DOWN: return "Down";
	case MotionEvent.ACTION_MOVE: return "Move";
	case MotionEvent.ACTION_POINTER_DOWN: return "Pointer Down";
	case MotionEvent.ACTION_UP: return "Up";
	case MotionEvent.ACTION_POINTER_UP: return "Pointer Up";
	case MotionEvent.ACTION_OUTSIDE: return "Outside";
	case MotionEvent.ACTION_CANCEL: return "Cancel";
    }
    return "";
}
চিত্র ১. মাল্টি-টাচ ড্রয়িং প্যাটার্ন।

অতিরিক্ত সম্পদ

ইনপুট ইভেন্ট সম্পর্কিত আরও তথ্যের জন্য, নিম্নলিখিত তথ্যসূত্রগুলি দেখুন: