Multitouch

One of the navigation methods that are unique to mobile devices is the ability to interact with an application via gestures on the device’s touch screen. Multitouch is defined as the ability to simultaneously register three or more touch points on the device. Within Adobe AIR 2.7, there are two event classes used to listen for multitouch events.

GestureEvent

The GestureEvent class is used to listen for a two-finger tap on the device. The event used to listen for this action is the GESTURE_TWO_FINGER_TAP. This event will return the registration points for the x and y coordinates when a two-finger tap occurs, for both stage positioning as well as object positioning.

Let’s review the code below. Within applicationComplete of the application, an event handler function is called which first sets the Multitouch.inputMode to MultitouchInputMode.GESTURE. Next, it checks to see if the device supports multitouch by reading the static property of the Multitouch class. If this property returns as true, an event listener is added to the stage to listen for GestureEvent.GESTURE_TWO_FINGER_TAP events. When this event occurs, the onGestureTwoFingerTap method is called. The onGestureTwoFingerTap method will capture the localX and localY coordinates, as well as the stageX and stageY coordinates. If you two-finger tap on an empty portion of the stage, these values will be identical. If you two-finger tap on an object on the stage, the localX and localY coordinates will be the values within the object, and the stageX and stageY will be relative to the stage itself. See Figure 4-11 for an example of a two-finger tap on the stage and Figure 4-12 for a two-finger tap on the Adobe AIR image:

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
                  xmlns:s="library://ns.adobe.com/flex/spark"
                  applicationComplete="application1_applicationCompleteHandler(event)">
    <fx:Script>
          <![CDATA[
               import mx.events.FlexEvent;

               protected function application1_applicationCompleteHandler(event:FlexEvent):void {
                     Multitouch.inputMode = MultitouchInputMode.GESTURE;
                     if(Multitouch.supportsGestureEvents){
                          stage.addEventListener(GestureEvent.GESTURE_TWO_FINGER_TAP, 
                              onGestureTwoFingerTap);
                     } else {
                          status.text="gestures not supported";
                     }

               }
               private function onGestureTwoFingerTap(event:GestureEvent):void{
                     info.text = "event = " + event.type + "\n" +
                          "localX = " + event.localX + "\n" +
                          "localY = " + event.localY + "\n" +
                          "stageX = " + event.stageX + "\n" +
                          "stageY = " + event.stageY;
               }

          ]]>
    </fx:Script>
    <fx:Declarations>
          <!-- Place non-visual elements (e.g., services, value objects) here -->
    </fx:Declarations>
    <s:Label id="status" text="Do a 2 finger tap both on and off the object"
                top="10" width="100%" textAlign="center"/>
    <s:TextArea id="info" width="100%" top="40" editable="false"/>
    <s:Image width="384" height="384" bottom="10" horizontalCenter="0"
                source="@Embed('adobeair.jpg')"/>
</s:Application>
Two-finger tap on stage (values are the same)

Figure 4-11. Two-finger tap on stage (values are the same)

Two-finger tap on image object (values are different)

Figure 4-12. Two-finger tap on image object (values are different)

TransformGesture

There are multiple transform gesture events available within AIR 2.7. Each will capture a unique multitouch event. The example below demonstrates how to listen for GESTURE_PAN, GESTURE_ROTATE, GESTURE_SWIPE, and GESTURE_ZOOM events.

Let’s review the code below. Within applicationComplete of the application, an event handler function is called which first sets the Multitouch.inputMode to MultitouchInputMode.GESTURE. Next, it checks to see if the device supports multitouch by reading the static property of the Multitouch class. If this property returns as true, event listeners are added to the stage to listen for the TransformGestureEvent.GESTURE_PAN, TransformGestureEvent.GESTURE_ROTATE, TransformGestureEvent.GESTURE_SWIPE, and TransformGestureEvent.GESTURE_ZOOM events.

When a user grabs the object with two fingers and drags the object, the TransformGestureEvent.GESTURE_PAN event is triggered and the onGesturePan method is called. Within the onGesturePan method, the offsetX and offsetY values of this event are written to the text property of the TextArea component. Adding the event’s offsetX and offsetY values sets the object’s x and y, to move the object across the stage. The results can be seen in Figure 4-13.

When a user grabs the object with two fingers and rotates the object, the TransformGestureEvent.GESTURE_ROTATE event is triggered and the onGestureRotate method is called. Within the onGestureRotate method, the rotation value of this event is written to the text property of the TextArea component. To allow the object to rotate around its center, the object’s transformAround method is called and the event’s rotation value is added to the object’s rotationZ value. The results can be seen in Figure 4-14.

