Ovi Store by Nokia is now available globally to an estimated 50 million Nokia device owners across more than 50 Nokia devices, including the forthcoming flagship device, the Nokia N97.
Starting from today, on a first set of Nokia devices, you can start purchasing and downloading applications from the Ovi Store client on your device.
And, if you’re a developer, you can finally start to distribute your content to all Nokia users around the globe!
With the release of many touch-enabled devices, as the latest Nokia 5800 XpressMusic and the forthcoming Nokia N97, applications can benefit from new ways of touch-based interactions. A typical example of these new patterns is represented by gestures: simple finger/stylus actions that allow the user to perform specific task, without the need of a precise interaction (e.g.: identify and press a specific button).
This article will explain how to implement basic touch gestures in Flash Lite. Specifically, we’ll see how to detect both horizontal (left-to-right and right-to-left) and vertical (up-to-down and down-to-up) gestures.
In the above video it’s possible to see a simple Flash Lite photo viewer, where the user can go from a photo to the next/previous just sliding finger or stylus.
The source code
Step 1. Detect touch events
First thing to do is to detect and handle touch-based events, and this can be done by implementing a MouseListener, and its onMouseDown() and onMouseUp() methods. We also define 4 Number variables to hold the x and y coordinates associated to the mouse up and down events: these will be used to detect if the touch interaction was actually a gesture or not.
So, take a new and empty FLA, and add this code on your first frame:
var startX:Number;
var startY:Number;
var endX:Number;
var endY:Number;
var gesturesListener:Object = newObject();
gesturesListener.onMouseDown = function(){
startX = _root._xmouse;
startY = _root._ymouse;
}
gesturesListener.onMouseUp = function(){
endX = _root._xmouse;
endY = _root._ymouse;
checkGesture();
}Mouse.addListener(gesturesListener);
The onMouseDown() function just sets the starting coordinates values, while the onMouseUp() also calls the checkGesture() function, defined below, that will check if the touch interaction was actually a gesture.
Step 2. Identify a gesture
Before trying to identify a gesture, let’s define some variables used to identify and define specific gesture types:
// minimum length of an horizontal gesturevar MIN_H_GESTURE:Number = Stage.width/3;
// minimum length of a vertical gesturevar MIN_V_GESTURE:Number = Stage.height/3;
// flags for each kind of gesturevar UP_TO_DOWN:Number = 1;
var DOWN_TO_UP:Number = 2;
var LEFT_TO_RIGHT:Number = 4;
var RIGHT_TO_LEFT:Number = 8;
The MIN_H_GESTURE and MIN_V_GESTURE variables define the minimum horizontal and vertical distances that must exist between the onMouseDown() and the onMouseUp() event to have, respectively, a horizontal or a vertical gesture.
Now, we can easily implement the checkGesture() function, by getting the horizontal and vertical length of the touch interaction, and comparing them with the minimum distances defined above.
Once identified a gesture, we have to actually handle it in some way. To do it, we’ll implement the handleGesture() function, that will check the passed argument to find which is the specific identified gesture.
In this example, we’ll simply trace the kind of identified gesture(s).
function handleGesture(gestureFlags:Number){if(gestureFlags & LEFT_TO_RIGHT)trace("left to right gesture");
if(gestureFlags & RIGHT_TO_LEFT)trace("right to left gesture");
if(gestureFlags & UP_TO_DOWN)trace("up to down gesture");
if(gestureFlags & DOWN_TO_UP)trace("down to up gesture");
}
Further development
A lot of improvements can be done to the code presented in this article. Just some example:
Detect diagonal gestures: by checking the appropriate gesture flags, it’s already possible to identify mixed diagonal gestures. So, basically you need to extend a bit the handleGesture() method
Define a maximum time to perform a gesture: basically, accept a gesture only if the time elapsed to perform it is below a certain limit. This could be useful in some scenarios, to avoid detecting fake gestures.
Download source code
You can download the full source code used in this article here:
This is an awesome tutorial and it’s much appreciated.
I was having some trouble assigning the gestures to soft keys.
In this tutorial, you are displaying the gestures, However for example could you please tell me how I would be able to assign the “right to left” gesture to the right key?
Thanks.
Supriya Tenany
11:18 am on December 21, 2010 Permalink
Hi,
A really good tutorial. I am only waiting for the practical implementation now. How can I check the touch functionalities on the device central? It provides me ‘Multitouch’ but I am unable to use it.
Let’s create the FisheyeMenu ActionScript class, that will extend MovieClip, that will be used to implement the actual menu logic:
class FisheyeMenu extends MovieClip
{}
Then, create an empty movie clip in your library, export it, and associate it with the FisheyeMenu class.
Step 2. Initializing the menu
First, define these 4 menu properties, that will hold some useful values:
// focus index of the selected menu item
var focusedIndex:Number;// total number of menu items
var itemsNum:Number;// width of single menu items (in pixels)
var itemWidth:Number;// the MovieClip that will contain the menu items
var itemsContainer:MovieClip;
Let’s also define an utility function that returns the currently focused item index:
public function getFocusedIndex(){returnthis.focusedIndex;}
And then, implement a function that will be used to initialize the menu with the items you want.
public function initializeMenu(itemIds:Array, itemWidth:Number){this.itemsNum= itemIds.length;this.focusedIndex=0;this.itemWidth= itemWidth;this.initItems(itemIds);}private function initItems(itemIds:Array){this.itemsContainer=this.createEmptyMovieClip('itemsContainer', this.getNextHighestDepth());for(var i:Number=0; i < itemIds.length; i++){
var item:MovieClip = itemsContainer.attachMovie(itemIds[i], 'item_'+ i, itemsContainer.getNextHighestDepth(), {_x: itemWidth * i, _y:0});if(i >0){
item._xscale =50;
item._yscale =50;}}}
The initializeMenu() function is the function you will call to initialize your fisheye menu with the items you want. Its arguments are:
an Array containing the id of MovieClip symbols to be used as items
the width of single menu items
Once called, initializeMenu()initializes the menu properties and then calls the initItems() function, that will actually attach the item instances, scaling down the unselected items and translating the menu itself to its starting position.
The getMenuLeft() function returns the x position to be used for the itemsContainerMovieClip, and depends on the focused item index:
private function getMenuLeft():Number{return- itemWidth * focusedIndex;}
Step 3. Implement sliding funcionality
When the user presses LEFT and RIGHT keys, you want the menu to perform these steps:
change the focused item, scaling down the previously focused one, and scaling up the new
translate the menu to be centered on the new focused item
In ActionScript, you can do it this way:
public function shiftItem(itemDelta:Number){
var nextIndex:Number= focusedIndex + itemDelta;if(nextIndex >=0&& nextIndex < itemsNum){
scaleItem(focusedIndex, true);
focusedIndex = nextIndex;
scaleItem(focusedIndex, false);
moveMenu();}}private function moveMenu():Void{new Tween(itemsContainer, "_x", None.easeNone, itemsContainer._x, getMenuLeft(), .50, true);}private function scaleItem(itemIndex:Number, scaleDown:Boolean):Void{
var item:MovieClip = itemsContainer['item_'+ itemIndex];
var fromScale:Number= scaleDown ?100:50;
var toScale:Number= scaleDown ?50:100;new Tween(item, "_xscale", None.easeNone, fromScale, toScale, .50, true);new Tween(item, "_yscale", None.easeNone, fromScale, toScale, .50, true);}
In this code snippet, there are 3 functions:
shiftItem() is the function called to change the focused Item index by the passed delta argument. It checks if the change is ok, and then calls the following 2 functions:
moveMenu() actually translates the items container, to have the new focused item horizontally centered
scaleItem()scales up or down, depending on the scaleDown argument, the item corresponding at the index passed as argument
Since here we use the Tween class, we have to add these 2 import lines at the beginning of the ActionScript file:
Take back your FLA, and create 3 symbols that will be used as items within the fisheye menu. Also, remember to check the “Export for ActionScript” option, to have them actually usable from ActionScript itself.
Step 5. Attach and initialize the menu
Now, attach a FisheyeMenu istance directly to the _root, and initialize it with the ID of the symbols created in the previous step:
var menu:MovieClip = _root.attachMovie('FisheyeMenu', 'main_menu', _root.getNextHighestDepth());
var items:Array=newArray('Item0', 'Item1', 'Item2');
menu._x =120;
menu._y =120;
menu.initializeMenu(items, 50);
Step 6. Create a KeyListener to interact with the menu
The KeyListener will be really simple, since it will simply call the shiftItem() function when the user press LEFT or RIGHT keys, and will call a custom function when the user press the ENTER key, to trace the index of the current focused item:
var keyListener:Object=newObject();
keyListener.onKeyDown= function(){
var key:Number=Key.getCode();if(key ==Key.RIGHT){
menu.shiftItem(1);}elseif(key ==Key.LEFT){
menu.shiftItem(-1);}elseif(key ==Key.ENTER){
menuFireAction();}}Key.addListener(keyListener);
function menuFireAction(){
trace("MENU ITEM PRESSED: "+ menu.getFocusedIndex());}
Downloads and related resources
You can download full source code (FLA + ActionScript file) of this example here:
What does it mean? In few words: no more worries about Flash Lite versions on users’ devices, more distribution opportunities for developers, and more applications for users!
In Adobe’s words:
Since the distributable player solution mimics the successful Adobe Flash® Player desktop model of content-triggered downloads, you can be confident that your users’ devices will always have the latest Flash Lite runtime.
Plus, the distribution model enables you to deliver free or paid applications to millions of open OS smartphones, through direct-to-consumer distribution or your existing distribution channels, or via Adobe’s aggregator partners, which include GetJar, Thumbplay, and Zed.
Finally, this solution gives end users a better experience by providing intuitive discovery and installation of Flash Lite applications. Consumers using supported Windows Mobile and S60 phones in India, Italy, Spain, UK, and the U.S. can easily download applications. (Additional countries will be added over time.) After downloading an application, consumers see its user-friendly icon in the device menu.
After 3 days in the cold and magic lands of Calabria, I found great news from Kuneri team: Pikkoo, the first community to create, share and download mobile wallpapers and screensavers, gets launched!
What’s great about this project?
You can create your screensavers and wallpapers in a snap! No graphic skills? No problem at all! Just drag the elements you want, choose colors, enter texts, define animations, and you’re done!
Do you think your creations are great? Share them! Not only on Pikkoo gallery, but also on your favorite social websites, with the cool Pikkoo social apps!
It’s FREE!
Still waiting? Just give it a try, and create your new mobile style!
Reply