Освой программирование играючи
/* Моя кошка замечательно разбирается в программировании. Стоит мне объяснить проблему ей - и все становится ясно. */
John Robbins, Debugging Applications, Microsoft Press, 2000
Подготовительные работы - приложение Gestures Builder
Создаём приложение с распознаванием жестов
Слайд-шоу на основе жестов
Цвета для жестов
Данный компонент присутствовал в Eclipse и в ранних версиях студии. Сейчас на панели инструментов его нет, но класс не объявлен устаревшим. Статья была написана ещё во времена использования Eclipse много лет назад.
Android позволяет быстро добавить в приложение возможность распознавания собственных жестов. Например, можно нарисовать кота и программа, распознав ваш жест, может замяукать (воспроизвести звуковой файл).
Найдите на эмуляторе программу Gestures Builder. Запустите её. Нажмите на кнопку Add gesture (Добавить жест). Введите имя для нового жеста, например, Slide to left (Жест влево) и проведите мышкой по экрану справа налево. Нажмите на кнопку Done, чтобы завершить создание жеста. Появится сообщение, что жест был сохранён по адресу /mnt/sdcard/gestures.
Аналогично добавьте жесты Slide to right (Жест вправо) и Kitty - Жест, напоминающий кота (просто жесть!).
Когда закончите с жестами, программу можете закрывать, она вам больше не понадобится. Но если задумаете добавить новые жесты или удалить старые - снова запускайте приложение и выполняйте нужные действия.
В Eclipse откройте перспективу DDMS и найдите вкладку File Explorer. Перейдите по указанному адресу /mnt/sdcard/, где были сохранены жесты, и найдите файл gestures без расширения. Скопируйте его на свой рабочий компьютер при помощи кнопки Pull a file from the device. На этом подготовительная часть завершена.
Создайте новый проект. Далее создайте новую папку res/raw и скопируйте в него файл gestures, сохранённый вами ранее.
Разместим компонент GestureOverlayView на экране:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<android.gesture.GestureOverlayView
android:id="@+id/gestures1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:eventsInterceptionEnabled="true"
android:gestureStrokeType="multiple" />
</RelativeLayout>
Далее пишем код по распознаванию жестов:
package ru.alexanderklimov.gestureoverlayview;
import java.util.ArrayList;
import android.os.Bundle;
import android.app.Activity;
import android.gesture.Gesture;
import android.gesture.GestureLibraries;
import android.gesture.GestureLibrary;
import android.gesture.GestureOverlayView;
import android.gesture.GestureOverlayView.OnGesturePerformedListener;
import android.gesture.Prediction;
import android.view.Menu;
import android.widget.Toast;
public class MainActivity extends Activity {
private GestureLibrary gestureLib;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
GestureOverlayView gestureview = (GestureOverlayView) findViewById(R.id.gestures1);
gestureLib = GestureLibraries.fromRawResource(this, R.raw.gestures);
if (!gestureLib.load()) {
finish();
}
gestureview.addOnGesturePerformedListener(handleGestureListener);
}
private OnGesturePerformedListener handleGestureListener = new OnGesturePerformedListener() {
public void onGesturePerformed(GestureOverlayView gestureView,
Gesture gesture) {
ArrayList<Prediction> predictions = gestureLib.recognize(gesture);
if (predictions.size() > 0) {
Prediction prediction = predictions.get(0);
if (prediction.score > 1.0) {
Toast.makeText(MainActivity.this,
"Ваш жест : " + prediction.name,
Toast.LENGTH_LONG).show();
}
}
}
};
}
Как видите, мы подключаем жесты через ресурсы:
gestureLib = GestureLibraries.fromRawResource(this, R.raw.gestures);
Запускаем приложение и пытаемся повторить жесты, которые мы создавали в Gesture Builder. Если приложение распознает созданные вами жесты, то появится всплывающее сообщение.
Перейдём к более практичному примеру на основе предыдущего примера.
Добавим в разметку элемент ViewFlipper, который будет распознавать жесты и работать как слайд-шоу при использовании наших жестов.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<android.gesture.GestureOverlayView
android:id="@+id/gestures1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:eventsInterceptionEnabled="true"
android:gestureStrokeType="multiple" />
<LinearLayout
android:id="@+id/LinearLayout1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="75dp" >
<ViewFlipper
android:id="@+id/ViewFlipper01"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<ImageView
android:id="@+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/cat1" />
<ImageView
android:id="@+id/imageView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/cat2" />
<ImageView
android:id="@+id/imageView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/cat3" />
<ImageView
android:id="@+id/imageView4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/cat4" />
</ViewFlipper>
</LinearLayout>
</RelativeLayout>
Теперь нам нужно распознать жест по его имени и выполнить нужную операцию:
package ru.alexanderklimov.gestureoverlayview;
import ...
public class MainActivity extends Activity {
private GestureLibrary gestureLib;
ViewFlipper vf;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
GestureOverlayView gestureview = (GestureOverlayView) findViewById(R.id.gestures1);
gestureLib = GestureLibraries.fromRawResource(this, R.raw.gestures);
if (!gestureLib.load()) {
finish();
}
gestureview.addOnGesturePerformedListener(handleGestureListener);
vf = (ViewFlipper) findViewById(R.id.ViewFlipper1);
vf.setInAnimation(this, android.R.anim.fade_in);
vf.setOutAnimation(this, android.R.anim.fade_out);
}
private OnGesturePerformedListener handleGestureListener = new OnGesturePerformedListener() {
public void onGesturePerformed(GestureOverlayView gestureView,
Gesture gesture) {
ArrayList<Prediction> predictions = gestureLib.recognize(gesture);
if (predictions.size() > 0) {
Prediction prediction = predictions.get(0);
if (prediction.score > 1.0) {
String action = predictions.get(0).name;
if ("Slide to left".equals(action)) {
vf.showPrevious();
Toast.makeText(MainActivity.this,
prediction.name + " : Show Next Picture",
Toast.LENGTH_LONG).show();
} else if ("Slide to right".equals(action)) {
vf.showPrevious();
vf.showPrevious();
Toast.makeText(MainActivity.this,
prediction.name + " : Show Previous Picture",
Toast.LENGTH_LONG).show();
} else if ("Kitty".equals(action)) {
// можно мяукать или делать другие действия
Toast.makeText(MainActivity.this,
prediction.name,
Toast.LENGTH_LONG).show();
}
}
}
}
};
}
Конечно, жесты вправо-влево слишком примитивны и реализовать слайд-шоу можно и более стандартными способами. Здесь они показаны только для демонстрации. Но можно придумать и более замысловатые жесты. В нашем примере есть сложный жест, напоминающий фигурку кота и программа прекрасно распознаёт его. Также можно придумать жесты в виде отдельных буквы. Скажем, жест в виде буквы S может сохранять документ (Save) и т.д.
По умолчанию, когда мы делаем жесты в приложении, то рисуются жирные жёлтые линии. Вы можете настроить цвет через XML, установив у GestureOverlayView необходимые атрибуты:
android:gestureColor="#AAFF0000"
android:uncertainGestureColor="#AA00FF00"
Если приложение распознало жест, то линия будет выводиться цветом из первого параметра, иначе - из второго. Поменяв цвета на красный и зелёный, я сделал процесс распознавания жестов более наглядным. В реальном приложении возможно стоит использовать прозрачные цвета, чтобы не отвлекать пользователя.