Partager via


Suivi des doigts tactiles multiples dans Xamarin.iOS

Ce document montre comment suivre les événements tactiles à partir de plusieurs doigts

Il existe des moments où une application tactile doit suivre les doigts individuels lorsqu’ils se déplacent simultanément sur l’écran. Une application classique est un programme de peinture à doigts. Vous souhaitez que l’utilisateur puisse dessiner avec un seul doigt, mais également dessiner avec plusieurs doigts à la fois. Lorsque votre programme traite plusieurs événements tactiles, il doit faire la distinction entre ces doigts.

Lorsqu’un doigt touche d’abord l’écran, iOS crée un UITouch objet pour ce doigt. Cet objet reste le même que le doigt se déplace sur l’écran, puis s’élève à partir de l’écran, à quel moment l’objet est supprimé. Pour suivre les doigts, un programme doit éviter de stocker cet UITouch objet directement. Au lieu de cela, il peut utiliser la Handle propriété de type IntPtr pour identifier de manière unique ces UITouch objets.

Presque toujours, un programme qui suit les doigts individuels conserve un dictionnaire pour le suivi tactile. Pour un programme iOS, la clé de dictionnaire est la Handle valeur qui identifie un doigt particulier. La valeur du dictionnaire dépend de l’application. Dans l’exemple de programme, chaque trait de doigt (du toucher à la libération) est associé à un objet qui contient toutes les informations nécessaires pour afficher la ligne dessinée avec ce doigt. Le programme définit une petite FingerPaintPolyline classe à cet effet :

class FingerPaintPolyline
{
    public FingerPaintPolyline()
    {
        Path = new CGPath();
    }

    public CGColor Color { set; get; }

    public float StrokeWidth { set; get; }

    public CGPath Path { private set; get; }
}

Chaque polyligne a une couleur, une largeur de trait et un objet graphique CGPath iOS pour accumuler et afficher plusieurs points de la ligne au fur et à mesure qu’il est dessiné.

Tout le reste du code indiqué ci-dessous est contenu dans un UIView dérivé nommé FingerPaintCanvasView. Cette classe gère un dictionnaire d’objets de type FingerPaintPolyline pendant le temps qu’ils sont activement dessinés par un ou plusieurs doigts :

Dictionary<IntPtr, FingerPaintPolyline> inProgressPolylines = new Dictionary<IntPtr, FingerPaintPolyline>();

Ce dictionnaire permet à la vue d’obtenir rapidement les FingerPaintPolyline informations associées à chaque doigt en fonction de la Handle propriété de l’objet UITouch .

La FingerPaintCanvasView classe conserve également un List objet pour les polylignes qui ont été terminées :

List<FingerPaintPolyline> completedPolylines = new List<FingerPaintPolyline>();

Les objets dans ce List cas sont dans le même ordre qu’ils ont été dessinés.

FingerPaintCanvasView remplace cinq méthodes définies par View:

Les différentes Touches substitutions accumulent les points qui composent les polylignes.

Le remplacement [Draw] dessine les polylignes terminées, puis les polylignes en cours :

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);
        }
    }
}

Chacune des Touches substitutions signale potentiellement les actions de plusieurs doigts, indiquées par un ou plusieurs UITouch objets stockés dans l’argument touches à la méthode. Les TouchesBegan substitutions parcourent ces objets. Pour chaque UITouch objet, la méthode crée et initialise un nouvel FingerPaintPolyline objet, y compris le stockage de l’emplacement initial du doigt obtenu à partir de la LocationInView méthode. Cet FingerPaintPolyline objet est ajouté au dictionnaire à InProgressPolylines l’aide de la Handle propriété de l’objet UITouch en tant que clé de dictionnaire :

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();
}

La méthode se termine par l’appel SetNeedsDisplay pour générer un appel au remplacement et pour mettre à Draw jour l’écran.

Lorsque le doigt ou les doigts se déplacent sur l’écran, les View appels multiples à son TouchesMoved remplacement sont effectués. Cette substitution effectue une boucle similaire dans les UITouch objets stockés dans l’argument touches et ajoute l’emplacement actuel du doigt au chemin d’accès graphique :

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();
}

La touches collection contient uniquement les UITouch objets des doigts qui ont été déplacés depuis le dernier appel vers TouchesBegan ou TouchesMoved. Si vous avez besoin UITouch d’objets correspondant à tous les doigts actuellement en contact avec l’écran, ces informations sont disponibles via la AllTouches propriété de l’argument UIEvent à la méthode.

Le TouchesEnded remplacement a deux travaux. Il doit ajouter le dernier point au chemin d’accès graphique et transférer l’objet FingerPaintPolyline du inProgressPolylines dictionnaire vers la completedPolylines liste :

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();
}

Le TouchesCancelled remplacement est géré en abandonnant simplement l’objet FingerPaintPolyline dans le dictionnaire :

public override void TouchesCancelled(NSSet touches, UIEvent evt)
{
    base.TouchesCancelled(touches, evt);

    foreach (UITouch touch in touches.Cast<UITouch>())
    {
        inProgressPolylines.Remove(touch.Handle);
    }
    SetNeedsDisplay();
}

Au total, ce traitement permet au programme d’échantillon de suivre les doigts individuels et de dessiner les résultats à l’écran :

Suivi des doigts individuels et dessin des résultats sur l’écran

Vous avez maintenant vu comment vous pouvez suivre des doigts individuels sur l’écran et faire la distinction entre eux.