ژست های چند لمسی را مدیریت کنید

روش Compose را امتحان کنید
Jetpack Compose جعبه ابزار UI توصیه شده برای اندروید است. با نحوه استفاده از لمس و ورودی در Compose آشنا شوید.

یک حرکت چند لمسی زمانی است که چندین اشاره گر (انگشت) به طور همزمان روی صفحه ضربه می زنند. این سند نحوه تشخیص حرکاتی که شامل چندین اشاره گر هستند را توضیح می دهد.

چندین اشاره گر را ردیابی کنید

هنگامی که چندین اشاره گر به طور همزمان روی صفحه ضربه می زنند، سیستم رویدادهای لمسی زیر را ایجاد می کند:

  • ACTION_DOWN : زمانی که اولین اشاره گر روی صفحه ضربه می زند ارسال می شود. این ژست را شروع می کند. داده های اشاره گر برای این اشاره گر همیشه در شاخص 0 در MotionEvent است.
  • 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 استفاده کنید.

  • Index : یک 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

از متد getActionMasked() یا نسخه سازگاری MotionEventCompat.getActionMasked() برای بازیابی عملکرد یک MotionEvent استفاده کنید. برخلاف متد 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 "";
}
شکل 1. الگوهای طراحی چند لمسی.

منابع اضافی

برای اطلاعات بیشتر در رابطه با رویدادهای ورودی، به مراجع زیر مراجعه کنید: