Use GestureDetector to handle touch events
This commit is contained in:
parent
b8496ffe5e
commit
712bff8459
1 changed files with 108 additions and 126 deletions
|
@ -1,5 +1,6 @@
|
|||
package btools.routingapp;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.res.AssetManager;
|
||||
import android.graphics.Bitmap;
|
||||
|
@ -9,7 +10,9 @@ import android.graphics.Color;
|
|||
import android.graphics.Matrix;
|
||||
import android.graphics.Paint;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.GestureDetector;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.ScaleGestureDetector;
|
||||
import android.view.View;
|
||||
|
||||
import java.io.File;
|
||||
|
@ -24,25 +27,25 @@ public class BInstallerView extends View {
|
|||
public static final int MASK_DELETED_RD5 = 2;
|
||||
public static final int MASK_INSTALLED_RD5 = 4;
|
||||
public static final int MASK_CURRENT_RD5 = 8;
|
||||
private static final float SCALE_GRID_VISIBLE = 3;
|
||||
private final Bitmap bmp;
|
||||
private final float[] testVector = new float[2];
|
||||
private final int[] tileStatus;
|
||||
private final File segmentDir;
|
||||
private final Matrix mat;
|
||||
private final Bitmap bmp;
|
||||
private final int[] tileStatus;
|
||||
private final float[] testVector = new float[2];
|
||||
private final Matrix matText;
|
||||
private final GestureDetector mGestureDetector;
|
||||
private final ScaleGestureDetector mScaleGestureDetector;
|
||||
Paint pnt_1 = new Paint();
|
||||
Paint pnt_2 = new Paint();
|
||||
Paint paint = new Paint();
|
||||
int btnh = 40;
|
||||
int btnw = 160;
|
||||
float tx, ty;
|
||||
private int imgwOrig;
|
||||
private int imghOrig;
|
||||
private float scaleOrig;
|
||||
private int imgw;
|
||||
private int imgh;
|
||||
private float lastDownX;
|
||||
private float lastDownY;
|
||||
private float viewscale;
|
||||
private boolean tilesVisible = false;
|
||||
private long availableSize;
|
||||
|
@ -69,6 +72,21 @@ public class BInstallerView extends View {
|
|||
tileStatus = new int[72 * 36];
|
||||
matText = new Matrix();
|
||||
mat = new Matrix();
|
||||
mGestureDetector = new GestureDetector(context, new GestureListener());
|
||||
mScaleGestureDetector = new ScaleGestureDetector(context, new ScaleGestureListener());
|
||||
}
|
||||
|
||||
private void setRatio(float ratio, float focusX, float focusY) {
|
||||
mat.postScale(ratio, ratio, focusX, focusY);
|
||||
fitBounds();
|
||||
tilesVisible = currentScale() >= SCALE_GRID_VISIBLE;
|
||||
|
||||
invalidate();
|
||||
}
|
||||
|
||||
private void setScale(float scale, float focusX, float focusY) {
|
||||
float ratio = scale / currentScale();
|
||||
setRatio(ratio, focusX, focusY);
|
||||
}
|
||||
|
||||
public void setAvailableSize(long availableSize) {
|
||||
|
@ -142,9 +160,9 @@ public class BInstallerView extends View {
|
|||
imgh = (int) (imghOrig / scaleOrig);
|
||||
|
||||
float scaleX = imgwOrig / ((float) bmp.getWidth());
|
||||
float scaley = imghOrig / ((float) bmp.getHeight());
|
||||
float scaleY = imghOrig / ((float) bmp.getHeight());
|
||||
|
||||
viewscale = Math.min(scaleX, scaley);
|
||||
viewscale = Math.min(scaleX, scaleY);
|
||||
|
||||
mat.postScale(viewscale, viewscale);
|
||||
tilesVisible = false;
|
||||
|
@ -260,120 +278,55 @@ public class BInstallerView extends View {
|
|||
}
|
||||
}
|
||||
|
||||
private void fitBounds() {
|
||||
float[] srcPoints = new float[]{
|
||||
0, 0,
|
||||
bmp.getWidth(), bmp.getHeight()
|
||||
};
|
||||
float[] dstPoints = new float[srcPoints.length];
|
||||
float transX = 0;
|
||||
float transY = 0;
|
||||
mat.mapPoints(dstPoints, srcPoints);
|
||||
if (dstPoints[0] > 0) {
|
||||
transX = -dstPoints[0];
|
||||
} else if (dstPoints[2] < getWidth()) {
|
||||
transX = getWidth() - dstPoints[2];
|
||||
}
|
||||
if (dstPoints[1] > 0) {
|
||||
transY = -dstPoints[1];
|
||||
} else if (dstPoints[3] < getHeight()) {
|
||||
transY = getHeight() - dstPoints[3];
|
||||
}
|
||||
if (transX != 0 || transY != 0) {
|
||||
mat.postTranslate(transX, transY);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent event) {
|
||||
boolean retVal = mScaleGestureDetector.onTouchEvent(event);
|
||||
retVal = mGestureDetector.onTouchEvent(event) || retVal;
|
||||
return retVal || super.onTouchEvent(event);
|
||||
}
|
||||
|
||||
// get masked (not specific to a pointer) action
|
||||
int maskedAction = event.getActionMasked();
|
||||
class GestureListener extends GestureDetector.SimpleOnGestureListener {
|
||||
|
||||
switch (maskedAction) {
|
||||
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
case MotionEvent.ACTION_POINTER_DOWN: {
|
||||
lastDownX = event.getX();
|
||||
lastDownY = event.getY();
|
||||
|
||||
break;
|
||||
@Override
|
||||
public boolean onSingleTapConfirmed(MotionEvent e) {
|
||||
// Download Button
|
||||
if ((delTiles > 0 || rd5Tiles >= 0) && e.getX() > imgwOrig - btnw * scaleOrig && e.getY() > imghOrig - btnh * scaleOrig) {
|
||||
if (mOnClickListener != null) {
|
||||
mOnClickListener.onClick(null);
|
||||
}
|
||||
invalidate();
|
||||
return true;
|
||||
}
|
||||
case MotionEvent.ACTION_MOVE: { // a pointer was moved
|
||||
|
||||
int np = event.getPointerCount();
|
||||
int nh = event.getHistorySize();
|
||||
if (nh == 0) break;
|
||||
|
||||
float x0 = event.getX(0);
|
||||
float y0 = event.getY(0);
|
||||
float hx0 = event.getHistoricalX(0, 0);
|
||||
float hy0 = event.getHistoricalY(0, 0);
|
||||
|
||||
if (np > 1) // multi-touch
|
||||
{
|
||||
float x1 = event.getX(1);
|
||||
float y1 = event.getY(1);
|
||||
float hx1 = event.getHistoricalX(1, 0);
|
||||
float hy1 = event.getHistoricalY(1, 0);
|
||||
|
||||
float r = (float) Math.sqrt((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0));
|
||||
float hr = (float) Math.sqrt((hx1 - hx0) * (hx1 - hx0) + (hy1 - hy0) * (hy1 - hy0));
|
||||
|
||||
if (hr > 0.) {
|
||||
float ratio = r / hr;
|
||||
|
||||
float mx = (x1 + x0) / 2.f;
|
||||
float my = (y1 + y0) / 2.f;
|
||||
|
||||
float scale = currentScale();
|
||||
float newscale = scale * ratio;
|
||||
|
||||
if (newscale > 10.f) ratio *= (10.f / newscale);
|
||||
if (newscale < 0.5f) ratio *= (0.5f / newscale);
|
||||
|
||||
mat.postScale(ratio, ratio, mx, my);
|
||||
|
||||
mat.postScale(ratio, ratio, mx, my);
|
||||
|
||||
boolean tilesv = currentScale() >= 3.f;
|
||||
if (tilesVisible && !tilesv) {
|
||||
clearAllTilesStatus(MASK_SELECTED_RD5 | MASK_DELETED_RD5);
|
||||
}
|
||||
tilesVisible = tilesv;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
mat.postTranslate(x0 - hx0, y0 - hy0);
|
||||
|
||||
break;
|
||||
}
|
||||
case MotionEvent.ACTION_UP:
|
||||
|
||||
long downTime = event.getEventTime() - event.getDownTime();
|
||||
|
||||
if (downTime < 5 || downTime > 500) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (Math.abs(lastDownX - event.getX()) > 10 || Math.abs(lastDownY - event.getY()) > 10) {
|
||||
break;
|
||||
}
|
||||
|
||||
// download button?
|
||||
if ((delTiles > 0 || rd5Tiles >= 0) && event.getX() > imgwOrig - btnw * scaleOrig && event.getY() > imghOrig - btnh * scaleOrig) {
|
||||
if (rd5Tiles == 0) {
|
||||
for (int ix = 0; ix < 72; ix++) {
|
||||
for (int iy = 0; iy < 36; iy++) {
|
||||
int tidx = gridPos2Tileindex(ix, iy);
|
||||
if (tidx != -1) {
|
||||
if ((tileStatus[tidx] & MASK_INSTALLED_RD5) != 0) {
|
||||
tileStatus[tidx] |= MASK_SELECTED_RD5;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mOnClickListener != null) {
|
||||
mOnClickListener.onClick(null);
|
||||
}
|
||||
invalidate();
|
||||
break;
|
||||
}
|
||||
|
||||
if (!tilesVisible) {
|
||||
float scale = currentScale();
|
||||
if (scale > 0f && scale < 5f) {
|
||||
float ratio = 5f / scale;
|
||||
mat.postScale(ratio, ratio, event.getX(), event.getY());
|
||||
tilesVisible = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (tilesVisible) {
|
||||
Matrix imat = new Matrix();
|
||||
if (mat.invert(imat)) {
|
||||
float[] touchpoint = new float[2];
|
||||
touchpoint[0] = event.getX();
|
||||
touchpoint[1] = event.getY();
|
||||
float[] touchpoint = {e.getX(), e.getY()};
|
||||
imat.mapPoints(touchpoint);
|
||||
|
||||
int tidx = tileIndex(touchpoint[0], touchpoint[1]);
|
||||
|
@ -389,23 +342,52 @@ public class BInstallerView extends View {
|
|||
tileStatus[tidx] ^= MASK_SELECTED_RD5;
|
||||
}
|
||||
}
|
||||
|
||||
tx = touchpoint[0];
|
||||
ty = touchpoint[1];
|
||||
}
|
||||
|
||||
|
||||
break;
|
||||
case MotionEvent.ACTION_POINTER_UP:
|
||||
case MotionEvent.ACTION_CANCEL: {
|
||||
// TODO use data
|
||||
break;
|
||||
invalidate();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
invalidate();
|
||||
|
||||
return true;
|
||||
@Override
|
||||
public boolean onDoubleTap(MotionEvent e) {
|
||||
if (!tilesVisible) {
|
||||
setScale(5, e.getX(), e.getY());
|
||||
} else {
|
||||
setScale(1, e.getX(), e.getY());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
|
||||
mat.postTranslate(-distanceX, -distanceY);
|
||||
fitBounds();
|
||||
invalidate();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class ScaleGestureListener implements ScaleGestureDetector.OnScaleGestureListener {
|
||||
|
||||
@Override
|
||||
public boolean onScaleBegin(ScaleGestureDetector scaleGestureDetector) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onScale(ScaleGestureDetector scaleGestureDetector) {
|
||||
float focusX = scaleGestureDetector.getFocusX();
|
||||
float focusY = scaleGestureDetector.getFocusY();
|
||||
float ratio = scaleGestureDetector.getScaleFactor();
|
||||
|
||||
setRatio(ratio, focusX, focusY);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScaleEnd(ScaleGestureDetector scaleGestureDetector) {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue