blob: 0ffc3704bb80dc220cb9ffd42d578af70eb1c2c5 [file] [log] [blame]
/*
* Copyright (C) 2008-2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.gesture;
import android.graphics.Color;
import android.view.MotionEvent;
import android.view.View;
import java.util.ArrayList;
/**
* TouchThroughGesturing implements the interaction behavior that allows a user
* to gesture over a regular UI widget such as ListView and at the same time,
* still allows a user to perform basic interactions (clicking, scrolling and panning)
* with the underlying widget.
*/
public class TouchThroughGesturing implements GestureListener {
public static final int SINGLE_STROKE = 0;
public static final int MULTIPLE_STROKE = 1;
private static final float STROKE_LENGTH_THRESHOLD = 30;
private static final float SQUARENESS_THRESHOLD = 0.275f;
private static final float ANGLE_THRESHOLD = 40;
public static final int DEFAULT_UNCERTAIN_GESTURE_COLOR = Color.argb(60, 255, 255, 0);
private boolean mIsGesturing = false;
private float mTotalLength;
private float mX, mY;
private View mModel;
private int mGestureType = SINGLE_STROKE;
private int mUncertainGestureColor = DEFAULT_UNCERTAIN_GESTURE_COLOR;
private ArrayList<GestureActionListener> mActionListeners = new ArrayList<GestureActionListener>();
public TouchThroughGesturing(View model) {
mModel = model;
}
/**
*
* @param type SINGLE_STROKE or MULTIPLE_STROKE
*/
public void setGestureType(int type) {
mGestureType = type;
}
public void setUncertainGestureColor(int color) {
mUncertainGestureColor = color;
}
public void onStartGesture(GestureOverlay overlay, MotionEvent event) {
if (mGestureType == MULTIPLE_STROKE) {
overlay.cancelFadingOut();
}
mX = event.getX();
mY = event.getY();
mTotalLength = 0;
mIsGesturing = false;
if (mGestureType == SINGLE_STROKE || overlay.getCurrentGesture() == null
|| overlay.getCurrentGesture().getStrokesCount() == 0) {
overlay.setGestureColor(mUncertainGestureColor);
}
mModel.dispatchTouchEvent(event);
}
public void onGesture(GestureOverlay overlay, MotionEvent event) {
if (mIsGesturing) {
return;
}
float x = event.getX();
float y = event.getY();
float dx = x - mX;
float dy = y - mY;
mTotalLength += (float)Math.sqrt(dx * dx + dy * dy);
mX = x;
mY = y;
if (mTotalLength > STROKE_LENGTH_THRESHOLD) {
OrientedBoundingBox bbx = GestureUtils.computeOrientedBBX(overlay.getCurrentStroke());
float angle = Math.abs(bbx.orientation);
if (angle > 90) {
angle = 180 - angle;
}
if (bbx.squareness > SQUARENESS_THRESHOLD || angle < ANGLE_THRESHOLD) {
mIsGesturing = true;
overlay.setGestureColor(GestureOverlay.DEFAULT_GESTURE_COLOR);
event = MotionEvent.obtain(event.getDownTime(), System.currentTimeMillis(),
MotionEvent.ACTION_UP, x, y, event.getPressure(), event.getSize(), event
.getMetaState(), event.getXPrecision(), event.getYPrecision(),
event.getDeviceId(), event.getEdgeFlags());
}
}
mModel.dispatchTouchEvent(event);
}
public void onFinishGesture(GestureOverlay overlay, MotionEvent event) {
if (mIsGesturing) {
overlay.clear(true);
ArrayList<GestureActionListener> listeners = mActionListeners;
int count = listeners.size();
for (int i = 0; i < count; i++) {
GestureActionListener listener = listeners.get(i);
listener.onGesturePerformed(overlay, overlay.getCurrentGesture());
}
} else {
mModel.dispatchTouchEvent(event);
overlay.clear(false);
}
}
public void addGestureActionListener(GestureActionListener listener) {
mActionListeners.add(listener);
}
public void removeGestureActionListener(GestureActionListener listener) {
mActionListeners.remove(listener);
}
public boolean isGesturing() {
return mIsGesturing;
}
}