Freigeben über


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 FingerPaintCanvasViewenthalten. 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:

Verfolgen einzelner Finger und Zeichnen der Ergebnisse auf dem Bildschirm

Sie haben nun gesehen, wie Sie einzelne Finger auf dem Bildschirm nachverfolgen und zwischen ihnen unterscheiden können.