/MusicLockTutorial/src/com/google/marvin/widget/GestureOverlay.java
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}