/*
* Copyright (C) 2016 stfalcon.com
*
* 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.stfalcon.frescoimageviewer;
import android.content.Context;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
/*
* Created by Alexander Krol (troy379) on 29.08.16.
*/
abstract class SwipeDirectionDetector {
public abstract void onDirectionDetected(Direction direction);
private int touchSlop;
private float startX, startY;
private boolean isDetected;
public SwipeDirectionDetector(Context context) {
this.touchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
}
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
startX = event.getX();
startY = event.getY();
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
if (!isDetected) {
onDirectionDetected(Direction.NOT_DETECTED);
}
startX = startY = 0.0f;
isDetected = false;
break;
case MotionEvent.ACTION_MOVE:
if (!isDetected && getDistance(event) > touchSlop) {
isDetected = true;
float x = event.getX();
float y = event.getY();
Direction direction = getDirection(startX, startY, x, y);
onDirectionDetected(direction);
}
break;
}
return false;
}
/**
* Given two points in the plane p1=(x1, x2) and p2=(y1, y1), this method
* returns the direction that an arrow pointing from p1 to p2 would have.
*
* @param x1 the x position of the first point
* @param y1 the y position of the first point
* @param x2 the x position of the second point
* @param y2 the y position of the second point
* @return the direction
*/
public Direction getDirection(float x1, float y1, float x2, float y2) {
double angle = getAngle(x1, y1, x2, y2);
return Direction.get(angle);
}
/**
* Finds the angle between two points in the plane (x1,y1) and (x2, y2)
* The angle is measured with 0/360 being the X-axis to the right, angles
* increase counter clockwise.
*
* @param x1 the x position of the first point
* @param y1 the y position of the first point
* @param x2 the x position of the second point
* @param y2 the y position of the second point
* @return the angle between two points
*/
public double getAngle(float x1, float y1, float x2, float y2) {
double rad = Math.atan2(y1 - y2, x2 - x1) + Math.PI;
return (rad * 180 / Math.PI + 180) % 360;
}
private float getDistance(MotionEvent ev) {
float distanceSum = 0;
float dx = (ev.getX(0) - startX);
float dy = (ev.getY(0) - startY);
distanceSum += Math.sqrt(dx * dx + dy * dy);
return distanceSum;
}
public enum Direction {
NOT_DETECTED,
UP,
DOWN,
LEFT,
RIGHT;
public static Direction get(double angle) {
if (inRange(angle, 45, 135)) {
return Direction.UP;
} else if (inRange(angle, 0, 45) || inRange(angle, 315, 360)) {
return Direction.RIGHT;
} else if (inRange(angle, 225, 315)) {
return Direction.DOWN;
} else {
return Direction.LEFT;
}
}
private static boolean inRange(double angle, float init, float end) {
return (angle >= init) && (angle < end);
}
}
}