8. Februar 2013

Android: Gestenerkennung mit GestureOverlayView

In einem vergangenen Post wurde bereits die Erkennung von einfachen Gesten in einer Android-App vorgestellt. Das Problem bei der dort vorgestellten Vorgehensweise, die auf der Verwendung der Klasse "GestureDetector" basierte, war, dass nur diejenigen Gesten erkannt wurden, die direkt auf der entsprechenden Activity, bzw. View ausgeführt wurden. Wenn diese  von anderen Komponenten, wie z.B. Buttons verdeckt wurde, schlug die Erkennung fehl. Diese Problematik lässt sich durch die Komponente "GestureOverlayView" umgehen. Diese Möglichkeit der Gestenerkennung  soll in diesem Post vorgestellt werden. Der ursprüngliche Post findet sich hier. Das Beispiel in diesem Post basiert auf dessen Original-Beispiel.

Zunächst einmal muss eine GestureOverlayKomponente in das entsprechende XML Layout File integriert werden. In diesem Beispiel soll die Komponente über allen anderen Komponenten und über die komplette Bildschirmfläche gelegt werden. Der Aufbau der resultierenden XML-Datei sieht hierbei wie folgt aus:
 <?xml version="1.0" encoding="utf-8"?>  
 <android.gesture.GestureOverlayView xmlns:android="http://schemas.android.com/apk/res/android"  
   android:id="@+id/gestureOverlayView"  
   android:layout_width="fill_parent"  
   android:layout_height="fill_parent"  
   android:eventsInterceptionEnabled="true"  
   android:fadeEnabled="false"  
   android:fadeOffset="0"  
   android:gestureColor="#00000000"  
   android:gestureStrokeType="multiple"  
   android:orientation="vertical"  
   android:uncertainGestureColor="#00000000" >  
   
   <LinearLayout  
     android:layout_width="match_parent"  
     android:layout_height="match_parent"  
     android:orientation="vertical" >  
   
     <TextView  
       android:id="@+id/textView"  
       android:layout_width="wrap_content"  
       android:layout_height="wrap_content"  
       android:text="no gesture detected" />  
   </LinearLayout>  
   
 </android.gesture.GestureOverlayView>  

Standardmäßig werden die ausgeführten Gesten auf der Komponente visuell dargestellt, sollen diese jedoch ausschließlich erkannt werden, so ist diese Darstellung unerwünscht und kann vermieden werden, in dem man die zur Darstellung benutzen Farben über die Attribute android:gestureColor="#00000000" und android:uncertainGestureColor="#00000000" auf transparent stellt. Über die Attribute android:fadeOffset="0" und android:fadeEnabled="false" lässt sich die störende Verzögerung zwischen Gestenerkennung und daraus resultierender Aktion elimieren, die dadurch entsteht, das die Visualisierung, wenn vorhanden, zunächst langsam ausgeblendet wird, bevor die Aktion ausgeführt wird.

Im Gegensatz zur Verwendung der Klasse "GestureDetector", bietet die Verwendung einer GestureOverlayView weitreichendere Möglichkeiten, da beliebige Gesten über eine sogenannte Gesture-Library definiert werden können. Dazu bietet das Android-SDK ein Tool namens "GestureBuilder", das im Android-Emulator bereits als App vorhanden ist.Mithilfe dieser App lassen sich beliebige Gesten durch Zeichnen definieren, mit einem Namen versehen und in einer Datei exportieren. Dazu muss der Emulator so konfiguriert sein, dass er eine virtuelle SD-Karte benutzt (dies wurde bereits in diesem Post beschrieben). Die dadurch erzeugte Datei lässt sich beispielsweise über die Eclipse-View "File Explorer" aus dem Emulator in das reguläre Dateisystem übertragen (die Datei ist auf diese Weise unter dem Pfad mnt/sdcard/gesture zu finden). Die so erhaltene Gesture-Library muss imjeweiligen Projekt im Unterverzeichnis res/raw abgelegt werden.

Im GestureBuilder erstellte Gesten (Klicken zum Vergrößern)

Um die im XML-Layout definierte GestureOverlayView-Komponente zu benutzen um, in der Gesture-Library abgelegte, Gesten zu erkennen, muss anschließen der Code der entsprechenden Activity angepasst werden. Diese muss dazu das Interface android.gesture.GestureOverlayView.OnGesturePerformedListener implementieren. Der resultierende Code könnte etwa wie folgt aussehen:
 public class DashboardActivity extends Activity implements  
         OnGesturePerformedListener {  
   
     private GestureLibrary gestureLibrary;  
   
     @Override  
     public void onCreate(Bundle savedInstanceState) {  
         super.onCreate(savedInstanceState);  
         setContentView(R.layout.dashboard_activity);  
   
         gestureLibrary = GestureLibraries.fromRawResource(this, R.raw.gestures);  
   
         if (!gestureLibrary.load()) {  
             finish();  
         }  
   
         GestureOverlayView gestures = (GestureOverlayView) findViewById(R.id.gestureOverlayView);  
         gestures.addOnGesturePerformedListener(this);  
     }  
   
     public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) {  
         ArrayList<Prediction> predictions = gestureLibrary.recognize(gesture);  
   
         if (predictions.size() > 0) {  
             Prediction prediction = predictions.get(0);  
   
             if (prediction.score > 1.0) {  
                 if (prediction.name.equalsIgnoreCase("swipe_right")) {  
                     TextView textView = (TextView) findById(R.id.textView);  
                     textView.setText("detected swipe right gesture");  
                 } else if (prediction.name.equalsIgnoreCase("swipe_left")) {  
                     TextView textView = (TextView) findById(R.id.textView);  
                     textView.setText("detected swipe left gesture");  
                 }  
             }  
         }  
     }  
   
 }  
Die Activity erhält hierbei eine Instanz der Klasse android.gesture.GestureLibrary, in die, beim Aufruft der onCreate-Methode, die zuvor erstellte Gesture-Library aus der entsprechenden Datei geladen wird. Außerdem wird die in der XML-Datei definierte GestureOverlayView über ihre ID geladen und die Activity wird als Listener an ihr angemeldet.

Die eigentliche Erkennung findet nun in der onGesturePerformed-Methode statt, die automatisch bei der Erkennung einer definierten Geste aufgerufen wird. Es gilt dabei, zu überprüfen, welche Geste erkannt wurde, was über den, im GestureBuilder angegebenen, Namen möglich ist. In diesem Fall wurden zwei Swipe-Gesten definiert, deren Erkennung in einer TextView ausgegeben wird.

Keine Kommentare:

Kommentar veröffentlichen