Çok Dokunmalı Parmak İzleme
Bu konu başlığında, dokunma olaylarını birden çok parmaktan izleme adımları gösterilmektedir
Çok dokunmalı bir uygulamanın ekranda aynı anda hareket ederken tek tek parmaklarını izlemesi gereken zamanlar vardır. Tipik bir uygulama parmak boyama programıdır. Kullanıcının tek parmakla çizim yapabilmesini ancak aynı anda birden çok parmakla çizim yapabilmesini istiyorsunuz. Programınız birden çok dokunma olayını işlerken, her bir parmakla ilgili olan olayları ayırt etmesi gerekir. Android bu amaçla bir kimlik kodu sağlar, ancak bu kodu almak ve işlemek biraz karmaşık olabilir.
Belirli bir parmakla ilişkili tüm olaylar için kimlik kodu aynı kalır. Kimlik kodu, bir parmak ekrana ilk kez dokunduğunda atanır ve parmak ekrandan kaldırıldıktan sonra geçersiz hale gelir. Bu kimlik kodları genellikle çok küçük tamsayılardır ve Android bunları daha sonraki dokunma olayları için yeniden kullanıyor.
Neredeyse her zaman, tek tek parmaklarını izleyen bir program, dokunma izleme için bir sözlük tutar. Sözlük anahtarı, belirli bir parmağı tanımlayan kimlik kodudur. Sözlük değeri uygulamaya bağlıdır. FingerPaint örneğinde, her parmak vuruşu (dokunmadan yayına) çizginin o parmakla çizilmesi için gerekli tüm bilgileri içeren bir nesneyle ilişkilendirilir. Program bu amaçla küçük FingerPaintPolyline
bir sınıf tanımlar:
class FingerPaintPolyline
{
public FingerPaintPolyline()
{
Path = new Path();
}
public Color Color { set; get; }
public float StrokeWidth { set; get; }
public Path Path { private set; get; }
}
Her çok çizgi, çizilirken çizginin birden çok noktasında birikip işlemek için bir renk, vuruş genişliği ve bir Android grafik Path
nesnesine sahiptir.
Aşağıda gösterilen kodun geri kalanı adlı FingerPaintCanvasView
bir View
türev içinde yer alır. Bu sınıf, bir veya daha fazla parmakla etkin olarak çizildikleri süre boyunca türündeki FingerPaintPolyline
nesnelerin bir sözlüğünü tutar:
Dictionary<int, FingerPaintPolyline> inProgressPolylines = new Dictionary<int, FingerPaintPolyline>();
Bu sözlük, görünümün belirli bir parmakla ilişkili bilgileri hızla almasını FingerPaintPolyline
sağlar.
sınıfı, FingerPaintCanvasView
tamamlanmış olan çok çizgili değerler için de bir List
nesne tutar:
List<FingerPaintPolyline> completedPolylines = new List<FingerPaintPolyline>();
Bunun List
içindeki nesneler, çizildiği sıradadır.
FingerPaintCanvasView
tarafından View
tanımlanan iki yöntemi geçersiz kılar: OnDraw
ve OnTouchEvent
.
OnDraw
Geçersiz kılmada, görünüm tamamlanmış çok çizgileri çizer ve sonra devam eden çok çizgilileri çizer.
yöntemi geçersiz OnTouchEvent
kılma özelliğinden ActionIndex
bir pointerIndex
değer alarak başlar. Bu ActionIndex
değer birden çok parmağı birbirinden ayırt eder, ancak birden çok olay arasında tutarlı değildir. Bu nedenle, yönteminden GetPointerId
işaretçi id
değerini almak için öğesini kullanırsınızpointerIndex
. Bu kimlik birden çok olay arasında tutarlıdır :
public override bool OnTouchEvent(MotionEvent args)
{
// Get the pointer index
int pointerIndex = args.ActionIndex;
// Get the id to identify a finger over the course of its progress
int id = args.GetPointerId(pointerIndex);
// Use ActionMasked here rather than Action to reduce the number of possibilities
switch (args.ActionMasked)
{
// ...
}
// Invalidate to update the view
Invalidate();
// Request continued touch input
return true;
}
Geçersiz kılmanın özelliği yerine deyiminde switch
özelliğini kullandığına ActionMasked
Action
dikkat edin. Bunun nedeni şu şekildedir:
Çoklu dokunmayla ilgilenirken, özelliğin Action
ilk parmağın MotionEventsAction.Down
ekrana dokunması için bir değeri vardır ve ikinci ve üçüncü parmaklar da ekrana dokunduğundan ve Pointer3Down
değerlerine Pointer2Down
sahiptir. Dördüncü ve beşinci parmaklar iletişim kurarken, özelliğin Action
numaralandırmanın MotionEventsAction
üyelerine bile karşılık olmayan sayısal değerleri vardır! Anlamlarını yorumlamak için değerlerdeki bit bayraklarının değerlerini incelemeniz gerekir.
Benzer şekilde, parmaklar ekrana temas ettikçe, Action
özellik ikinci ve Pointer3Up
üçüncü parmaklar Pointer2Up
için ve ilk parmak için değerlerine Up
sahiptir.
ActionMasked
özelliği, birden çok parmak arasında ayrım yapmak için özelliğiyle ActionIndex
birlikte kullanılması amaçlandığı için daha az sayıda değer alır. Parmaklar ekrana dokunduğunda, özellik yalnızca ilk parmak ve PointerDown
sonraki parmaklar için eşit MotionEventActions.Down
olabilir. Parmaklar ekrandan ayrılırken, ActionMasked
sonraki parmaklar Pointer1Up
ve Up
ilk parmak için değerleri vardır.
kullanırken ActionMasked
, ActionIndex
ekrana dokunmak ve ekrandan çıkmak için sonraki parmaklar arasında ayrım yapılır, ancak nesnedeki MotionEvent
diğer yöntemlerin bağımsız değişkeni dışında genellikle bu değeri kullanmanız gerekmez. Çoklu dokunma için, bu yöntemlerden en önemlilerinden biri yukarıdaki kodda çağrılır GetPointerId
. Bu yöntem, belirli olayları parmakla ilişkilendirmek için sözlük anahtarı için kullanabileceğiniz bir değer döndürür.
OnTouchEvent
Örnekteki geçersiz kılma, yeni FingerPaintPolyline
bir nesne oluşturup sözlüğe ekleyerek ve PointerDown
olaylarını aynı şekilde işlerMotionEventActions.Down
:
public override bool OnTouchEvent(MotionEvent args)
{
// Get the pointer index
int pointerIndex = args.ActionIndex;
// Get the id to identify a finger over the course of its progress
int id = args.GetPointerId(pointerIndex);
// Use ActionMasked here rather than Action to reduce the number of possibilities
switch (args.ActionMasked)
{
case MotionEventActions.Down:
case MotionEventActions.PointerDown:
// Create a Polyline, set the initial point, and store it
FingerPaintPolyline polyline = new FingerPaintPolyline
{
Color = StrokeColor,
StrokeWidth = StrokeWidth
};
polyline.Path.MoveTo(args.GetX(pointerIndex),
args.GetY(pointerIndex));
inProgressPolylines.Add(id, polyline);
break;
// ...
}
// ...
}
görünümünün pointerIndex
içinde parmağın konumunu elde etmek için de kullanıldığına dikkat edin. Tüm dokunma bilgileri değerle pointerIndex
ilişkilendirilir. , id
birden çok iletideki parmaklarını benzersiz olarak tanımlar, bu nedenle sözlük girdisini oluşturmak için kullanılır.
Benzer şekilde, OnTouchEvent
geçersiz kılma, tamamlanmış çok çizgiliyiMotionEventActions.Up
, geçersiz kılma sırasında çizilebilmeleri için koleksiyona completedPolylines
aktararak ve Pointer1Up
öğesini OnDraw
de aynı şekilde işler. Kod ayrıca girdiyi id
sözlükten kaldırır:
public override bool OnTouchEvent(MotionEvent args)
{
// ...
switch (args.ActionMasked)
{
// ...
case MotionEventActions.Up:
case MotionEventActions.Pointer1Up:
inProgressPolylines[id].Path.LineTo(args.GetX(pointerIndex),
args.GetY(pointerIndex));
// Transfer the in-progress polyline to a completed polyline
completedPolylines.Add(inProgressPolylines[id]);
inProgressPolylines.Remove(id);
break;
case MotionEventActions.Cancel:
inProgressPolylines.Remove(id);
break;
}
// ...
}
Şimdi de işin zor kısmı.
Aşağı ve yukarı olayları arasında genellikle birçok MotionEventActions.Move
olay vardır. Bunlar tek bir çağrısında OnTouchEvent
paketlenir ve ve Up
olaylarından Down
farklı şekilde işlenmelidir. pointerIndex
Özelliğinden ActionIndex
daha önce alınan değer yoksayılmalıdır. Bunun yerine, yöntemin 0 ile özelliği arasında döngü yaparak birden çok pointerIndex
değer alması ve PointerCount
ardından bu pointerIndex
değerlerin her biri için bir id
alması gerekir:
public override bool OnTouchEvent(MotionEvent args)
{
// ...
switch (args.ActionMasked)
{
// ...
case MotionEventActions.Move:
// Multiple Move events are bundled, so handle them differently
for (pointerIndex = 0; pointerIndex < args.PointerCount; pointerIndex++)
{
id = args.GetPointerId(pointerIndex);
inProgressPolylines[id].Path.LineTo(args.GetX(pointerIndex),
args.GetY(pointerIndex));
}
break;
// ...
}
// ...
}
Bu işlem türü, örneğin tek tek parmaklarını izlemesine ve sonuçları ekranda çizmesine olanak tanır:
Artık ekranda tek tek parmaklarını nasıl izleyebilebileceğinizi ve aralarında nasıl ayrım yapabileceğinizi gördünüz.