Çoklu dokunma hareketlerini işleme

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

Çoklu dokunma hareketi, birden fazla işaretçi (parmak) ekrana aynı anda dokunduğunda gerçekleşir. Bu dokümanda, birden fazla işaretçi içeren hareketlerin nasıl algılanacağı açıklanmaktadır.

Birden çok işaretçiyi izleme

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

  • ACTION_DOWN: ilk işaretçi ekrana dokunduğunda gönderilir. Bu işlem, hareketi başlatır. Bu işaretçi için işaretçi verileri her zaman MotionEvent içindeki 0 dizinindedir.
  • ACTION_POINTER_DOWN: İlkinden sonra ekrana fazladan işaretçiler girdiğinde gönderilir. getActionIndex() kullanarak az önce aşağı inen işaretçinin dizinini edinebilirsiniz.
  • 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 çıktığında gönderilir. getActionIndex() kullanarak, az önce yukarı çıkan işaretçinin dizinini edinebilirsiniz.
  • 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 gösterir.

Başlangıç ve bitiş hareketleri

Hareket, bir ACTION_DOWN etkinliği ile başlayıp ACTION_UP veya ACTION_CANCEL etkinliği ile biten bir dizi etkinliktir. Aynı anda tek bir etkin hareket var. AŞAĞI, TAŞI, YUKARI ve İPTAL işlemleri hareketin tamamına uygulanır. Örneğin, ACTION_MOVE içeren bir etkinlik, o andaki tüm işaretçiler için bir hareketi gösterebilir.

İşaretçileri takip edin

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

  • Dizin: MotionEvent, işaretçi bilgilerini bir dizide depolar. İşaretçinin dizini, bu dizideki konumudur. MotionEvent yöntemlerinin çoğu, işaretçi dizinini işaretçi kimliği yerine parametre olarak alır.
  • Kimlik: Belirli bir işaretçinin hareket genelinde izlenmesini sağlamak için her işaretçinin dokunma etkinliklerinde kalıcı kalan bir kimlik eşlemesi de vardır.

Bağımsız işaretçiler, bir hareket etkinliğinde tanımlanmamış bir sırada görünür. Bu nedenle, bir işaretçinin dizini bir etkinlikten diğerine değişebilir ancak işaretçi etkin olduğu sürece işaretçinin işaretçi kimliğinin sabit kalması garanti edilir. Bir hareketle sonraki tüm hareket etkinliklerinde işaretçiyi takip etmek için işaretçinin kimliğini almak amacıyla getPointerId() yöntemini kullanın. Ardından, ardışık hareket etkinlikleri için findPointerIndex() yöntemini kullanarak söz konusu hareket etkinliğindeki belirli bir işaretçi kimliğinin işaretçi dizinini elde edin. Ö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 fazla temas işaretçisini desteklemek için tüm etkin işaretçileri kendi ACTION_POINTER_DOWN ve ACTION_DOWN etkinlik zamanlarında kimlikleriyle önbelleğe alabilirsiniz. ACTION_POINTER_UP ve ACTION_UP etkinliklerinde işaretçileri önbelleğinizden kaldırın. Önbelleğe alınan bu kimlikleri, diğer işlem etkinliklerini doğru şekilde işleme konusunda yararlı bulabilirsiniz. Ö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çinin koordinatlarını alın, ardından hangi işaretçilerin taşındığını bulmak 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 değerini 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 çok işaretçiyle çalışacak şekilde tasarlanmıştır. İşlemi işaretçi dizinleri olmadan döndürür. Geçerli bir işaretçi dizini olan işlemler için işlemle ilişkili işaretçilerin dizinini aşağıdaki snippet'te gösterildiği gibi döndürmek amacıyla 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: