Advertisement
Guest User

Untitled

a guest
Jul 12th, 2012
276
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.97 KB | None | 0 0
  1. package co.sts.combinationlock;
  2.  
  3. import android.os.Bundle;
  4. import android.app.Activity;
  5. import android.graphics.Bitmap;
  6. import android.graphics.BitmapFactory;
  7. import android.graphics.Matrix;
  8. import android.util.Log;
  9. import android.view.GestureDetector;
  10. import android.view.Menu;
  11. import android.view.MenuItem;
  12. import android.view.MotionEvent;
  13. import android.view.View;
  14. import android.view.GestureDetector.SimpleOnGestureListener;
  15. import android.view.View.OnTouchListener;
  16. import android.view.ViewTreeObserver.OnGlobalLayoutListener;
  17. import android.widget.ImageView;
  18. import android.support.v4.app.NavUtils;
  19.  
  20. public class ComboLock extends Activity{
  21.  
  22. private static Bitmap imageOriginal, imageScaled;
  23. private static Matrix matrix;
  24.  
  25. private ImageView dialer;
  26. private int dialerHeight, dialerWidth;
  27.  
  28. private GestureDetector detector;
  29.  
  30. // needed for detecting the inversed rotations
  31. private boolean[] quadrantTouched;
  32.  
  33. private boolean allowRotating;
  34.  
  35. @Override
  36. public void onCreate(Bundle savedInstanceState) {
  37. super.onCreate(savedInstanceState);
  38. setContentView(R.layout.activity_combo_lock);
  39.  
  40. // load the image only once
  41. if (imageOriginal == null) {
  42. imageOriginal = BitmapFactory.decodeResource(getResources(), R.drawable.numbers);
  43. }
  44.  
  45. // initialize the matrix only once
  46. if (matrix == null) {
  47. matrix = new Matrix();
  48. } else {
  49. // not needed, you can also post the matrix immediately to restore the old state
  50. matrix.reset();
  51. }
  52.  
  53. detector = new GestureDetector(this, new MyGestureDetector());
  54.  
  55. // there is no 0th quadrant, to keep it simple the first value gets ignored
  56. quadrantTouched = new boolean[] { false, false, false, false, false };
  57.  
  58. allowRotating = true;
  59.  
  60. dialer = (ImageView) findViewById(R.id.locknumbers);
  61. dialer.setOnTouchListener(new MyOnTouchListener());
  62. dialer.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
  63.  
  64. @Override
  65. public void onGlobalLayout() {
  66. // method called more than once, but the values only need to be initialized one time
  67. if (dialerHeight == 0 || dialerWidth == 0) {
  68. dialerHeight = dialer.getHeight();
  69. dialerWidth = dialer.getWidth();
  70.  
  71. // resize
  72. Matrix resize = new Matrix();
  73. //resize.postScale((float)Math.min(dialerWidth, dialerHeight) / (float)imageOriginal.getWidth(), (float)Math.min(dialerWidth, dialerHeight) / (float)imageOriginal.getHeight());
  74. imageScaled = Bitmap.createBitmap(imageOriginal, 0, 0, imageOriginal.getWidth(), imageOriginal.getHeight(), resize, false);
  75.  
  76. // translate to the image view's center
  77. float translateX = dialerWidth / 2 - imageScaled.getWidth() / 2;
  78. float translateY = dialerHeight / 2 - imageScaled.getHeight() / 2;
  79. matrix.postTranslate(translateX, translateY);
  80.  
  81. dialer.setImageBitmap(imageScaled);
  82. dialer.setImageMatrix(matrix);
  83. }
  84. }
  85. });
  86.  
  87. }
  88.  
  89. /**
  90. * Rotate the dialer.
  91. *
  92. * @param degrees The degrees, the dialer should get rotated.
  93. */
  94. private void rotateDialer(float degrees) {
  95. matrix.postRotate(degrees, dialerWidth / 2, dialerHeight / 2);
  96.  
  97. //need to print degrees
  98.  
  99. dialer.setImageMatrix(matrix);
  100. }
  101.  
  102. /**
  103. * @return The angle of the unit circle with the image view's center
  104. */
  105. private double getAngle(double xTouch, double yTouch) {
  106. double x = xTouch - (dialerWidth / 2d);
  107. double y = dialerHeight - yTouch - (dialerHeight / 2d);
  108.  
  109. switch (getQuadrant(x, y)) {
  110. case 1:
  111. return Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI;
  112.  
  113. case 2:
  114. case 3:
  115. return 180 - (Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI);
  116.  
  117. case 4:
  118. return 360 + Math.asin(y / Math.hypot(x, y)) * 180 / Math.PI;
  119.  
  120. default:
  121. // ignore, does not happen
  122. return 0;
  123. }
  124. }
  125.  
  126. /**
  127. * @return The selected quadrant.
  128. */
  129. private static int getQuadrant(double x, double y) {
  130. if (x >= 0) {
  131. return y >= 0 ? 1 : 4;
  132. } else {
  133. return y >= 0 ? 2 : 3;
  134. }
  135. }
  136.  
  137. /**
  138. * Simple implementation of an {@link OnTouchListener} for registering the dialer's touch events.
  139. */
  140. private class MyOnTouchListener implements OnTouchListener {
  141.  
  142. private double startAngle;
  143.  
  144. @Override
  145. public boolean onTouch(View v, MotionEvent event) {
  146.  
  147. switch (event.getAction()) {
  148.  
  149. case MotionEvent.ACTION_DOWN:
  150.  
  151. // reset the touched quadrants
  152. for (int i = 0; i < quadrantTouched.length; i++) {
  153. quadrantTouched[i] = false;
  154. }
  155.  
  156. allowRotating = false;
  157.  
  158. startAngle = getAngle(event.getX(), event.getY());
  159. break;
  160.  
  161. case MotionEvent.ACTION_MOVE:
  162. double currentAngle = getAngle(event.getX(), event.getY());
  163. rotateDialer((float) (startAngle - currentAngle));
  164. startAngle = currentAngle;
  165. break;
  166.  
  167. case MotionEvent.ACTION_UP:
  168. allowRotating = true;
  169. break;
  170. }
  171.  
  172. // set the touched quadrant to true
  173. quadrantTouched[getQuadrant(event.getX() - (dialerWidth / 2), dialerHeight - event.getY() - (dialerHeight / 2))] = true;
  174.  
  175. detector.onTouchEvent(event);
  176.  
  177. return true;
  178. }
  179. }
  180.  
  181. /**
  182. * Simple implementation of a {@link SimpleOnGestureListener} for detecting a fling event.
  183. */
  184. private class MyGestureDetector extends SimpleOnGestureListener {
  185. @Override
  186. public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
  187.  
  188. // get the quadrant of the start and the end of the fling
  189. int q1 = getQuadrant(e1.getX() - (dialerWidth / 2), dialerHeight - e1.getY() - (dialerHeight / 2));
  190. int q2 = getQuadrant(e2.getX() - (dialerWidth / 2), dialerHeight - e2.getY() - (dialerHeight / 2));
  191.  
  192. // the inversed rotations
  193. if ((q1 == 2 && q2 == 2 && Math.abs(velocityX) < Math.abs(velocityY))
  194. || (q1 == 3 && q2 == 3)
  195. || (q1 == 1 && q2 == 3)
  196. || (q1 == 4 && q2 == 4 && Math.abs(velocityX) > Math.abs(velocityY))
  197. || ((q1 == 2 && q2 == 3) || (q1 == 3 && q2 == 2))
  198. || ((q1 == 3 && q2 == 4) || (q1 == 4 && q2 == 3))
  199. || (q1 == 2 && q2 == 4 && quadrantTouched[3])
  200. || (q1 == 4 && q2 == 2 && quadrantTouched[3])) {
  201.  
  202. dialer.post(new FlingRunnable(-1 * (velocityX + velocityY)));
  203. } else {
  204. // the normal rotation
  205. dialer.post(new FlingRunnable(velocityX + velocityY));
  206. }
  207.  
  208. return true;
  209. }
  210. }
  211.  
  212. /**
  213. * A {@link Runnable} for animating the the dialer's fling.
  214. */
  215. private class FlingRunnable implements Runnable {
  216.  
  217. private float velocity;
  218.  
  219. public FlingRunnable(float velocity) {
  220. this.velocity = velocity;
  221. }
  222.  
  223. @Override
  224. public void run() {
  225. if (Math.abs(velocity) > 5 && allowRotating) {
  226. //rotateDialer(velocity / 75);
  227. //velocity /= 1.0666F;
  228.  
  229. // post this instance again
  230. dialer.post(this);
  231. }
  232. }
  233. }
  234. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement