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 :
Vous avez maintenant vu comment vous pouvez suivre des doigts individuels sur l’écran et faire la distinction entre eux.