FrameReported & ContactButton [Custom Control]
Aucun commentaire
Si vous avez déjà développé pour Windows Phone 7, vous avez déjà du remarquer certaines interactions problématiques. C'est notamment le cas lorsque vous utilisez les contrôles de base. Par exemple, lorsque vous cliquez sur un bouton par inadvertance (très souvent le cas pour les enfants), cela bloque toute autre tentative d'écoute sur un autre contrôle. Pour le vérifier posez deux boutons dans une grille windows phone 7 et compilez le projet sur le device. Lorsque vous cliquez sur le premier bouton, la diffusion de tout autre événement souris ou contact (tels que MouseLeftButtonDown par exemple) est impossible. Vous vous trouvez dans un cas classique d'interaction Multi-Touch sans l'avoir prévu. Afin de réaliser des applications réellement multitouch qui prennent ce genre de problématiques en compte, il existe différentes solutions plus ou moins efficaces .
Utiliser des événements plus adaptés : ManipulationStarted, ManipulationDelta et ManipulationCompleted. Ceux-ci sont directement implémentés dans le framework au niveau de la classe UIElement. Ces événements fournissent plus de détail concernant l'interaction utilisateur en cours. C'est cette solution qui est privilégiée dans 90% des cas. Toutefois cela ne répond pas à notre problématique principale.
Implémenter l'API de Gesture proposée par le Toolkit Windows Phone 7. Cette API facilite la vie lorsqu'il est nécessaire de connaitre l'écartement entre deux contacts, la rotation du segment entre des contacts et tout autre type d'opérations de ce genre. Le problème est qu'encore une fois, cela n'est pas une bonne solution car les événements proposés ne concernent qu'une seule surface (contrôle) à la fois. De plus l'implémentation de cette API n'est pas très pratique à mettre en oeuvre et ajoute une surcouche à l'API native et engendre de faibles performances (voir figure ci-dessous).
La seule bonne solution, et la plus exhaustive en matière de possibilités, consiste à Utiliser la classe static Touch. Celle-ci représente le plus bas niveau de traitement MultiTouch. Elle vous permet d'écouter un unique évènement nommé FrameReported. L'objet événementiel récupéré par l'écouteur possède plusieurs informations qui permettent de développer votre propre classe Wrapper MultiTouch ou encore des contrôles particuliers. Ces informations sont contenus dans l'objet événementiel de type TouchFrameEventArgs. L'objet événementiel permet de récupérer le premier contact, de supprimer la diffusion d'événements souris via la méthode SuspendMousePromotionUntilTouchUp. TouchFrameEventArgs donne également accès à la liste des contacts en cours sur une surface via la méthode GetTouchPoints. Cette liste est relative au contexte conteneur passé lors de l'appel de la méthode. De la même manière que GetPosition() de la classe MouseButtonEventArgs, passer null renvoie la liste relative au VisualRoot, donc à l'application elle-même. Chaque contact sur la surface est de type TouchPoint. A ce stade, l'API commence à être réellement utile puisqu'il est possible, pour chaque contact, de récupérer des informations utiles comme sa dimension , son action(relaché, déplacé, appuyé) et sa position relative au conteneur. Voici un exemple :
public MainPage() { InitializeComponent(); Touch.FrameReported += new TouchFrameEventHandler(Touch_FrameReported); } void Touch_FrameReported(object sender, TouchFrameEventArgs e) { var tp = e.GetPrimaryTouchPoint(null); switch(tp.Action) { case TouchAction.Down: break; case TouchAction.Move: break; case TouchAction.Up: break; default: break; } }
Sur un projet en cours, j'ai du développé un contrôle ContactButton permettant de résoudre cette problématique. L'objectif d'un point de vue utilisateur était d'activer certains menus lorsque deux boutons à la fois étaient cliqués. Ce contrôle est basé sur l'API native multiTouch de Silverlight et sur les classes d'AutomationPeer. L'idée est de diffuser un événement lorsque plusieurs boutons d'un même groupe sont cliqués en même temps. Il est possible d'écouter un événement static de la classe ContactButton afin de récupérer le groupe de bouton cliqué. Au moins deux boutons d'un même groupe doivent être appuyés en même temps pour que la classe diffuse l'événement. Il est également possible d'écouter un groupe spécifique. Voici comme utiliser ces événements :
public TestTwinBehavior() { InitializeComponent(); tcb1.ContactSelectionChanged += new EventHandler(tcb1_ContactSelectionChanged); ContactButton.ContactGroupChanged += new EventHandler(ContactButton_ContactGroupChanged); } void ContactButton_ContactGroupChanged(object sender, ContactButtonGroupEventArgs e) { Debug.WriteLine(e.ContactButtonGroupName); } void tcb1_ContactSelectionChanged(object sender, Tweened.WP7.Controls.ContactButtonGroupEventArgs e) { foreach (ButtonBase item in e.ContactedButtons) { Debug.WriteLine(item.Name); } }
Je mets à disposition un projet et la dll qui l'accompagne. En outre, le contrôle LayoutGridSelector est fourni avec des améliorations concernant le support des thèmes visuels Windows Phone 7.











