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