Dokunma hareketi, kullanıcının dokunmatik ekrana bir veya daha fazla parmağını yerleştirmesi ve uygulamanızın bu dokunma şeklini hareket olarak yorumlamasıyla gerçekleşir. Hareket algılamanın iki aşaması vardır:
- Dokunma etkinliği verilerini toplama.
- Uygulamanızın desteklediği hareketlerle ilgili ölçütleri karşılayıp karşılamadığını belirlemek için verileri yorumlama
AndroidX sınıfları
Bu belgedeki örneklerde GestureDetectorCompat ve MotionEventCompat sınıfları kullanılmaktadır. Bu sınıflar AndroidX
Kitaplığı'nda bulunur. Daha eski 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çmez. Bunun yerine, bu etkinlikle ilişkili işlemi almak için MotionEvent nesnenizi ilettiğiniz statik yardımcı program yöntemleri sağlar.
Veri toplama
Bir kullanıcı ekrana bir veya daha fazla parmağını yerleştirdiğinde, dokunma etkinliklerini alan görünümde onTouchEvent() geri çağırma tetiklenir. Dokunma etkinliklerinin her bir dizisi (ör. konum, basınç, boyut ve başka bir parmağın eklenmesi) hareket olarak tanımlandığında onTouchEvent() birkaç kez tetiklenir.
Hareket, kullanıcının ekrana ilk dokunuşuyla başlar, sistem kullanıcının parmağının veya parmaklarının konumunu izlerken devam eder ve kullanıcının son parmağının ekrandan ayrılma etkinliğini yakalayarak sona erer.
Bu etkileşim boyunca, MotionEvent delivered to
onTouchEvent(), her etkileşimin ayrıntılarını sağlar. Uygulamanız, MotionEvent tarafından sağlanan verileri kullanarak ilgilendiği bir hareketin gerçekleşip gerçekleşmediğini belirleyebilir.
Bir etkinlik veya görünüm için dokunma etkinliklerini yakalama
Activity veya View içinde dokunma etkinliklerini yakalamak için onTouchEvent() geri çağırmasını geçersiz kılın.
Aşağıdaki kod snippet'i, kullanıcının gerçekleştirdiği işlemi getAction() parametresinden çıkarmak için event kullanır.
Bu, önemsediğiniz bir hareketin gerçekleşip gerçekleşmediğini belirlemek 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ı dokunup basılı tuttuğu ve sürüklediği için 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, bu etkinliklerin ele almanız gereken bir hareketi temsil edip etmediğini belirlemek üzere kendi işlemlerinizi yapabilirsiniz. Ancak uygulamanızda çift dokunma, dokunup basılı tutma, kaydırma gibi yaygın hareketler kullanılıyorsa GestureDetector sınıfından yararlanabilirsiniz. GestureDetector, dokunma etkinliklerini tek tek işlemenize gerek kalmadan yaygın hareketleri algılamanızı kolaylaştırır. Bu konu Hareketleri 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 yakalama
onTouchEvent() yerine, setOnTouchListener() yöntemini kullanarak herhangi bir View nesnesine View.OnTouchListener nesnesi ekleyebilirsiniz. Bu sayede, aşağıdaki örnekte gösterildiği gibi mevcut bir View öğesini alt sınıfa ayırmadan dokunma etkinliklerini dinlemek mümkün olur:
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 döndüren bir işleyici oluşturmamaya dikkat edin.
Bunu yaparsanız dinleyici, 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 bir görünüm oluşturuyorsanız daha önce açıklandığı gibi onTouchEvent() geçersiz kılabilirsiniz.
Hareketleri algılama
Android, yaygın hareketleri algılamak için GestureDetector sınıfını sağlar. Desteklenen bazı hareketler arasında onDown(), onLongPress() ve onFling() yer alır.
GestureDetector özelliğini, daha önce açıklanan onTouchEvent() yöntemiyle birlikte kullanabilirsiniz.
Desteklenen tüm hareketleri algılama
Bir GestureDetectorCompat nesnesi oluşturduğunuzda, aldığı 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 etkinlik alabilmesi için görünümün 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, on<TouchEvent> yöntemlerinden true dönüş değeri, dokunma etkinliğinin işlendiğini gösterir. false dönüş değeri, dokunma işlemi başarıyla işlenene kadar etkinlikleri görünüm yığınında aşağıya 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 dokunma etkinliği için MotionEvent içeriğinin ne olduğu hakkında fikir edinebilirsiniz. Ardından, basit etkileşimler için ne kadar veri 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ılama
Yalnızca birkaç hareketi işlemek istiyorsanız GestureDetector.SimpleOnGestureListener arayüzünü uygulamak yerine GestureDetector.OnGestureListener arayüzünü genişletebilirsiniz.
GestureDetector.SimpleOnGestureListener, tüm on<TouchEvent> yöntemleri için false döndürerek bir uygulama sağlar. Bu sayede yalnızca önem verdiğiniz yöntemleri geçersiz kılabilirsiniz. Örneğin, aşağıdaki kod snippet'i, GestureDetector.SimpleOnGestureListener öğesini genişleten ve onFling() ile onDown() öğesini geçersiz kılan bir sınıf oluşturur.
GestureDetector.OnGestureListener veya GestureDetector.SimpleOnGestureListener kullanmanız fark etmeksizin, true döndüren bir onDown() yöntemi uygulamak en iyi uygulamadır. Bunun nedeni, tüm hareketlerin onDown() mesajıyla başlamasıdır. GestureDetector.SimpleOnGestureListener'ın varsayılan olarak yaptığı gibi onDown()'tan false döndürürseniz sistem, hareketin geri kalanını yoksaymak istediğinizi varsayar ve GestureDetector.OnGestureListener'ün diğer yöntemleri çağrılmaz. Bu durum, uygulamanızda beklenmedik sorunlara neden olabilir. Yalnızca bir hareketin tamamını gerçekten yoksaymak istiyorsanız false değerini onDown() öğesinden 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; } } }