Genel hareketleri algılama

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.

Kullanıcı dokunmatik ekrana bir veya daha fazla parmağı koyduğunda ve uygulamanız bu dokunma kalıbını bir hareket olarak yorumladığında dokunma hareketi meydana gelir. Hareket algılama iki aşamadan oluşur:

  1. Dokunma etkinliği verileri toplanıyor.
  2. Uygulamanızın desteklediği hareketlerle ilgili ölçütleri karşılayıp karşılamadığını belirlemek için verileri yorumlama.

AndroidX dersleri

Bu belgedeki örneklerde GestureDetectorCompat ve MotionEventCompat sınıfları kullanılmaktadır. Bu sınıflar AndroidX Kitaplığında yer alır. Önceki cihazlarla uyumluluk sağlamak için mümkün olduğunda AndroidX sınıflarını kullanın. MotionEventCompat, MotionEvent sınıfının yerine geçen bir değildir. Bunun yerine, söz konusu etkinlikle ilişkili işlemi almak için MotionEvent nesnenizi ilettiğiniz statik yardımcı program yöntemleri sağlar.

Veri toplama

Kullanıcı ekrana bir veya daha fazla parmağı koyduğunda, dokunma etkinliklerini alan görünümde geri çağırma işlemionTouchEvent() tetiklenir. Konum, basınç, boyut ve başka bir parmağın eklenmesi gibi hareket olarak tanımlanan her dokunma etkinliği dizisi için onTouchEvent() birkaç kez tetiklenir.

Hareket, kullanıcı ekrana ilk kez dokunduğunda başlar, sistem kullanıcının parmağının veya parmaklarının konumunu izlerken devam eder ve kullanıcının ekrandan ayrılan son parmağının son etkinliğinin yakalanmasıyla sona erer. Bu etkileşim sırasında, onTouchEvent() üzerinde yayınlanan MotionEvent her etkileşimin ayrıntılarını sağlar. Uygulamanız, önemli bir hareketin gerçekleşip gerçekleşmediğini belirlemek için MotionEvent tarafından sağlanan verileri kullanabilir.

Bir Etkinlik veya Görünüm için dokunma etkinliklerini kaydetme

Activity veya View öğesinde dokunma etkinliklerine müdahale etmek için onTouchEvent() geri çağırma işlevini geçersiz kılın.

Aşağıdaki kod snippet'i, kullanıcının gerçekleştirdiği işlemi event parametresinden ayıklamak için getAction() özelliğini kullanır. Bu, önem verdiğiniz bir hareketin gerçekleşip gerçekleşmediğini belirlemeniz için ihtiyacınız olan ham verileri sağlar.

Kotlin

class MainActivity : Activity() {
    ...
    // This example shows an Activity. You can use the same approach if you are 
    // subclassing a View.
    override fun onTouchEvent(event: MotionEvent): Boolean {
        return when (event.action) {
            MotionEvent.ACTION_DOWN -> {
                Log.d(DEBUG_TAG, "Action was DOWN")
                true
            }
            MotionEvent.ACTION_MOVE -> {
                Log.d(DEBUG_TAG, "Action was MOVE")
                true
            }
            MotionEvent.ACTION_UP -> {
                Log.d(DEBUG_TAG, "Action was UP")
                true
            }
            MotionEvent.ACTION_CANCEL -> {
                Log.d(DEBUG_TAG, "Action was CANCEL")
                true
            }
            MotionEvent.ACTION_OUTSIDE -> {
                Log.d(DEBUG_TAG, "Movement occurred outside bounds of current screen element")
                true
            }
            else -> super.onTouchEvent(event)
        }
    }
}

Java

