reader/android: swipe left or right to turn pages

Change-Id: I037be10273f637a754c82bfcf3c6515034e19d13
diff --git a/android/app/src/main/java/io/v/android/apps/reader/PdfViewerActivity.java b/android/app/src/main/java/io/v/android/apps/reader/PdfViewerActivity.java
index b3e1c1a..2dfe9b7 100644
--- a/android/app/src/main/java/io/v/android/apps/reader/PdfViewerActivity.java
+++ b/android/app/src/main/java/io/v/android/apps/reader/PdfViewerActivity.java
@@ -10,13 +10,14 @@
 import android.net.Uri;
 import android.os.Bundle;
 import android.provider.OpenableColumns;
+import android.support.v4.view.GestureDetectorCompat;
 import android.util.Log;
 import android.view.Menu;
 import android.view.MenuItem;
+import android.view.MotionEvent;
 import android.view.View;
 import android.webkit.WebView;
 import android.webkit.WebViewClient;
-import android.widget.Button;
 import android.widget.Toast;
 
 import com.google.android.gms.analytics.HitBuilders;
@@ -47,8 +48,6 @@
     private static final String EXTRA_DEVICE_SET_ID = "device_set_id";
 
     private PdfViewWrapper mPdfView;
-    private Button mButtonPrev;
-    private Button mButtonNext;
     private MenuItem mMenuItemLinkPage;
 
     private DBList<DeviceSet> mDeviceSets;
@@ -78,20 +77,27 @@
         mPdfView = (PdfViewWrapper) findViewById(R.id.pdfview);
         mPdfView.init();
 
-        mButtonPrev = (Button) findViewById(R.id.button_prev);
-        mButtonNext = (Button) findViewById(R.id.button_next);
+        // Swipe gesture detection.
+        final GestureDetectorCompat swipeDetector = SwipeGestureDetector.create(
+                this,
+                new SwipeGestureDetector.SimpleOnSwipeListener() {
+                    @Override
+                    public boolean onSwipeLeft() {
+                        nextPage();
+                        return true;
+                    }
 
-        mButtonPrev.setOnClickListener(new View.OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                prevPage();
-            }
-        });
+                    @Override
+                    public boolean onSwipeRight() {
+                        prevPage();
+                        return true;
+                    }
+                });
 
-        mButtonNext.setOnClickListener(new View.OnClickListener() {
+        mPdfView.setOnTouchListener(new View.OnTouchListener() {
             @Override
-            public void onClick(View v) {
-                nextPage();
+            public boolean onTouch(View v, MotionEvent event) {
+                return swipeDetector.onTouchEvent(event);
             }
         });
     }
diff --git a/android/app/src/main/java/io/v/android/apps/reader/SwipeGestureDetector.java b/android/app/src/main/java/io/v/android/apps/reader/SwipeGestureDetector.java
new file mode 100644
index 0000000..3b73b4b
--- /dev/null
+++ b/android/app/src/main/java/io/v/android/apps/reader/SwipeGestureDetector.java
@@ -0,0 +1,90 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package io.v.android.apps.reader;
+
+import android.content.Context;
+import android.support.v4.view.GestureDetectorCompat;
+import android.view.GestureDetector;
+import android.view.MotionEvent;
+
+/**
+ * A swipe gesture detector which emits swipe events in left/right/up/down directions.
+ */
+public final class SwipeGestureDetector {
+
+    /**
+     * Use SwipeGestureDetector.create() instead.
+     */
+    private SwipeGestureDetector() {
+    }
+
+    /**
+     * The listener interface that is used to notify when swipe gestures occur.
+     * If you only want to listen for a subset, extend {@link SimpleOnSwipeListener} instead.
+     */
+    public interface OnSwipeListener {
+        boolean onSwipeLeft();
+        boolean onSwipeRight();
+        boolean onSwipeUp();
+        boolean onSwipeDown();
+    }
+
+    /**
+     * A convenient class to extend when you only want to listen to a subset of swipe gestures.
+     */
+    public static class SimpleOnSwipeListener implements OnSwipeListener {
+        @Override public boolean onSwipeLeft()  { return false; }
+        @Override public boolean onSwipeRight() { return false; }
+        @Override public boolean onSwipeUp()    { return false; }
+        @Override public boolean onSwipeDown()  { return false; }
+    }
+
+    /**
+     * A gesture listener that listens to fling events and turns them into swipe events.
+     */
+    private static class FlingToSwipeListener extends GestureDetector.SimpleOnGestureListener {
+
+        private static final int DISTANCE_THRESHOLD = 100;
+        private static final int VELOCITY_THRESHOLD = 100;
+
+        private OnSwipeListener mSwipeListener;
+
+        public FlingToSwipeListener(OnSwipeListener swipeListener) {
+            mSwipeListener = swipeListener;
+        }
+
+        @Override
+        public boolean onFling(MotionEvent e1, MotionEvent e2, float vx, float vy) {
+            boolean result = false;
+            float dx = e2.getX() - e1.getX();
+            float dy = e2.getY() - e1.getY();
+            if (Math.abs(dx) > Math.abs(dy)) {
+                if (Math.abs(dx) > DISTANCE_THRESHOLD && Math.abs(vx) > VELOCITY_THRESHOLD) {
+                    if (dx > 0) {
+                        result = mSwipeListener.onSwipeRight();
+                    } else {
+                        result = mSwipeListener.onSwipeLeft();
+                    }
+                }
+            } else {
+                if (Math.abs(dy) > DISTANCE_THRESHOLD && Math.abs(vy) > VELOCITY_THRESHOLD) {
+                    if (dy > 0) {
+                        result = mSwipeListener.onSwipeDown();
+                    } else {
+                        result = mSwipeListener.onSwipeUp();
+                    }
+                }
+            }
+
+            return result;
+        }
+
+    }
+
+    public static GestureDetectorCompat create(Context context, OnSwipeListener listener) {
+        return new GestureDetectorCompat(context, new FlingToSwipeListener(listener));
+    }
+
+}
diff --git a/android/app/src/main/res/layout/activity_pdf_viewer.xml b/android/app/src/main/res/layout/activity_pdf_viewer.xml
index 9f57074..77bb12a 100644
--- a/android/app/src/main/res/layout/activity_pdf_viewer.xml
+++ b/android/app/src/main/res/layout/activity_pdf_viewer.xml
@@ -11,27 +11,10 @@
     android:layout_marginTop="@dimen/activity_vertical_margin"
     tools:context=".PdfViewerActivity">
 
-    <Button
-        android:id="@+id/button_prev"
-        android:layout_width="48dp"
-        android:layout_height="48dp"
-        android:layout_alignParentBottom="true"
-        android:layout_alignParentLeft="true"
-        android:text="&lt;" />
-
-    <Button
-        android:id="@+id/button_next"
-        android:layout_width="48dp"
-        android:layout_height="48dp"
-        android:layout_alignParentBottom="true"
-        android:layout_alignParentRight="true"
-        android:text="&gt;" />
-
     <io.v.android.apps.reader.PdfViewWrapper
         android:id="@+id/pdfview"
         android:layout_width="match_parent"
         android:layout_height="fill_parent"
-        android:layout_above="@id/button_prev"
         android:layout_alignParentTop="true" />
 
 </RelativeLayout>