149b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong/* 249b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong * Copyright (C) 2013 The Android Open Source Project 349b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong * 449b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong * Licensed under the Apache License, Version 2.0 (the "License"); 549b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong * you may not use this file except in compliance with the License. 649b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong * You may obtain a copy of the License at 749b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong * 849b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong * http://www.apache.org/licenses/LICENSE-2.0 949b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong * 1049b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong * Unless required by applicable law or agreed to in writing, software 1149b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong * distributed under the License is distributed on an "AS IS" BASIS, 1249b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1349b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong * See the License for the specific language governing permissions and 1449b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong * limitations under the License. 1549b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong */ 1649b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong 1749b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kongpackage com.android.camera.ui; 1849b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong 1949b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kongimport android.content.Context; 2049b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kongimport android.view.GestureDetector; 2149b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kongimport android.view.MotionEvent; 2249b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kongimport android.view.ScaleGestureDetector; 2349b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong 242bca210e5fc8a77685775ffb403096167b017dceAngus Kongimport com.android.camera.debug.Log; 252bca210e5fc8a77685775ffb403096167b017dceAngus Kong 26121022cb590955e37f1264f77190ce4711159976Doris Liu// This class aggregates two gesture detectors: GestureDetector, 2749b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong// ScaleGestureDetector. 28166e36fb6e04d40a1bef0459ee6b96c9c736039bAngus Kongpublic class FilmstripGestureRecognizer { 2949b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong @SuppressWarnings("unused") 302bca210e5fc8a77685775ffb403096167b017dceAngus Kong private static final Log.Tag TAG = new Log.Tag("FStripGestureRecog"); 3149b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong 3249b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong public interface Listener { 3349b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong boolean onSingleTapUp(float x, float y); 3449b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong boolean onDoubleTap(float x, float y); 3549b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong boolean onScroll(float x, float y, float dx, float dy); 3649b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong boolean onFling(float velocityX, float velocityY); 3749b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong boolean onScaleBegin(float focusX, float focusY); 3849b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong boolean onScale(float focusX, float focusY, float scale); 3949b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong boolean onDown(float x, float y); 4087f9a62f473a3c57505e2877b0a46ab3cb5e62acAngus Kong boolean onUp(float x, float y); 4126795a9258c0815ca2a92d2c660438066f001022Angus Kong void onLongPress(float x, float y); 4249b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong void onScaleEnd(); 4349b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong } 4449b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong 4549b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong private final GestureDetector mGestureDetector; 4649b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong private final ScaleGestureDetector mScaleDetector; 4749b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong private final Listener mListener; 4849b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong 49166e36fb6e04d40a1bef0459ee6b96c9c736039bAngus Kong public FilmstripGestureRecognizer(Context context, Listener listener) { 5049b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong mListener = listener; 5149b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong mGestureDetector = new GestureDetector(context, new MyGestureListener(), 5249b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong null, true /* ignoreMultitouch */); 53121022cb590955e37f1264f77190ce4711159976Doris Liu mGestureDetector.setOnDoubleTapListener(new MyDoubleTapListener()); 5449b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong mScaleDetector = new ScaleGestureDetector( 5549b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong context, new MyScaleListener()); 5649b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong } 5749b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong 58166e36fb6e04d40a1bef0459ee6b96c9c736039bAngus Kong public boolean onTouchEvent(MotionEvent event) { 59166e36fb6e04d40a1bef0459ee6b96c9c736039bAngus Kong final boolean gestureProcessed = mGestureDetector.onTouchEvent(event); 60166e36fb6e04d40a1bef0459ee6b96c9c736039bAngus Kong final boolean scaleProcessed = mScaleDetector.onTouchEvent(event); 6187f9a62f473a3c57505e2877b0a46ab3cb5e62acAngus Kong if (event.getAction() == MotionEvent.ACTION_UP) { 6287f9a62f473a3c57505e2877b0a46ab3cb5e62acAngus Kong mListener.onUp(event.getX(), event.getY()); 6387f9a62f473a3c57505e2877b0a46ab3cb5e62acAngus Kong } 64166e36fb6e04d40a1bef0459ee6b96c9c736039bAngus Kong return (gestureProcessed | scaleProcessed); 6549b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong } 6649b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong 6749b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong private class MyGestureListener 6849b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong extends GestureDetector.SimpleOnGestureListener { 6949b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong @Override 7026795a9258c0815ca2a92d2c660438066f001022Angus Kong public void onLongPress(MotionEvent e) { 7126795a9258c0815ca2a92d2c660438066f001022Angus Kong mListener.onLongPress(e.getX(), e.getY()); 7226795a9258c0815ca2a92d2c660438066f001022Angus Kong } 7326795a9258c0815ca2a92d2c660438066f001022Angus Kong 7426795a9258c0815ca2a92d2c660438066f001022Angus Kong @Override 7549b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong public boolean onScroll( 7649b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong MotionEvent e1, MotionEvent e2, float dx, float dy) { 7749b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong return mListener.onScroll(e2.getX(), e2.getY(), dx, dy); 7849b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong } 7949b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong 8049b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong @Override 8149b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, 8249b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong float velocityY) { 8349b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong return mListener.onFling(velocityX, velocityY); 8449b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong } 8549b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong 8649b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong @Override 8749b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong public boolean onDown(MotionEvent e) { 8849b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong mListener.onDown(e.getX(), e.getY()); 8949b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong return super.onDown(e); 9049b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong } 9149b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong } 9249b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong 93121022cb590955e37f1264f77190ce4711159976Doris Liu /** 94121022cb590955e37f1264f77190ce4711159976Doris Liu * The listener that is used to notify when a double-tap or a confirmed 95121022cb590955e37f1264f77190ce4711159976Doris Liu * single-tap occur. 96121022cb590955e37f1264f77190ce4711159976Doris Liu */ 97121022cb590955e37f1264f77190ce4711159976Doris Liu private class MyDoubleTapListener implements GestureDetector.OnDoubleTapListener { 98121022cb590955e37f1264f77190ce4711159976Doris Liu 99121022cb590955e37f1264f77190ce4711159976Doris Liu @Override 100121022cb590955e37f1264f77190ce4711159976Doris Liu public boolean onSingleTapConfirmed(MotionEvent e) { 101121022cb590955e37f1264f77190ce4711159976Doris Liu return mListener.onSingleTapUp(e.getX(), e.getY()); 102121022cb590955e37f1264f77190ce4711159976Doris Liu } 103121022cb590955e37f1264f77190ce4711159976Doris Liu 104121022cb590955e37f1264f77190ce4711159976Doris Liu @Override 105121022cb590955e37f1264f77190ce4711159976Doris Liu public boolean onDoubleTap(MotionEvent e) { 106121022cb590955e37f1264f77190ce4711159976Doris Liu return mListener.onDoubleTap(e.getX(), e.getY()); 107121022cb590955e37f1264f77190ce4711159976Doris Liu } 108121022cb590955e37f1264f77190ce4711159976Doris Liu 109121022cb590955e37f1264f77190ce4711159976Doris Liu @Override 110121022cb590955e37f1264f77190ce4711159976Doris Liu public boolean onDoubleTapEvent(MotionEvent e) { 111121022cb590955e37f1264f77190ce4711159976Doris Liu return true; 112121022cb590955e37f1264f77190ce4711159976Doris Liu } 113121022cb590955e37f1264f77190ce4711159976Doris Liu } 114121022cb590955e37f1264f77190ce4711159976Doris Liu 11549b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong private class MyScaleListener 11649b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong extends ScaleGestureDetector.SimpleOnScaleGestureListener { 11749b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong @Override 11849b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong public boolean onScaleBegin(ScaleGestureDetector detector) { 11949b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong return mListener.onScaleBegin( 12049b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong detector.getFocusX(), detector.getFocusY()); 12149b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong } 12249b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong 12349b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong @Override 12449b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong public boolean onScale(ScaleGestureDetector detector) { 12549b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong return mListener.onScale(detector.getFocusX(), 12649b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong detector.getFocusY(), detector.getScaleFactor()); 12749b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong } 12849b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong 12949b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong @Override 13049b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong public void onScaleEnd(ScaleGestureDetector detector) { 13149b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong mListener.onScaleEnd(); 13249b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong } 13349b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong } 13449b9ba2ba89760f297ecc7d6d94d68fb4b836be1Angus Kong} 135