public class MainActivity extends Activity {
...
// This example shows an Activity. You can use the same approach if you are
// subclassing a View.
@Override
public boolean onTouchEvent(MotionEvent event){
    switch(event.getAction()) {
        case (MotionEvent.ACTION_DOWN) :
            Log.d(DEBUG_TAG,"Action was DOWN");
            return true;
        case (MotionEvent.ACTION_MOVE) :
            Log.d(DEBUG_TAG,"Action was MOVE");
            return true;
        case (MotionEvent.ACTION_UP) :
            Log.d(DEBUG_TAG,"Action was UP");
            return true;
        case (MotionEvent.ACTION_CANCEL) :
            Log.d(DEBUG_TAG,"Action was CANCEL");
            return true;
        case (MotionEvent.ACTION_OUTSIDE) :
            Log.d(DEBUG_TAG,"Movement occurred outside bounds of current screen element");
            return true;
        default :
            return super.onTouchEvent(event);
    }
}

Bu kod, kullanıcı dokunarak, basılı tutarak ve sürüklerken Logcat'te aşağıdaki gibi mesajlar oluşturur:

GESTURES D   Action was DOWN
GESTURES D   Action was UP
GESTURES D   Action was MOVE

Özel hareketler için, kullanmanız gereken bir hareketi temsil edip etmediklerini belirlemek amacıyla bu etkinliklerde kendi işlemenizi yapabilirsiniz. Ancak uygulamanızda iki kez dokunma, dokunup basılı tutma, hızla sallama vb. yaygın hareketler kullanılıyorsa GestureDetector sınıfından yararlanabilirsiniz. GestureDetector, dokunma etkinliklerini kendiniz işlemeden genel hareketleri algılamanızı kolaylaştırır. Bu konu, Hareket algılama bölümünde daha ayrıntılı olarak ele alınmaktadır.

Tek bir görünüm için dokunma etkinliklerini kaydedin

onTouchEvent() özelliğine alternatif olarak, setOnTouchListener() yöntemini kullanarak herhangi bir View nesnesine View.OnTouchListener nesnesi ekleyebilirsiniz. Bu, aşağıdaki örnekte gösterildiği gibi, mevcut bir View öğesini alt kategorilere ayırmadan dokunma etkinliklerini dinlemeyi mümkün kılar:

Kotlin

findViewById<View>(R.id.my_view).setOnTouchListener { v, event ->
    // Respond to touch events.
    true
}

Java

View myView = findViewById(R.id.my_view);
myView.setOnTouchListener(new OnTouchListener() {
    public boolean onTouch(View v, MotionEvent event) {
        // Respond to touch events.
        return true;
    }
});

ACTION_DOWN etkinliği için false değerini döndüren bir işleyici oluşturmaya dikkat edin. Bunu yaparsanız işleyici, sonraki ACTION_MOVE ve ACTION_UP etkinlik dizisi için çağrılmaz. Bunun nedeni, tüm dokunma etkinliklerinin başlangıç noktasının ACTION_DOWN olmasıdır.

Özel görünüm oluşturuyorsanız daha önce açıklandığı gibi onTouchEvent() öğesini geçersiz kılabilirsiniz.

Hareketleri algıla

Android, genel hareketleri algılamak için GestureDetector sınıfını sağlar. Desteklediği hareketlerden bazıları şunlardır: onDown(), onLongPress() ve onFling(). GestureDetector özelliğini daha önce açıklanan onTouchEvent() yöntemiyle birlikte kullanabilirsiniz.

Desteklenen tüm hareketleri algıla

Bir GestureDetectorCompat nesnesini örneklendirmek için gereken parametrelerden biri, GestureDetector.OnGestureListener arayüzünü uygulayan bir sınıftır. GestureDetector.OnGestureListener, belirli bir dokunma etkinliği gerçekleştiğinde kullanıcıları bilgilendirir. GestureDetector nesnenizin etkinlikleri almasını mümkün kılmak için görünüm veya etkinliğin onTouchEvent() yöntemini geçersiz kılın ve gözlemlenen tüm etkinlikleri algılayıcı örneğine iletin.

Aşağıdaki snippet'te, tek tek on<TouchEvent> yöntemlerinden true döndürülmesi, dokunma etkinliğinin işlendiğini gösterir. false döndürülen değeri, dokunma başarıyla işlenene kadar etkinlikleri görünüm yığınından geçirir.

Aşağıdaki snippet'i bir test uygulamasında çalıştırırsanız dokunmatik ekranla etkileşimde bulunduğunuzda işlemlerin nasıl tetiklendiği ve her bir dokunma etkinliği için MotionEvent içeriğinin ne olduğu hakkında bir fikir edinebilirsiniz. Ardından, basit etkileşimler için ne kadar verinin oluşturulduğunu görürsünüz.

Kotlin

private const val DEBUG_TAG = "Gestures"

class MainActivity :
        Activity(),
        GestureDetector.OnGestureListener,
        GestureDetector.OnDoubleTapListener {

    private lateinit var mDetector: GestureDetectorCompat

    // Called when the activity is first created.
    public override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        // Instantiate the gesture detector with the
        // application context and an implementation of
        // GestureDetector.OnGestureListener.
        mDetector = GestureDetectorCompat(this, this)
        // Set the gesture detector as the double-tap
        // listener.
        mDetector.setOnDoubleTapListener(this)
    }

