Friday, December 25 2009
The Surface SDK comes in two flavors; WPF and XNA. All of the input events on the WPF Surface SDK are implemented as Attached Events, which are essentially just a clever use of standard Routed Events in WPF. I won’t delve into the all details here about what Attached Events are, but they were a primary focus for an implementation of ContactMultiTap on the Surface.
For those of you not familiar with the Surface, it’s convenient to think of it as a gigantic iPhone (although it’s been around in secret long before the iPhone) that can also recognize object tags (like 2D barcodes). This is because instead of using a capacitive multi-touch approach like the iPhone it implements a multi-camera computer vision system and interprets inputs from that. In this post, I discuss my implementation as well as the benefits of time-based multi-tap input on this “big a** table.”
So what are the benefits to adding multi-tap modality to a device with a very large spatial modality? My hypothesis is that in a table computing environment, where a user is presented with a system that lacks a mouse, adding multi-tap transfers well established learned behavior for multi-clicking. When using the somewhat naive definition of “intuitive equals familiar” one could claim that therefore multi (or at least double) tap would be intuitive for users as they transition into a table computing environment. There are also several places in existing multi-touch devices where double tap is used frequently (mapping applications on the iPhone and Android platforms for example). This evidence is far from compelling and I look forward to testing this hypothesis during some application trials next semester at Columbia.
So for those of you who just want to get down to the nitty gritty implementation, here we go. For the casual user integrating this attached behavior is very simple. Just include the appropriate namespace
<s:SurfaceWindow x:Class="MultiTapEventsSample.MainWindow"
xmlns:l="clr-namespace:MultiTapEventsSample" (...)
And then simply add an event handler to the appropriate element:
<Grid
behaviors:ContactMultiTap.MultiTapInterval="00:00:00.5"
behaviors:ContactMultiTap.ContactMultiTapGesture="OnContactMultiTap">
It’s important to note that you have to set the MultiTapInterval property or the attached event will not get raised. This interval is the maximum amount of time allowed between tap gestures for them to still be considered part of a multi-tap gesture. A simple event handler for this would be:
private void OnContactMultiTap(object sender, ContactMultiTapEventArgs args)
{
if (args.MultiTapCount == 2)
{
// Your custom DOUBLE TAP code here
}
}
Under the covers, the behavior is tracking weak references to UIElements and then internally storing an individual timer for each potential multi-tap gesture and resetting the tap count when the timer fires. The behavior also tracks spatial location of taps. For example, if you quickly tap twice but on opposite sides of the Surface it will not register as a multi-tap. Given the massively collaborative nature of the Surface, spatial locality to multi-tap gestures was important to preserving users intent.
As always this code is available on GitHub. I’m interested to see if this gets used out in the wild, so if you have any questions, feel free to contact me.