Skip to content
This repository was archived by the owner on Jan 7, 2023. It is now read-only.
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 122 additions & 0 deletions lib/src/main/java/com/soundcloud/android/crop/CropImageView.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.PointF;
import android.graphics.Rect;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.FloatMath;
import android.view.MotionEvent;

import java.util.ArrayList;
Expand All @@ -14,6 +17,26 @@ public class CropImageView extends ImageViewTouchBase {
HighlightView motionHighlightView;
Context context;

private static enum TouchState{
NONE,
SINGLE,
WAITING,
MULTI
};
private TouchState touchState = TouchState.NONE;
private Runnable enterSingleTouchHandler = new Runnable() {
@Override
public void run() {
touchState = TouchState.SINGLE;
onSingleTouchEvent(blockingEvent);
}
};

private MotionEvent blockingEvent;
private static final int waitingMillis = 70; // 30ms is enough in most case
private Handler mHandler = new Handler();
private static float oldFingerDis = 0f; // Finger's distance last zoom.

private float lastX;
private float lastY;
private int motionEdge;
Expand Down Expand Up @@ -91,6 +114,104 @@ public boolean onTouchEvent(MotionEvent event) {
return false;
}

// Dispatch event
boolean blockEvent = false;
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
// Fist touch point detected
// waiting for second point, or tiger singer touch event after a short period of time
touchState = TouchState.WAITING;
blockingEvent = MotionEvent.obtain(event);
blockEvent = true;
mHandler.postDelayed(enterSingleTouchHandler, waitingMillis);
break;
case MotionEvent.ACTION_POINTER_DOWN:
// Second or more touch point detected
// If is waiting, then it must be multi-touch event
if (touchState == TouchState.WAITING) {
mHandler.removeCallbacks(enterSingleTouchHandler);
touchState = TouchState.MULTI;
// Send blocking event now
onMultiTouchEvent(blockingEvent);
}
break;
case MotionEvent.ACTION_UP:
if (touchState == TouchState.WAITING) {
mHandler.removeCallbacks(enterSingleTouchHandler);
onSingleTouchEvent(blockingEvent);
touchState = TouchState.SINGLE;
}
break;
case MotionEvent.ACTION_MOVE:
if (touchState == TouchState.WAITING) {
blockEvent = true;
}
break;
}

if (!blockEvent) {
switch (touchState) {
case SINGLE:
return onSingleTouchEvent(event);
case MULTI:
return onMultiTouchEvent(event);
}
}

if (event.getAction() == MotionEvent.ACTION_UP) {
touchState = TouchState.NONE;
}
return true;
}

private static float getTwoFingerDis(MotionEvent event) {
float x = (event.getX(0) - event.getX(1));
float y = (event.getY(0) - event.getY(1));
return FloatMath.sqrt(x * x + y * y);
}

private static PointF getTwoFingerMiddle(MotionEvent event) {
if (event.getPointerCount() < 2) {
return new PointF(event.getX(), event.getY());
}

float x = (event.getX(0) + event.getX(1)) / 2f;
float y = (event.getY(0) + event.getY(1)) / 2f;
return new PointF(x, y);
}

private boolean onMultiTouchEvent(MotionEvent event) {
if (event.getPointerCount() < 2) {
return true;
}
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_POINTER_DOWN:
oldFingerDis = getTwoFingerDis(event);
break;
case MotionEvent.ACTION_MOVE:
tryZoom(event);
break;

}
return true;
}

private boolean tryZoom(MotionEvent event) {
float curD = getTwoFingerDis(event);
PointF curM = getTwoFingerMiddle(event);

float shake = 5.0f;
if (Math.abs(curD - oldFingerDis) > shake) {
float scale = curD / oldFingerDis;
zoomTo(getScale() * scale, curM.x, curM.y);
oldFingerDis = curD;
return true;
} else {
return false;
}
}

private boolean onSingleTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
for (HighlightView hv : highlightViews) {
Expand Down Expand Up @@ -134,6 +255,7 @@ public boolean onTouchEvent(MotionEvent event) {
// the user to move the image around. This call to center puts
// it back to the normalized location (with false meaning don't
// animate).
// Now it can zoom :)
if (getScale() == 1F) {
center(true, true);
}
Expand Down