    override fun onTouchEvent(event: MotionEvent): Boolean {
        return if (mDetector.onTouchEvent(event)) {
            true
        } else {
            super.onTouchEvent(event)
        }
    }

    override fun onDown(event: MotionEvent): Boolean {
        Log.d(DEBUG_TAG, "onDown: $event")
        return true
    }

    override fun onFling(
            event1: MotionEvent,
            event2: MotionEvent,
            velocityX: Float,
            velocityY: Float
    ): Boolean {
        Log.d(DEBUG_TAG, "onFling: $event1 $event2")
        return true
    }

    override fun onLongPress(event: MotionEvent) {
        Log.d(DEBUG_TAG, "onLongPress: $event")
    }

    override fun onScroll(
            event1: MotionEvent,
            event2: MotionEvent,
            distanceX: Float,
            distanceY: Float
    ): Boolean {
        Log.d(DEBUG_TAG, "onScroll: $event1 $event2")
        return true
    }

    override fun onShowPress(event: MotionEvent) {
        Log.d(DEBUG_TAG, "onShowPress: $event")
    }

    override fun onSingleTapUp(event: MotionEvent): Boolean {
        Log.d(DEBUG_TAG, "onSingleTapUp: $event")
        return true
    }

    override fun onDoubleTap(event: MotionEvent): Boolean {
        Log.d(DEBUG_TAG, "onDoubleTap: $event")
        return true
    }

    override fun onDoubleTapEvent(event: MotionEvent): Boolean {
        Log.d(DEBUG_TAG, "onDoubleTapEvent: $event")
        return true
    }

    override fun onSingleTapConfirmed(event: MotionEvent): Boolean {
        Log.d(DEBUG_TAG, "onSingleTapConfirmed: $event")
        return true
    }

}

Java

public class MainActivity extends Activity implements
        GestureDetector.OnGestureListener,
        GestureDetector.OnDoubleTapListener{

    private static final String DEBUG_TAG = "Gestures";
    private GestureDetectorCompat mDetector;

    // Called when the activity is first created.
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // Instantiate the gesture detector with the
        // application context and an implementation of
        // GestureDetector.OnGestureListener.
        mDetector = new GestureDetectorCompat(this,this);
        // Set the gesture detector as the double-tap
        // listener.
        mDetector.setOnDoubleTapListener(this);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event){
        if (this.mDetector.onTouchEvent(event)) {
            return true;
        }
        return super.onTouchEvent(event);
    }

    @Override
    public boolean onDown(MotionEvent event) {
        Log.d(DEBUG_TAG,"onDown: " + event.toString());
        return true;
    }

    @Override
    public boolean onFling(MotionEvent event1, MotionEvent event2,
            float velocityX, float velocityY) {
        Log.d(DEBUG_TAG, "onFling: " + event1.toString() + event2.toString());
        return true;
    }

    @Override
    public void onLongPress(MotionEvent event) {
        Log.d(DEBUG_TAG, "onLongPress: " + event.toString());
    }

    @Override
    public boolean onScroll(MotionEvent event1, MotionEvent event2, float distanceX,
            float distanceY) {
        Log.d(DEBUG_TAG, "onScroll: " + event1.toString() + event2.toString());
        return true;
    }

    @Override
    public void onShowPress(MotionEvent event) {
        Log.d(DEBUG_TAG, "onShowPress: " + event.toString());
    }

    @Override
    public boolean onSingleTapUp(MotionEvent event) {
        Log.d(DEBUG_TAG, "onSingleTapUp: " + event.toString());
        return true;
    }

    @Override
    public boolean onDoubleTap(MotionEvent event) {
        Log.d(DEBUG_TAG, "onDoubleTap: " + event.toString());
        return true;
    }

    @Override
    public boolean onDoubleTapEvent(MotionEvent event) {
        Log.d(DEBUG_TAG, "onDoubleTapEvent: " + event.toString());
        return true;
    }

    @Override
    public boolean onSingleTapConfirmed(MotionEvent event) {
        Log.d(DEBUG_TAG, "onSingleTapConfirmed: " + event.toString());
        return true;
    }
}

