PageRenderTime 13ms CodeModel.GetById 2ms app.highlight 8ms RepoModel.GetById 1ms app.codeStats 0ms

/MusicLockTutorial/src/com/google/marvin/widget/GestureOverlay.java

http://eyes-free.googlecode.com/
Java | 183 lines | 117 code | 39 blank | 27 comment | 30 complexity | 75633b1b9f7e456cb2c80a5a33538d62 MD5 | raw file
  1/*
  2 * Copyright (C) 2010 Google Inc.
  3 * 
  4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  5 * use this file except in compliance with the License. You may obtain a copy of
  6 * the License at
  7 * 
  8 * http://www.apache.org/licenses/LICENSE-2.0
  9 * 
 10 * Unless required by applicable law or agreed to in writing, software
 11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 13 * License for the specific language governing permissions and limitations under
 14 * the License.
 15 */
 16
 17package com.google.marvin.widget;
 18
 19import android.content.Context;
 20import android.view.MotionEvent;
 21import android.view.View;
 22
 23/**
 24 * A transparent overlay which catches all touch events and uses a call back to
 25 * return the gesture that the user performed.
 26 * 
 27 * @author clchen@google.com (Charles L. Chen)
 28 */
 29
 30public class GestureOverlay extends View {
 31    public static class Gesture {
 32        public static final int UPLEFT = 1;
 33
 34        public static final int UP = 2;
 35
 36        public static final int UPRIGHT = 3;
 37
 38        public static final int LEFT = 4;
 39
 40        public static final int CENTER = 5;
 41
 42        public static final int RIGHT = 6;
 43
 44        public static final int DOWNLEFT = 7;
 45
 46        public static final int DOWN = 8;
 47
 48        public static final int DOWNRIGHT = 9;
 49    }
 50
 51    /**
 52     * The callback interface to be used when a gesture is detected.
 53     */
 54    public interface GestureListener {
 55        public void onGestureStart(int g);
 56
 57        public void onGestureChange(int g);
 58
 59        public void onGestureFinish(int g);
 60    }
 61
 62    private final double left = 0;
 63
 64    private final double upleft = Math.PI * .25;
 65
 66    private final double up = Math.PI * .5;
 67
 68    private final double upright = Math.PI * .75;
 69
 70    private final double downright = -Math.PI * .75;
 71
 72    private final double down = -Math.PI * .5;
 73
 74    private final double downleft = -Math.PI * .25;
 75
 76    private final double right = Math.PI;
 77
 78    private final double rightWrap = -Math.PI;
 79
 80    private GestureListener cb = null;
 81
 82    private double downX;
 83
 84    private double downY;
 85
 86    private int currentGesture;
 87
 88    private int radiusThreshold = 30;
 89
 90    public GestureOverlay(Context context, GestureListener callback) {
 91        super(context);
 92        cb = callback;
 93    }
 94
 95    public GestureOverlay(Context context) {
 96        super(context);
 97    }
 98
 99    public void setGestureListener(GestureListener callback) {
100        cb = callback;
101    }
102
103    public void setMinimumRadius(int minRadius) {
104        radiusThreshold = minRadius;
105    }
106
107    @Override
108    public boolean onTouchEvent(MotionEvent event) {
109        int action = event.getAction();
110        float x = event.getX();
111        float y = event.getY();
112        int prevGesture = -1;
113        switch (action) {
114            case MotionEvent.ACTION_DOWN:
115                downX = x;
116                downY = y;
117                currentGesture = Gesture.CENTER;
118                if (cb != null) {
119                    cb.onGestureStart(currentGesture);
120                }
121                break;
122            case MotionEvent.ACTION_UP:
123                prevGesture = currentGesture;
124                currentGesture = evalMotion(x, y);
125                // Do some correction if the user lifts up on deadspace
126                if (currentGesture == -1) {
127                    currentGesture = prevGesture;
128                }
129                if (cb != null) {
130                    cb.onGestureFinish(currentGesture);
131                }
132                break;
133            default:
134                prevGesture = currentGesture;
135                currentGesture = evalMotion(x, y);
136                // Do some correction if the user lifts up on deadspace
137                if (currentGesture == -1) {
138                    currentGesture = prevGesture;
139                    break;
140                }
141                if (prevGesture != currentGesture) {
142                    if (cb != null) {
143                        cb.onGestureChange(currentGesture);
144                    }
145                }
146                break;
147        }
148        return true;
149    }
150
151    public int evalMotion(double x, double y) {
152        float rTolerance = radiusThreshold;
153        double thetaTolerance = (Math.PI / 12);
154
155        double r = Math.sqrt(((downX - x) * (downX - x)) + ((downY - y) * (downY - y)));
156
157        if (r < rTolerance) {
158            return Gesture.CENTER;
159        }
160
161        double theta = Math.atan2(downY - y, downX - x);
162        if (Math.abs(theta - left) < thetaTolerance) {
163            return Gesture.LEFT;
164        } else if (Math.abs(theta - upleft) < thetaTolerance) {
165            return Gesture.UPLEFT;
166        } else if (Math.abs(theta - up) < thetaTolerance) {
167            return Gesture.UP;
168        } else if (Math.abs(theta - upright) < thetaTolerance) {
169            return Gesture.UPRIGHT;
170        } else if (Math.abs(theta - downright) < thetaTolerance) {
171            return Gesture.DOWNRIGHT;
172        } else if (Math.abs(theta - down) < thetaTolerance) {
173            return Gesture.DOWN;
174        } else if (Math.abs(theta - downleft) < thetaTolerance) {
175            return Gesture.DOWNLEFT;
176        } else if ((theta > right - thetaTolerance) || (theta < rightWrap + thetaTolerance)) {
177            return Gesture.RIGHT;
178        }
179        // Off by more than the threshold, so it doesn't count
180        return -1;
181    }
182
183}