13a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang/* 23a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang * Copyright (C) 2012 The Android Open Source Project 33a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang * 43a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang * Licensed under the Apache License, Version 2.0 (the "License"); 53a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang * you may not use this file except in compliance with the License. 63a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang * You may obtain a copy of the License at 73a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang * 83a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang * http://www.apache.org/licenses/LICENSE-2.0 93a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang * 103a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang * Unless required by applicable law or agreed to in writing, software 113a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang * distributed under the License is distributed on an "AS IS" BASIS, 123a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang * See the License for the specific language governing permissions and 143a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang * limitations under the License. 153a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang */ 163a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang 173a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Changpackage com.android.gallery3d.ui; 183a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang 193a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Changimport android.content.Context; 20534b12fd804610dd67b8109bc08ba76f31afb33eChih-Chung Changimport android.os.SystemClock; 213a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Changimport android.view.GestureDetector; 223a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Changimport android.view.MotionEvent; 233a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Changimport android.view.ScaleGestureDetector; 243a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang 253a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang// This class aggregates three gesture detectors: GestureDetector, 263a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang// ScaleGestureDetector, and DownUpDetector. 273a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Changpublic class GestureRecognizer { 287817979db0c52ffeacb951625b1e821eba303285Ahbong Chang @SuppressWarnings("unused") 293a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang private static final String TAG = "GestureRecognizer"; 303a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang 313a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang public interface Listener { 323a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang boolean onSingleTapUp(float x, float y); 333a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang boolean onDoubleTap(float x, float y); 346b891c6a3739f8c49d42f9db6fc76cb92c7c5f25Chih-Chung Chang boolean onScroll(float dx, float dy, float totalX, float totalY); 35137c6d060f9710f1a460326f27459e89b49820c2Bobby Georgescu boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY); 363a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang boolean onScaleBegin(float focusX, float focusY); 373a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang boolean onScale(float focusX, float focusY, float scale); 383a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang void onScaleEnd(); 396b891c6a3739f8c49d42f9db6fc76cb92c7c5f25Chih-Chung Chang void onDown(float x, float y); 403a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang void onUp(); 413a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang } 423a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang 433a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang private final GestureDetector mGestureDetector; 443a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang private final ScaleGestureDetector mScaleDetector; 453a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang private final DownUpDetector mDownUpDetector; 463a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang private final Listener mListener; 473a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang 483a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang public GestureRecognizer(Context context, Listener listener) { 493a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang mListener = listener; 503a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang mGestureDetector = new GestureDetector(context, new MyGestureListener(), 513a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang null, true /* ignoreMultitouch */); 523a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang mScaleDetector = new ScaleGestureDetector( 533a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang context, new MyScaleListener()); 543a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang mDownUpDetector = new DownUpDetector(new MyDownUpListener()); 553a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang } 563a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang 573a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang public void onTouchEvent(MotionEvent event) { 583a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang mGestureDetector.onTouchEvent(event); 593a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang mScaleDetector.onTouchEvent(event); 603a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang mDownUpDetector.onTouchEvent(event); 613a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang } 623a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang 633a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang public boolean isDown() { 643a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang return mDownUpDetector.isDown(); 653a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang } 663a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang 67534b12fd804610dd67b8109bc08ba76f31afb33eChih-Chung Chang public void cancelScale() { 68534b12fd804610dd67b8109bc08ba76f31afb33eChih-Chung Chang long now = SystemClock.uptimeMillis(); 69534b12fd804610dd67b8109bc08ba76f31afb33eChih-Chung Chang MotionEvent cancelEvent = MotionEvent.obtain( 70534b12fd804610dd67b8109bc08ba76f31afb33eChih-Chung Chang now, now, MotionEvent.ACTION_CANCEL, 0, 0, 0); 71534b12fd804610dd67b8109bc08ba76f31afb33eChih-Chung Chang mScaleDetector.onTouchEvent(cancelEvent); 72534b12fd804610dd67b8109bc08ba76f31afb33eChih-Chung Chang cancelEvent.recycle(); 73534b12fd804610dd67b8109bc08ba76f31afb33eChih-Chung Chang } 74534b12fd804610dd67b8109bc08ba76f31afb33eChih-Chung Chang 753a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang private class MyGestureListener 763a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang extends GestureDetector.SimpleOnGestureListener { 773a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang @Override 783a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang public boolean onSingleTapUp(MotionEvent e) { 793a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang return mListener.onSingleTapUp(e.getX(), e.getY()); 803a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang } 813a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang 823a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang @Override 833a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang public boolean onDoubleTap(MotionEvent e) { 843a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang return mListener.onDoubleTap(e.getX(), e.getY()); 853a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang } 863a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang 873a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang @Override 883a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang public boolean onScroll( 893a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang MotionEvent e1, MotionEvent e2, float dx, float dy) { 906b891c6a3739f8c49d42f9db6fc76cb92c7c5f25Chih-Chung Chang return mListener.onScroll( 916b891c6a3739f8c49d42f9db6fc76cb92c7c5f25Chih-Chung Chang dx, dy, e2.getX() - e1.getX(), e2.getY() - e1.getY()); 923a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang } 933a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang 943a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang @Override 953a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, 963a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang float velocityY) { 97137c6d060f9710f1a460326f27459e89b49820c2Bobby Georgescu return mListener.onFling(e1, e2, velocityX, velocityY); 983a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang } 993a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang } 1003a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang 1013a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang private class MyScaleListener 1023a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang extends ScaleGestureDetector.SimpleOnScaleGestureListener { 1033a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang @Override 1043a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang public boolean onScaleBegin(ScaleGestureDetector detector) { 1053a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang return mListener.onScaleBegin( 1063a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang detector.getFocusX(), detector.getFocusY()); 1073a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang } 1083a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang 1093a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang @Override 1103a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang public boolean onScale(ScaleGestureDetector detector) { 1113a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang return mListener.onScale(detector.getFocusX(), 1123a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang detector.getFocusY(), detector.getScaleFactor()); 1133a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang } 1143a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang 1153a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang @Override 1163a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang public void onScaleEnd(ScaleGestureDetector detector) { 1173a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang mListener.onScaleEnd(); 1183a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang } 1193a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang } 1203a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang 1213a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang private class MyDownUpListener implements DownUpDetector.DownUpListener { 1223a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang @Override 1233a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang public void onDown(MotionEvent e) { 1246b891c6a3739f8c49d42f9db6fc76cb92c7c5f25Chih-Chung Chang mListener.onDown(e.getX(), e.getY()); 1253a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang } 1263a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang 1273a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang @Override 1283a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang public void onUp(MotionEvent e) { 1293a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang mListener.onUp(); 1303a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang } 1313a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang } 1323a02809c97669a157cf45bfd61d45272110d4091Chih-Chung Chang} 133