Çoklu dokunma hareketlerini işleme

Oluşturma yöntemini deneyin
Android için önerilen kullanıcı arayüzü araç seti Jetpack Compose'dur. Oluştur'da dokunma ve girişi 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 fazla işaretçiyi takip etme

Birden fazla işaretçi aynı anda ekrana 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çinin işaretçi verileri her zaman MotionEvent içinde 0 dizinindedir.
  • ACTION_POINTER_DOWN: ilk işaretçiden sonra ekrana ekstra işaretçiler girdiğinde gönderilir. getActionIndex() kullanarak, az önce aşağı doğru hareket eden işaretçinin dizin numarasını elde edebilirsiniz.
  • ACTION_MOVE: Herhangi bir sayıda işaretçi içeren bir harekette değişiklik olduğunda gönderilir.
  • ACTION_POINTER_UP: Birincil olmayan bir işaretçi yukarı gittiğinde gönderilir. getActionIndex() kullanarak az önce yukarı giden işaretçinin dizin değerini elde edebilirsiniz.
  • ACTION_UP: Son işaretçi ekrandan çıktığında gönderilir.
  • ACTION_CANCEL: Tüm işaretçiler dahil olmak üzere hareketin tamamının iptal edildiğini belirtir.

Başlatma ve bitirme hareketleri

Hareket, ACTION_DOWN etkinliğiyle başlayan ve ACTION_UP veya ACTION_CANCEL etkinliğiyle biten bir etkinlik dizisidir. Aynı anda yalnızca bir hareket etkindir. AŞAĞI, TAŞI, YUKARI ve İPTAL işlemleri hareketin tamamı için geçerlidir. Örneğin, ACTION_MOVE içeren bir etkinlik, o anda tüm işaretçilerin aşağı doğru hareket ettiğini gösterebilir.

İşaretçileri takip etme

Bir MotionEvent içindeki ayrı işaretçi konumlarını takip etmek için işaretçinin dizini ve kimliğini kullanın.

  • Dizin: MotionEvent, bir dizede işaretçi bilgilerini depolar. Bir işaretçinin dizini, bu diziye göre konumudur. MotionEvent yöntemlerinin çoğu, işaretçi kimliği yerine işaretçi dizini parametresini alır.
  • Noktalayıcı kimliği: Her işaretçi, hareketin tamamında tek bir işaretçinin izlenmesine olanak tanımak için dokunma etkinliklerinde kalıcı kalan bir kimlik eşlemesine de sahiptir.

Bir hareket etkinliğindeki ayrı işaretçiler 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. İşaretçinin kimliğini almak için getPointerId() yöntemini kullanarak işaretçiyi bir hareketteki tüm hareket etkinliklerinde izleyin. Ardından, art arda gelen hareket etkinlikleri için söz konusu hareket etkinliğindeki belirli bir işaretçi kimliğinin işaretçi dizini elde etmek üzere 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 fazla dokunma işaretçisini desteklemek için tüm etkin işaretçileri, kimlikleriyle birlikte kendi ACTION_POINTER_DOWN ve ACTION_DOWN etkinlik zamanlarında önbelleğe alabilirsiniz. İşaretçileri, ACTION_POINTER_UP ve ACTION_UP etkinliklerinde önbelleğinizden kaldırın. Diğer işlem etkinliklerini doğru şekilde işlemek için bu önbelleğe alınmış kimlikleri yararlı bulabilirsiniz. Örneğin, bir ACTION_MOVE etkinliğini işlerken, önbelleğe alınmış her etkin işaretçi kimliğinin dizini bulun, getX() ve getY() işlevlerini kullanarak işaretçinin koordinatlarını alın, ardından hangi işaretçilerin hareket ettiğini 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. Bu işlev her zaman 0 döndürdüğü için ACTION_MOVE etkinlikleriyle kullanmayın.

MotionEvent işlemlerini alma

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. İşaretçi dizinleri olmadan işlemi döndürür. Geçerli bir işaretçi dizine sahip işlemler için aşağıdaki snippet'te gösterildiği gibi işlemle ilişkili işaretçilerin dizini döndürmek üzere getActionIndex() öğesini 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 dokunma çizim kalıpları.

Ek kaynaklar

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