Çoklu dokunma hareketlerini işleme

Oluşturma yöntemini deneyin
Jetpack Compose, Android için önerilen kullanıcı arayüzü araç setidir. Oluşturma'da dokunma ve giriş işlevini nasıl kullanacağınızı öğrenin.

Çoklu dokunma hareketi, ekrana birden fazla işaretçinin (parmakların) aynı anda dokunmasıdır. Bu dokümanda, birden çok işaretçi içeren hareketlerin nasıl algılanacağı açıklanmaktadır.

Birden fazla işaretçiyi takip edin

Ekrana aynı anda birden fazla işaretçi dokunduğunda sistem aşağıdaki dokunma etkinliklerini oluşturur:

  • ACTION_DOWN: İlk işaretçi ekrana dokunduğunda gönderilir. Bu işlem, hareketi başlatır. Bu işaretçinin işaretçi verileri her zaman MotionEvent için 0 dizinindedir.
  • ACTION_POINTER_DOWN: Ekstra işaretçiler ilkinden sonra ekrana girdiğinde gönderilir. Az önce düşen işaretçinin dizinini getActionIndex() kullanarak alabilirsiniz.
  • ACTION_MOVE: Herhangi bir sayıda işaretçi içeren bir harekette değişiklik gerçekleştiğinde gönderilir.
  • ACTION_POINTER_UP: Birincil olmayan işaretçi yükseldiğinde gönderilir. getActionIndex() işlevini kullanarak az önce artan işaretçinin dizinini alabilirsiniz.
  • ACTION_UP: Son işaretçi ekrandan ayrıldığında gönderilir.
  • ACTION_CANCEL: Tüm işaretçiler dahil olmak üzere hareketin tamamının iptal edildiğini belirtir.

Başlangıç ve bitiş hareketleri

Hareket, bir ACTION_DOWN etkinliğiyle başlayıp ACTION_UP veya ACTION_CANCEL etkinliğiyle sona eren bir etkinlik dizisidir. Aynı anda tek bir etkin hareket vardır. AŞAĞI, TAŞI, YUKARI ve İPTAL işlemleri, tüm hareket için geçerli olur. Örneğin, ACTION_MOVE içeren bir etkinlik, tüm işaretçilerin o anda aşağı doğru bir hareket ettiğini gösterebilir.

İşaretçileri takip edin

MotionEvent içindeki bağımsız işaretçi konumlarını takip etmek için işaretçinin dizinini ve kimliğini kullanın.

  • Dizin: MotionEvent, bir dizide işaretçi bilgilerini depolar. Bir işaretçinin dizini, bu dizi içindeki konumudur. MotionEvent yöntemlerinin çoğu, işaretçi dizinini işaretçi kimliği yerine parametre olarak alır.
  • Kimlik: Her işaretçi, tek bir işaretçinin hareketin tamamında izlenebilmesi için dokunma etkinliklerinde kalıcı kalan bir kimlik eşlemesi de bulunur.

İşaretçiler tek tek, bir hareket etkinliğinde tanımlanmamış bir sırada görünür. Bu nedenle, işaretçinin dizini bir etkinlikten diğerine değişebilir ancak işaretçinin işaretçi kimliğinin, işaretçi etkin kaldığı sürece sabit kalması garanti edilir. İşaretçiyi bir harekette izleyen tüm hareket etkinliklerinde izlemek amacıyla işaretçi kimliğini almak için getPointerId() yöntemini kullanın. Ardından, art arda gerçekleşen hareket etkinlikleri için söz konusu hareket etkinliğindeki belirli bir işaretçi kimliğinin işaretçi dizinini almak için findPointerIndex() yöntemini kullanın. Örnek:

Kotlin

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

Java

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

Birden çok temas işaretçisini desteklemek için, kimlikleriyle birlikte tüm etkin işaretçileri kendi ACTION_POINTER_DOWN ve ACTION_DOWN etkinlik zamanında önbelleğe alabilirsiniz. Önbelleğinizden ACTION_POINTER_UP ve ACTION_UP etkinliklerinde işaretçileri kaldırın. Önbelleğe alınan bu kimlikleri, diğer işlem etkinliklerini doğru şekilde yönetme konusunda işinize yarayabilir. Örneğin, bir ACTION_MOVE etkinliğini işlerken önbelleğe alınan her etkin işaretçi kimliğinin dizinini bulun, getX() ve getY() işlevlerini kullanarak işaretçi koordinatlarını alın, ardından hangi işaretçilerin hareket ettiğini öğrenmek için bu koordinatları önbelleğe alınmış koordinatlarınızla karşılaştırın.

getActionIndex() işlevini yalnızca ACTION_POINTER_UP ve ACTION_POINTER_DOWN etkinlikleriyle kullanın. Her zaman 0 sonucunu döndürdüğünden bu işlevi ACTION_MOVE etkinlikleriyle kullanmayın.

MotionEvent işlemi al

MotionEvent işlemini almak için getActionMasked() yöntemini veya uyumluluk sürümünü MotionEventCompat.getActionMasked() kullanın. Önceki getAction() yönteminden farklı olarak getActionMasked(), birden fazla işaretçiyle çalışacak şekilde tasarlanmıştır. İşlem, işaretçi dizinleri olmadan döndürür. Geçerli bir işaretçi dizini olan işlemlerde, aşağıdaki snippet'te gösterildiği gibi işlemle ilişkili işaretçilerin dizinini döndürmek için getActionIndex() kullanın:

Kotlin

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

Java

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 "";
}
Şekil 1. Çoklu dokunmayla çizim desenleri.

Ek kaynaklar

Giriş etkinlikleriyle ilgili daha fazla bilgi için aşağıdaki referanslara bakın: