Home | History | Annotate | Download | only in articles
      1 page.title=Gestures
      2 @jd:body
      3 
      4 <p>Touch screens are a great way to interact with applications on
      5 mobile devices. With a touch screen, users can easily tap, drag, fling,
      6 or slide to quickly perform actions in their favorite applications. 
      7 For app developers. the Android framework makes it's easy to
      8 recognize simple actions, like a swipe, but it has been more 
      9 difficult to handle complicated gestures, sometimes requiring 
     10 developers to write a lot of code.</p>
     11 
     12 <p>That's why we introduced a new gestures API in Android 1.6. This API, located
     13 in the new package {@link android.gesture}, lets you store, load, draw, and
     14 recognize gestures. This article will show you how you can use the
     15 <code>android.gesture</code> API in your applications. Before going any further,
     16 you should <a
     17 href="http://code.google.com/p/apps-for-android/downloads/detail?name=
     18 GesturesDemos.zip&amp;can=2&amp;q=#makechanges">download the source code 
     19 of the examples</a>.</p>
     20 
     21 <h3>Creating a gestures library</h3>
     22 
     23 <p>Android 1.6 and higher SDK platforms include a new application pre-installed
     24 on the emulator, called Gestures Builder. You can use this application to create
     25 a set of pre-defined gestures for your own application. It also serves as an
     26 example of how to let the user define his own gestures in your applications. You
     27 can find the source code of Gestures Builders in the samples directory of each
     28 SDK platform. In our example we will use Gestures Builder to generate a set of
     29 gestures for us (make sure to create an AVD with an SD card image to use
     30 Gestures Builder.) The screenshot below shows what the application looks like
     31 after adding a few gestures:</p>
     32 
     33 <img src="images/gestures_006.png" style="width: 320px; height: 480px;">
     34 
     35 <p>As you can see, a gesture is always associated with a name. That name is very
     36 important because it identifies each gesture within your application. The names
     37 do not have to be unique. Actually it can be very useful to have several
     38 gestures with the same name to increase the precision of the recognition. Every
     39 time you add or edit a gesture in the Gestures Builder, a file is generated on
     40 the emulator's SD card, <code>/sdcard/gestures</code>. This file contains the
     41 description of all the gestures, and you will need to package it inside your
     42 application inside the resources directory, in
     43 <code>/res/raw</code>.</p>
     44 
     45 <h3>Loading the gestures library</h3>
     46 
     47 <p>Now that you have a set of pre-defined gestures, you must load it inside your
     48 application. This can be achieved in several ways but the easiest is to use the
     49 <code>GestureLibraries</code> class:</p>
     50 
     51 <pre class="prettyprint">mLibrary = GestureLibraries.fromRawResource(this, R.raw.spells);
     52 if (!mLibrary.load()) {
     53     finish();
     54 }</pre>
     55 
     56 <p>In this example, the gesture library is loaded from the file
     57 <code>/res/raw/spells</code>. You can easily load libraries from other sources,
     58 like the SD card, which is very important if you want your application to be
     59 able to save the library; a library loaded from a raw resource is read-only and
     60 cannot be modified. The following diagram shows the structure of a library:</p>
     61 
     62 <img src="images/gestures_002.png" style="width: 600px; height: 512px;">
     63 
     64 <h3>Recognizing gestures</h3>
     65 
     66 <p>To start recognizing gestures in your application, all you have to do 
     67 is add a <code>GestureOverlayView</code> to your XML layout:</p>
     68 
     69 <pre>&lt;android.gesture.GestureOverlayView
     70     android:id="@+id/gestures"
     71     android:layout_width="fill_parent" 
     72     android:layout_height="0dip"
     73     android:layout_weight="1.0" /&gt;</pre>
     74 
     75 <p>Notice that the <code>GestureOverlayView</code>
     76 is not part of the usual android.widget package. Therefore, you must
     77 use its fully qualified name. A gesture overlay acts as a simple
     78 drawing board on which the user can draw his gestures. You can tweak
     79 several visual properties, like the color and the width of the stroke
     80 used to draw gestures, and register various listeners to follow what
     81 the user is doing. The most commonly used listener is 
     82 <code>GestureOverlayView.OnGesturePerformedListener</code>, 
     83 which fires whenever a user is done drawing a gesture:</p>
     84 
     85 <pre>GestureOverlayView gestures = (GestureOverlayView) findViewById(R.id.gestures);
     86 gestures.addOnGesturePerformedListener(this);</pre>
     87 
     88 <p>When the listener fires, you can ask the <code>GestureLibrary</code>
     89 to try to recognize the gesture. In return, you will get a list of
     90 Prediction instances, each with a name - the same name you entered in
     91 the Gestures Builder - and a score. The list is sorted by descending
     92 scores; the higher the score, the more likely the associated gesture is
     93 the one the user intended to draw. The following code snippet
     94 demonstrates how to retrieve the name of the first prediction:</p>
     95 
     96 <pre>public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) {
     97     ArrayList&lt;prediction&gt; predictions = mLibrary.recognize(gesture);
     98 
     99     // We want at least one prediction
    100     if (predictions.size() &gt; 0) {
    101         Prediction prediction = predictions.get(0);
    102         // We want at least some confidence in the result
    103         if (prediction.score &gt; 1.0) {
    104             // Show the spell
    105             Toast.makeText(this, prediction.name, Toast.LENGTH_SHORT).show();
    106         }
    107     }
    108 }</pre>
    109 
    110 <p>In this example, the first prediction is taken into account only if it's
    111 score is greater than 1.0. The threshold you use is entirely up to you
    112 but know that scores lower than 1.0 are typically poor matches. And
    113 this is all the code you need to create a simple application that can
    114 recognize pre-defined gestures (see the source code of the project
    115 GesturesDemo):</p>
    116 
    117 <img src="images/gestures.png" style="width: 320px; height: 480px;">
    118 
    119 <h3>Gestures overlay</h3>
    120 
    121 <p>In the example above, the <code>GestureOverlayView</code> was used 
    122 as a normal view, embedded inside a <code>LinearLayout</code>.
    123 However, as its name suggests, it can also be used as an overlay on top
    124 of other views. This can be useful to recognize gestures in a game or
    125 just anywhere in the UI of an application. In the second example,
    126 called GesturesListDemo, we'll create an overlay on top of a list of
    127 contacts. We start again in Gestures Builder to create a new set of
    128 pre-defined gestures:</p>
    129 
    130 <p><img src="images/gestures_005.png" style="width: 320px; height: 480px;"></p>
    131 
    132 <p>And here is what the XML layout looks like:</p>
    133 
    134 <pre>&lt;android.gesture.GestureOverlayView
    135     xmlns:android="http://schemas.android.com/apk/res/android"
    136     android:id="@+id/gestures"
    137     android:layout_width="fill_parent"
    138     android:layout_height="fill_parent"
    139     
    140     android:gestureStrokeType="multiple"
    141     android:eventsInterceptionEnabled="true"
    142     android:orientation="vertical"&gt;
    143 
    144     &lt;ListView
    145         android:id="@android:id/list"  
    146         android:layout_width="fill_parent" 
    147         android:layout_height="fill_parent"  /&gt;
    148 
    149 &lt;/android.gesture.GestureOverlayView&gt;</pre>
    150 
    151 <p>In this application, the gestures view is an overlay on top of a regular
    152 ListView. The overlay also specifies a few properties that we did not
    153 need before:</p>
    154 
    155 <ul>
    156 <li><code>gestureStrokeType</code>: indicates
    157 whether we want to recognize gestures made of a single stroke or
    158 multiple strokes. Since one of our gestures is the "+" symbol, we need
    159 multiple strokes</li>
    160 <li><code>eventsInterceptionEnabled</code>: when
    161 set to true, this property tells the overlay to steal the events from
    162 its children as soon as it knows the user is really drawing a gesture.
    163 This is useful when there's a scrollable view under the overlay, to
    164 avoid scrolling the underlying child as the user draws his gesture </li>
    165 <li><code>orientation</code>:
    166 indicates the scroll orientation of the views underneath. In this case
    167 the list scrolls vertically, which means that any horizontal gestures
    168 (like <code>action_delete</code>) can immediately be recognized as a
    169 gesture. Gestures that start with a vertical stroke must contain at
    170 least one horizontal component to be recognized. In other words, a
    171 simple vertical line cannot be recognized as a gesture since it would
    172 conflict with the list's scrolling.</li>
    173 </ul>
    174 
    175 <p>The code used to load and set up the gestures library and overlay is exactly
    176 the same as before. The only difference is that we now check the name of the
    177 predictions to know what the user intended to do:</p>
    178 
    179 <pre>public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) {
    180     ArrayList&lt;Prediction&gt; predictions = mLibrary.recognize(gesture);
    181     if (predictions.size() &gt; 0 &amp;&amp; predictions.get(0).score &gt; 1.0) {
    182         String action = predictions.get(0).name;
    183         if ("action_add".equals(action)) {
    184             Toast.makeText(this, "Adding a contact", Toast.LENGTH_SHORT).show();
    185         } else if ("action_delete".equals(action)) {
    186             Toast.makeText(this, "Removing a contact", Toast.LENGTH_SHORT).show();
    187         } else if ("action_refresh".equals(action)) {
    188             Toast.makeText(this, "Reloading contacts", Toast.LENGTH_SHORT).show();
    189         }
    190     }
    191 }</pre>
    192 
    193 <p>The user is now able to draw his gestures on top of the list without 
    194 interfering with the scrolling:</p>
    195 
    196 <img src="images/gestures_004.png" style="width: 320px; height: 480px;">
    197 
    198 <p>The overlay even gives visual clues as to whether the gesture is considered
    199 valid for recognition. In the case of a vertical overlay, for instance,
    200 a single vertical stroke cannot be recognized as a gesture and is
    201 therefore drawn with a translucent color:</p>
    202 
    203 <img src="images/gestures_003.png" style="width: 320px; height: 480px;">
    204 
    205 <h3>It's your turn</h3>
    206 
    207 <p>Adding support for gestures in your application is easy and can be a valuable
    208 addition. The gestures API does not even have to be used to recognize complex
    209 shapes; it will work equally well to recognize simple swipes. We are very
    210 excited by the possibilities the gestures API offers, and we're eager to see
    211 what cool applications the community will create with it.</p>
    212