Desteklenen hareketlerin bir alt kümesini algıla

Yalnızca birkaç hareketi işlemek istiyorsanız GestureDetector.OnGestureListener arayüzünü uygulamak yerine GestureDetector.SimpleOnGestureListener hareketini genişletebilirsiniz.

GestureDetector.SimpleOnGestureListener, hepsi için false döndürerek on<TouchEvent> yöntemlerinin tümü için bir uygulama sağlar. Bu, yalnızca önem verdiğiniz yöntemleri geçersiz kılmanıza olanak tanır. Örneğin, aşağıdaki kod snippet'i GestureDetector.SimpleOnGestureListener öğesini genişleten ve onFling() ile onDown() değerlerini geçersiz kılan bir sınıf oluşturur.

GestureDetector.OnGestureListener veya GestureDetector.SimpleOnGestureListener kullanmanızdan bağımsız olarak, true döndüren bir onDown() yöntemi uygulamak en iyi uygulamadır. Bunun nedeni, tüm hareketlerin bir onDown() mesajıyla başlamasıdır. Varsayılan olarak GestureDetector.SimpleOnGestureListener tarafından yapılan gibi onDown() öğesinden false döndürürseniz sistem, hareketin geri kalanını yoksaymak istediğinizi varsayar ve diğer GestureDetector.OnGestureListener yöntemleri çağrılmaz. Bu, uygulamanızda beklenmedik sorunlara neden olabilir. Yalnızca bir hareketin tamamını gerçekten yoksaymak istiyorsanız onDown() öğesinden false değerini döndürün.

Kotlin

private const val DEBUG_TAG = "Gestures"

class MainActivity : Activity() {

    private lateinit var mDetector: GestureDetectorCompat

    public override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        mDetector = GestureDetectorCompat(this, MyGestureListener())
    }

    override fun onTouchEvent(event: MotionEvent): Boolean {
        mDetector.onTouchEvent(event)
        return super.onTouchEvent(event)
    }

    private class MyGestureListener : GestureDetector.SimpleOnGestureListener() {

        override fun onDown(event: MotionEvent): Boolean {
            Log.d(DEBUG_TAG, "onDown: $event")
            return true
        }

        override fun onFling(
                event1: MotionEvent,
                event2: MotionEvent,
                velocityX: Float,
                velocityY: Float
        ): Boolean {
            Log.d(DEBUG_TAG, "onFling: $event1 $event2")
            return true
        }
    }
}

Java

public class MainActivity extends Activity {

    private GestureDetectorCompat mDetector;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mDetector = new GestureDetectorCompat(this, new MyGestureListener());
    }

    @Override
    public boolean onTouchEvent(MotionEvent event){
        if (this.mDetector.onTouchEvent(event)) {
              return true;
        }
        return super.onTouchEvent(event);
    }

    class MyGestureListener extends GestureDetector.SimpleOnGestureListener {
        private static final String DEBUG_TAG = "Gestures";

        @Override
        public boolean onDown(MotionEvent event) {
            Log.d(DEBUG_TAG,"onDown: " + event.toString());
            return true;
        }

        @Override
        public boolean onFling(MotionEvent event1, MotionEvent event2,
                float velocityX, float velocityY) {
            Log.d(DEBUG_TAG, "onFling: " + event1.toString() + event2.toString());
            return true;
        }
    }
}

Ek kaynaklar