Multi-Touch Finger Tracking in Xamarin.iOS
In diesem Dokument wird veranschaulicht, wie Fingereingabeereignisse von mehreren Fingern nachverfolgt werden.
Es gibt Situationen, in denen eine Multitouchanwendung einzelne Finger nachverfolgen muss, während sie gleichzeitig auf dem Bildschirm bewegt werden. Eine typische Anwendung ist ein Fingerfarbenprogramm. Sie möchten, dass der Benutzer mit einem Finger zeichnen kann, aber auch mit mehreren Fingern gleichzeitig zeichnen kann. Da Ihr Programm mehrere Touchereignisse verarbeitet, muss es zwischen diesen Fingern unterscheiden.
Wenn ein Finger zuerst den Bildschirm berührt, erstellt iOS ein UITouch
Objekt für diesen Finger. Dieses Objekt wird erneut Standard mit dem Finger auf dem Bildschirm bewegt und dann vom Bildschirm entfernt, an dem das Objekt verworfen wird. Um Finger im Auge zu behalten, sollte ein Programm das direkte Speichern dieses UITouch
Objekts vermeiden. Stattdessen kann die Eigenschaft des Typs IntPtr
verwendet Handle
werden, um diese UITouch
Objekte eindeutig zu identifizieren.
Fast immer, ein Programm, das einzelne Finger verfolgt, Standard ein Wörterbuch zur Touchverfolgung enthält. Bei einem iOS-Programm ist der Wörterbuchschlüssel der Wert, der Handle
einen bestimmten Finger identifiziert. Der Wörterbuchwert hängt von der Anwendung ab. Im Beispielprogramm wird jeder Fingerstrich (von Der Fingereingabe bis zur Freigabe) einem Objekt zugeordnet, das alle erforderlichen Informationen enthält, um die mit dem Finger gezeichnete Linie zu rendern. Das Programm definiert für diesen Zweck eine kleine FingerPaintPolyline
Klasse:
class FingerPaintPolyline
{
public FingerPaintPolyline()
{
Path = new CGPath();
}
public CGColor Color { set; get; }
public float StrokeWidth { set; get; }
public CGPath Path { private set; get; }
}
Jede Polylinie verfügt über eine Farbe, eine Strichbreite und ein iOS-Grafikobjekt CGPath
, um mehrere Punkte der Linie zu sammeln und zu rendern, während sie gezeichnet wird.
Der rest des unten gezeigten Codes ist in einem UIView
abgeleiteten Namen FingerPaintCanvasView
enthalten. Diese Klasse Standard enthält ein Wörterbuch von Objekten vom Typ während FingerPaintPolyline
der Zeit, in der sie aktiv von einem oder mehreren Fingern gezeichnet werden:
Dictionary<IntPtr, FingerPaintPolyline> inProgressPolylines = new Dictionary<IntPtr, FingerPaintPolyline>();
Mit diesem Wörterbuch kann die Ansicht schnell die informationen abrufen, die FingerPaintPolyline
jedem Finger zugeordnet sind, basierend auf der Handle
Eigenschaft des UITouch
Objekts.
Die FingerPaintCanvasView
Klasse Standard enthält auch ein List
Objekt für die polylines, die abgeschlossen wurden:
List<FingerPaintPolyline> completedPolylines = new List<FingerPaintPolyline>();
Die Objekte in dieser List
Reihenfolge befinden sich in derselben Reihenfolge, in der sie gezeichnet wurden.
FingerPaintCanvasView
überschreibt fünf methoden, die durch View
:
Die verschiedenen Touches
Außerkraftsetzungen sammeln die Punkte, aus denen die Polylinien bestehen.
Die [Draw
] Überschreibung zeichnet die abgeschlossenen Polylinien und dann die laufenden Polylinien:
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);
}
}
}
Jede der Touches
Außerkraftsetzungen meldet potenziell die Aktionen mehrerer Finger, die durch ein oder UITouch
mehrere Objekte angegeben werden, die touches
im Argument gespeichert sind, an die Methode. Die TouchesBegan
Außerkraftsetzungen durchlaufen diese Objekte. Für jedes UITouch
Objekt erstellt und initialisiert die Methode ein neues FingerPaintPolyline
Objekt, einschließlich des Speicherns der ursprünglichen Position des von der LocationInView
Methode abgerufenen Fingers. Dieses FingerPaintPolyline
Objekt wird dem InProgressPolylines
Wörterbuch mithilfe der Handle
Eigenschaft des UITouch
Objekts als Wörterbuchschlüssel hinzugefügt:
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();
}
Die Methode wird beendet, indem sie aufruft SetNeedsDisplay
, um einen Aufruf der Draw
Außerkraftsetzung zu generieren und den Bildschirm zu aktualisieren.
Wenn sich der Finger oder die Finger auf dem Bildschirm bewegen, ruft die View
Überschreibung mehrere Aufrufe ab TouchesMoved
. Diese Außerkraftsetzung durchläuft auf ähnliche Weise die UITouch
im touches
Argument gespeicherten Objekte und fügt die aktuelle Position des Fingers dem Grafikpfad hinzu:
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();
}
Die touches
Auflistung enthält nur die UITouch
Objekte für die Finger, die seit dem letzten Aufruf TouchesBegan
verschoben wurden.TouchesMoved
Wenn Sie jemals Objekte benötigenUITouch
, die allen Fingern entsprechen, die aktuell mit dem Bildschirm in Kontakt stehen, sind diese Informationen über die AllTouches
Eigenschaft des UIEvent
Arguments für die Methode verfügbar.
Die TouchesEnded
Außerkraftsetzung verfügt über zwei Aufträge. Sie muss den letzten Punkt zum Grafikpfad hinzufügen und das FingerPaintPolyline
Objekt aus dem inProgressPolylines
Wörterbuch in die completedPolylines
Liste übertragen:
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();
}
Die TouchesCancelled
Außerkraftsetzung wird behandelt, indem sie einfach das FingerPaintPolyline
Objekt im Wörterbuch aufgibt:
public override void TouchesCancelled(NSSet touches, UIEvent evt)
{
base.TouchesCancelled(touches, evt);
foreach (UITouch touch in touches.Cast<UITouch>())
{
inProgressPolylines.Remove(touch.Handle);
}
SetNeedsDisplay();
}
Insgesamt ermöglicht diese Verarbeitung dem Beispielprogramm, einzelne Finger nachzuverfolgen und die Ergebnisse auf dem Bildschirm zu zeichnen:
Sie haben nun gesehen, wie Sie einzelne Finger auf dem Bildschirm nachverfolgen und zwischen ihnen unterscheiden können.