When a user swipes across the object with one finger in any direction, the TransformGestureEvent.GESTURE_SWIPE event is triggered and the onGestureSwipe method is called. Within the onGestureSwipe method, the value of the event’s offsetX and offsetY are evaluated to determine which direction the user swiped across the object. This direction is then written to the text property of the TextArea component. The results can be seen in Figure 4-15.

When a user performs a “pinch and zoom” on the object with two fingers, the TransformGestureEvent.GESTURE_ZOOM event is triggered and the onGestureZoom method is called. Within the onGestureZoom method, the value of the event’s scaleX and scaleY written to the text property of the TextArea component. The scaleX value is then used as a multiplier on the object’s scaleX and scaleY property to increase or decrease the size of the object as the user pinches or expands two fingers on the object. The results can be seen in Figure 4-16:

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
                  xmlns:s="library://ns.adobe.com/flex/spark"
                  applicationComplete="application1_applicationCompleteHandler(event)">    <fx:Script>
          <![CDATA[
               import mx.events.FlexEvent;

               protected function application1_applicationCompleteHandler(event:FlexEvent):void {
                     Multitouch.inputMode = MultitouchInputMode.GESTURE;
                     if(Multitouch.supportsGestureEvents){
                          image.addEventListener(TransformGestureEvent.GESTURE_PAN, 
                              onGesturePan);
                          image.addEventListener(TransformGestureEvent.GESTURE_ROTATE, 
                              onGestureRotate);
                          image.addEventListener(TransformGestureEvent.GESTURE_SWIPE, 
                              onGestureSwipe);
                          image.addEventListener(TransformGestureEvent.GESTURE_ZOOM, 
                              onGestureZoom);
                     } else {
                          status.text="gestures not supported";
                     }
               }

               private function onGesturePan(event:TransformGestureEvent):void{
                     info.text = "event = " + event.type + "\n" +
                          "offsetX = " + event.offsetX + "\n" +
                          "offsetY = " + event.offsetY;
                     image.x += event.offsetX;
                     image.y += event.offsetY;
               }

               private function onGestureRotate( event : TransformGestureEvent ) : void {
                     info.text = "event = " + event.type + "\n" +
                          "rotation = " + event.rotation;
                     image.transformAround(new Vector3D(image.width/2,image.height/2, 0),
                          null,
                          new Vector3D(0,0,image.rotationZ
                                + event.rotation));
               }

               private function onGestureSwipe( event : TransformGestureEvent ) : void {
                     var direction:String = "";
                     if(event.offsetX == 1) direction = "right";
                     if(event.offsetX == −1) direction = "left";
                     if(event.offsetY == 1) direction = "down";
                     if(event.offsetY == −1) direction = "up";
                     info.text = "event = " + event.type + "\n" +
                          "direction = " + direction;
               }

               private function onGestureZoom( event : TransformGestureEvent ) : void {
                     info.text = "event = " + event.type + "\n" +
                          "scaleX = " + event.scaleX + "\n" +
                          "scaleY = " + event.scaleY;
                     image.scaleX = image.scaleY *= event.scaleX;
               }

               protected function button1_clickHandler(event:MouseEvent):void
               {
                     image.rotation = 0;
                     image.scaleX = 1;
                     image.scaleY = 1;
                     image.x = 40;
                     image.y = 260;
                     info.text = "";
               }

          ]]>
    </fx:Script>
    <fx:Declarations>
          <!-- Place non-visual elements (e.g., services, value objects) here -->
    </fx:Declarations>
    <s:Label id="status" text="Transform Gestures" top="10" width="100%" 
             textAlign="center"/>
    <s:HGroup width="100%" top="40" left="5" right="5">
          <s:TextArea id="info" editable="false" width="100%" height="200"/>
          <s:Button label="Reset" click="button1_clickHandler(event)"/>
    </s:HGroup>
    <s:Image id="image" x="40" y="260" width="384" height="384"
                source="@Embed('adobeair.jpg')"/>
</s:Application>
GESTURE_PAN event

Figure 4-13. GESTURE_PAN event

GESTURE_ROTATE event

Figure 4-14. GESTURE_ROTATE event

GESTURE_SWIPE event

Figure 4-15. GESTURE_SWIPE event

GESTURE_ZOOM event

Figure 4-16. GESTURE_ZOOM event

Get Developing iOS Applications with Flex 4.5 now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.