Bu derste, dokunma etkinliklerindeki hareketin nasıl izleneceği açıklanmaktadır.
Mevcut dokunma temasının konumu, basıncı veya boyutu her değiştiğinde ACTION_MOVE etkinliğiyle yeni bir onTouchEvent() tetiklenir. Genel hareketleri algılama bölümünde açıklandığı gibi, bu etkinliklerin tümü onTouchEvent() parametresinin MotionEvent parametresine kaydedilir.
Parmakla dokunma her zaman en hassas etkileşim şekli olmadığından, dokunma etkinliklerinin algılanması genellikle basit temastan ziyade harekete dayanır. Android, uygulamaların harekete dayalı hareketler (ör. kaydırma) ile harekete dayalı olmayan hareketler (ör. tek dokunma) arasında ayrım yapmasına yardımcı olmak için dokunma eğimi kavramını içerir. Dokunma toleransı, kullanıcının dokunuşunun harekete dayalı bir hareket olarak yorumlanmadan önce kaç piksel hareket edebileceğini ifade eder. Bu konu hakkında daha fazla bilgi için ViewGroup'taki dokunma etkinliklerini yönetme başlıklı makaleyi inceleyin.
Uygulamanızın ihtiyaçlarına bağlı olarak, bir hareketteki hareketi izlemenin çeşitli yolları vardır. Örnekler:
- Bir işaretçinin başlangıç ve bitiş konumu (ör. ekrandaki bir nesneyi A noktasından B noktasına taşıma).
- İşaretçinin X ve Y koordinatları tarafından belirlenen hareket yönü.
- Geçmiş'e dokunun.
MotionEventyöntemini çağırarak bir hareketin geçmişinin boyutunu bulabilirsinizgetHistorySize(). Daha sonra, hareket etkinliğiningetHistorical<Value>yöntemlerini kullanarak geçmiş etkinliklerin her birinin konumlarını, boyutlarını, zamanını ve basınçlarını elde edebilirsiniz. Geçmiş, kullanıcının parmağının izini oluştururken (ör. dokunarak çizim yaparken) kullanışlıdır. Ayrıntılar içinMotionEventreferansına bakın. - İşaretçinin dokunmatik ekranda hareket ederken sahip olduğu hız.
Aşağıdaki ilgili kaynaklara göz atın:
Parça hızı
İşaretçinin katettiği mesafeye veya yöne dayalı, harekete dayalı bir hareket kullanabilirsiniz. Ancak hız, genellikle bir hareketin özelliklerini izlemede veya hareketin gerçekleşip gerçekleşmediğine karar vermede belirleyici bir faktördür. Android, hız hesaplamasını kolaylaştırmak için VelocityTracker sınıfını sağlar.
VelocityTracker, dokunma etkinliklerinin hızını izlemenize yardımcı olur. Bu, hızın hareket ölçütlerinden biri olduğu hareketler (ör. hızlıca kaydırma) için kullanışlıdır.
VelocityTracker API'sindeki yöntemlerin amacını gösteren bir örneği aşağıda bulabilirsiniz:
Kotlin
private const val DEBUG_TAG = "Velocity" class MainActivity : Activity() { private var mVelocityTracker: VelocityTracker? = null override fun onTouchEvent(event: MotionEvent): Boolean { when (event.actionMasked) { MotionEvent.ACTION_DOWN -> { // Reset the velocity tracker back to its initial state. mVelocityTracker?.clear() // If necessary, retrieve a new VelocityTracker object to watch // the velocity of a motion. mVelocityTracker = mVelocityTracker ?: VelocityTracker.obtain() // Add a user's movement to the tracker. mVelocityTracker?.addMovement(event) } MotionEvent.ACTION_MOVE -> { mVelocityTracker?.apply { val pointerId: Int = event.getPointerId(event.actionIndex) addMovement(event) // When you want to determine the velocity, call // computeCurrentVelocity(). Then, call getXVelocity() and // getYVelocity() to retrieve the velocity for each pointer // ID. computeCurrentVelocity(1000) // Log velocity of pixels per second. It's best practice to // use VelocityTrackerCompat where possible. Log.d("", "X velocity: ${getXVelocity(pointerId)}") Log.d("", "Y velocity: ${getYVelocity(pointerId)}") } } MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> { // Return a VelocityTracker object back to be re-used by others. mVelocityTracker?.recycle() mVelocityTracker = null } } return true } }
Java
public class MainActivity extends Activity { private static final String DEBUG_TAG = "Velocity"; ... private VelocityTracker mVelocityTracker = null; @Override public boolean onTouchEvent(MotionEvent event) { int index = event.getActionIndex(); int action = event.getActionMasked(); int pointerId = event.getPointerId(index); switch(action) { case MotionEvent.ACTION_DOWN: if(mVelocityTracker == null) { // Retrieve a new VelocityTracker object to watch the // velocity of a motion. mVelocityTracker = VelocityTracker.obtain(); } else { // Reset the velocity tracker back to its initial state. mVelocityTracker.clear(); } // Add a user's movement to the tracker. mVelocityTracker.addMovement(event); break; case MotionEvent.ACTION_MOVE: mVelocityTracker.addMovement(event); // When you want to determine the velocity, call // computeCurrentVelocity(). Then call getXVelocity() and // getYVelocity() to retrieve the velocity for each pointer ID. mVelocityTracker.computeCurrentVelocity(1000); // Log velocity of pixels per second. It's best practice to use // VelocityTrackerCompat where possible. Log.d("", "X velocity: " + mVelocityTracker.getXVelocity(pointerId)); Log.d("", "Y velocity: " + mVelocityTracker.getYVelocity(pointerId)); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: // Return a VelocityTracker object back to be re-used by others. mVelocityTracker.recycle(); break; } return true; } }
İşaretçi yakalama özelliğini kullanma
Oyunlar, uzaktan masaüstü ve sanallaştırma istemcileri gibi bazı uygulamalar, fare işaretçisinin kontrolünü ele geçirmekten yararlanır. İşaretçi yakalama, Android 8.0 (API düzeyi 26) ve sonraki sürümlerde kullanılabilen bir özelliktir. Bu özellik, tüm fare etkinliklerini uygulamanızdaki odaklanmış bir görünüme ileterek bu kontrolü sağlar.
İşaretçi yakalama isteğinde bulunma
Uygulamanızdaki bir görünüm, yalnızca kendisini içeren görünüm hiyerarşisi odaklandığında işaretçi yakalama isteğinde bulunabilir. Bu nedenle, görünümde belirli bir kullanıcı işlemi olduğunda (ör. onClick() etkinliği sırasında veya etkinliğinizin onWindowFocusChanged() etkinlik işleyicisinde) işaretçi yakalama isteğinde bulunun.
İşaretçi yakalama isteğinde bulunmak için görünümde requestPointerCapture() yöntemini çağırın. Aşağıdaki kod örneğinde, kullanıcı bir görünümü tıkladığında işaretçi yakalama isteğinde bulunma işlemi gösterilmektedir:
Kotlin
fun onClick(view: View) { view.requestPointerCapture() }
Java
@Override public void onClick(View view) { view.requestPointerCapture(); }
İşaretçiyi yakalama isteği başarılı olduğunda Android, onPointerCaptureChange(true) işlevini çağırır.
Sistem, fare etkinliklerini, yakalamayı isteyen görünümle aynı görünüm hiyerarşisinde olduğu sürece uygulamanızdaki odaklanılmış görünüme iletir. Diğer uygulamalar, yakalama serbest bırakılana kadar ACTION_OUTSIDE etkinlikleri de dahil olmak üzere fare etkinliklerini almayı durdurur. Android, fare dışındaki kaynaklardan gelen işaretçi etkinliklerini normal şekilde iletir ancak fare işaretçisi artık görünmez.
Yakalanan işaretçi etkinliklerini işleme
Bir görünüm işaretçi yakalamayı başarıyla elde ettiğinde Android, fare etkinliklerini sunar. Odaklanmış görünümünüz, aşağıdaki görevlerden birini gerçekleştirerek etkinlikleri işleyebilir:
- Özel bir görünüm kullanıyorsanız
onCapturedPointerEvent(MotionEvent)öğesini geçersiz kılın. - Aksi takdirde
OnCapturedPointerListenerkaydettirin.
Aşağıdaki kod örneğinde onCapturedPointerEvent(MotionEvent) nasıl uygulanacağı gösterilmektedir:
Kotlin
override fun onCapturedPointerEvent(motionEvent: MotionEvent): Boolean { // Get the coordinates required by your app. val verticalOffset: Float = motionEvent.y // Use the coordinates to update your view and return true if the event is // successfully processed. return true }
Java
@Override public boolean onCapturedPointerEvent(MotionEvent motionEvent) { // Get the coordinates required by your app. float verticalOffset = motionEvent.getY(); // Use the coordinates to update your view and return true if the event is // successfully processed. return true; }
Aşağıdaki kod örneğinde, OnCapturedPointerListener öğesinin nasıl kaydedileceği gösterilmektedir:
Kotlin
myView.setOnCapturedPointerListener { view, motionEvent -> // Get the coordinates required by your app. val horizontalOffset: Float = motionEvent.x // Use the coordinates to update your view and return true if the event is // successfully processed. true }
Java
myView.setOnCapturedPointerListener(new View.OnCapturedPointerListener() { @Override public boolean onCapturedPointer (View view, MotionEvent motionEvent) { // Get the coordinates required by your app. float horizontalOffset = motionEvent.getX(); // Use the coordinates to update your view and return true if the event is // successfully processed. return true; } });
İster özel bir görünüm kullanın ister bir dinleyici kaydedin, görünümünüz, X veya Y deltas gibi göreli hareketleri belirten işaretçi koordinatlarına sahip bir MotionEvent alır. Bu koordinatlar, trackball cihazı tarafından sağlanan koordinatlara benzer. Koordinatları getX() ve getY() kullanarak alabilirsiniz.
İşaretçi yakalama özelliğini bırakma
Uygulamanızdaki görünüm, aşağıdaki kod örneğinde gösterildiği gibi
releasePointerCapture() çağrısı yaparak işaretçi yakalamayı serbest bırakabilir:
Kotlin
override fun onClick(view: View) { view.releasePointerCapture() }
Java
@Override public void onClick(View view) { view.releasePointerCapture(); }
Sistem, genellikle yakalama isteğinde bulunan görünümü içeren görünüm hiyerarşisi odağını kaybettiği için releasePointerCapture() işlevini açıkça çağırmadan yakalamayı görünümden kaldırabilir.