Śledzenie palcem wielodotykowym na platformie Xamarin.iOS
W tym dokumencie pokazano, jak śledzić zdarzenia dotykowe z wielu palców
Czasami aplikacja wielodotykowa musi śledzić poszczególne palce, gdy poruszają się jednocześnie na ekranie. Jedną z typowych aplikacji jest program malowania palcami. Chcesz, aby użytkownik mógł rysować za pomocą pojedynczego palca, ale także rysować z wieloma palcami jednocześnie. Ponieważ program przetwarza wiele zdarzeń dotykowych, musi odróżnić te palce.
Gdy palec po raz pierwszy dotyka ekranu, system iOS tworzy UITouch
obiekt dla tego palca. Ten obiekt pozostaje taki sam, jak palec porusza się na ekranie, a następnie podnosi się z ekranu, w którym momencie obiekt jest usuwany. Aby śledzić palce, program powinien unikać bezpośredniego przechowywania tego UITouch
obiektu. Zamiast tego może użyć Handle
właściwości typu IntPtr
, aby jednoznacznie zidentyfikować te UITouch
obiekty.
Prawie zawsze, program, który śledzi poszczególne palce utrzymuje słownik do śledzenia dotyku. W przypadku programu dla systemu iOS klucz słownika Handle
jest wartością identyfikującą konkretny palec. Wartość słownika zależy od aplikacji. W przykładowym programie każdy pociągnięcie palca (od dotyku do zwolnienia) jest skojarzone z obiektem zawierającym wszystkie informacje niezbędne do renderowania linii rysowanej palcem. Program definiuje małą FingerPaintPolyline
klasę w tym celu:
class FingerPaintPolyline
{
public FingerPaintPolyline()
{
Path = new CGPath();
}
public CGColor Color { set; get; }
public float StrokeWidth { set; get; }
public CGPath Path { private set; get; }
}
Każda wielowierszowa ma kolor, szerokość pociągnięcia i obiekt graficzny CGPath
systemu iOS do gromadzenia i renderowania wielu punktów linii podczas rysowania.
Cała reszta kodu pokazanego poniżej znajduje się w pochodnej UIView
nazwie FingerPaintCanvasView
. Ta klasa utrzymuje słownik obiektów typu FingerPaintPolyline
w czasie, gdy są aktywnie rysowane przez co najmniej jeden palec:
Dictionary<IntPtr, FingerPaintPolyline> inProgressPolylines = new Dictionary<IntPtr, FingerPaintPolyline>();
Ten słownik umożliwia szybkie uzyskanie FingerPaintPolyline
informacji skojarzonych z każdym palcem na Handle
podstawie właściwości UITouch
obiektu.
Klasa FingerPaintCanvasView
obsługuje List
również obiekt dla linii polilinii, które zostały ukończone:
List<FingerPaintPolyline> completedPolylines = new List<FingerPaintPolyline>();
Obiekty w tej List
kolejności znajdują się w tej samej kolejności, w której zostały narysowane.
FingerPaintCanvasView
zastępuje pięć metod zdefiniowanych przez View
metodę :
Różne Touches
przesłonięcia gromadzą punkty, które składają się na linie wielokątne.
Przesłonięcia [Draw
] rysują ukończone linie wieloliniowe, a następnie linie wieloliniowe w toku:
public override void Draw(CGRect rect)
{
base.Draw(rect);
using (CGContext context = UIGraphics.GetCurrentContext())
{
// Stroke settings
context.SetLineCap(CGLineCap.Round);
context.SetLineJoin(CGLineJoin.Round);
// Draw the completed polylines
foreach (FingerPaintPolyline polyline in completedPolylines)
{
context.SetStrokeColor(polyline.Color);
context.SetLineWidth(polyline.StrokeWidth);
context.AddPath(polyline.Path);
context.DrawPath(CGPathDrawingMode.Stroke);
}
// Draw the in-progress polylines
foreach (FingerPaintPolyline polyline in inProgressPolylines.Values)
{
context.SetStrokeColor(polyline.Color);
context.SetLineWidth(polyline.StrokeWidth);
context.AddPath(polyline.Path);
context.DrawPath(CGPathDrawingMode.Stroke);
}
}
}
Każde z Touches
przesłonięć potencjalnie zgłasza akcje wielu palców, wskazywane przez co najmniej jeden UITouch
obiekt przechowywany w argumencie touches
metody . Przesłonięcia TouchesBegan
przechodzą przez te obiekty. Dla każdego UITouch
obiektu metoda tworzy i inicjuje nowy FingerPaintPolyline
obiekt, w tym przechowywanie początkowej lokalizacji palca uzyskanego LocationInView
z metody . Ten FingerPaintPolyline
obiekt jest dodawany do InProgressPolylines
słownika przy użyciu Handle
właściwości UITouch
obiektu jako klucza słownika:
public override void TouchesBegan(NSSet touches, UIEvent evt)
{
base.TouchesBegan(touches, evt);
foreach (UITouch touch in touches.Cast<UITouch>())
{
// Create a FingerPaintPolyline, set the initial point, and store it
FingerPaintPolyline polyline = new FingerPaintPolyline
{
Color = StrokeColor,
StrokeWidth = StrokeWidth,
};
polyline.Path.MoveToPoint(touch.LocationInView(this));
inProgressPolylines.Add(touch.Handle, polyline);
}
SetNeedsDisplay();
}
Metoda kończy się wywołaniem SetNeedsDisplay
wywołania przesłonięcia Draw
i zaktualizowania ekranu.
Gdy palec lub palce poruszają się na ekranie, View
otrzymuje wiele wywołań do jego TouchesMoved
przesłonięcia. To przesłonięcie podobnie przechodzi przez UITouch
obiekty przechowywane w argumencie touches
i dodaje bieżącą lokalizację palca do ścieżki grafiki:
public override void TouchesMoved(NSSet touches, UIEvent evt)
{
base.TouchesMoved(touches, evt);
foreach (UITouch touch in touches.Cast<UITouch>())
{
// Add point to path
inProgressPolylines[touch.Handle].Path.AddLineToPoint(touch.LocationInView(this));
}
SetNeedsDisplay();
}
Kolekcja touches
zawiera tylko te UITouch
obiekty dla palców, które zostały przeniesione od ostatniego wywołania do TouchesBegan
lub TouchesMoved
. Jeśli kiedykolwiek potrzebujesz UITouch
obiektów odpowiadających wszystkim palcam, które są obecnie w kontakcie z ekranem, informacje te są dostępne za pośrednictwem AllTouches
właściwości argumentu UIEvent
do metody .
Przesłonięcia TouchesEnded
mają dwa zadania. Musi dodać ostatni punkt do ścieżki grafiki i przenieść FingerPaintPolyline
obiekt ze inProgressPolylines
słownika completedPolylines
do listy:
public override void TouchesEnded(NSSet touches, UIEvent evt)
{
base.TouchesEnded(touches, evt);
foreach (UITouch touch in touches.Cast<UITouch>())
{
// Get polyline from dictionary and remove it from dictionary
FingerPaintPolyline polyline = inProgressPolylines[touch.Handle];
inProgressPolylines.Remove(touch.Handle);
// Add final point to path and save with completed polylines
polyline.Path.AddLineToPoint(touch.LocationInView(this));
completedPolylines.Add(polyline);
}
SetNeedsDisplay();
}
Przesłonięcia TouchesCancelled
są obsługiwane przez po prostu porzucenie FingerPaintPolyline
obiektu w słowniku:
public override void TouchesCancelled(NSSet touches, UIEvent evt)
{
base.TouchesCancelled(touches, evt);
foreach (UITouch touch in touches.Cast<UITouch>())
{
inProgressPolylines.Remove(touch.Handle);
}
SetNeedsDisplay();
}
W sumie to przetwarzanie umożliwia przykładowemu programowi śledzenie poszczególnych palców i rysowanie wyników na ekranie:
Wiesz już, jak można śledzić poszczególne palce na ekranie i rozróżniać je.