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;
|
package btools.routingapp;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.AssetManager;
|
import android.content.res.AssetManager;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
|
@ -9,7 +10,9 @@ import android.graphics.Color;
|
||||||
import android.graphics.Matrix;
|
import android.graphics.Matrix;
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
|
import android.view.GestureDetector;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
|
import android.view.ScaleGestureDetector;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import java.io.File;
|
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_DELETED_RD5 = 2;
|
||||||
public static final int MASK_INSTALLED_RD5 = 4;
|
public static final int MASK_INSTALLED_RD5 = 4;
|
||||||
public static final int MASK_CURRENT_RD5 = 8;
|
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 File segmentDir;
|
||||||
private final Matrix mat;
|
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 Matrix matText;
|
||||||
|
private final GestureDetector mGestureDetector;
|
||||||
|
private final ScaleGestureDetector mScaleGestureDetector;
|
||||||
Paint pnt_1 = new Paint();
|
Paint pnt_1 = new Paint();
|
||||||
Paint pnt_2 = new Paint();
|
Paint pnt_2 = new Paint();
|
||||||
Paint paint = new Paint();
|
Paint paint = new Paint();
|
||||||
int btnh = 40;
|
int btnh = 40;
|
||||||
int btnw = 160;
|
int btnw = 160;
|
||||||
float tx, ty;
|
|
||||||
private int imgwOrig;
|
private int imgwOrig;
|
||||||
private int imghOrig;
|
private int imghOrig;
|
||||||
private float scaleOrig;
|
private float scaleOrig;
|
||||||
private int imgw;
|
private int imgw;
|
||||||
private int imgh;
|
private int imgh;
|
||||||
private float lastDownX;
|
|
||||||
private float lastDownY;
|
|
||||||
private float viewscale;
|
private float viewscale;
|
||||||
private boolean tilesVisible = false;
|
private boolean tilesVisible = false;
|
||||||
private long availableSize;
|
private long availableSize;
|
||||||
|
@ -69,6 +72,21 @@ public class BInstallerView extends View {
|
||||||
tileStatus = new int[72 * 36];
|
tileStatus = new int[72 * 36];
|
||||||
matText = new Matrix();
|
matText = new Matrix();
|
||||||
mat = 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) {
|
public void setAvailableSize(long availableSize) {
|
||||||
|
@ -142,9 +160,9 @@ public class BInstallerView extends View {
|
||||||
imgh = (int) (imghOrig / scaleOrig);
|
imgh = (int) (imghOrig / scaleOrig);
|
||||||
|
|
||||||
float scaleX = imgwOrig / ((float) bmp.getWidth());
|
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);
|
mat.postScale(viewscale, viewscale);
|
||||||
tilesVisible = false;
|
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
|
@Override
|
||||||
public boolean onTouchEvent(MotionEvent event) {
|
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
|
class GestureListener extends GestureDetector.SimpleOnGestureListener {
|
||||||
int maskedAction = event.getActionMasked();
|
|
||||||
|
|
||||||
switch (maskedAction) {
|
@Override
|
||||||
|
public boolean onSingleTapConfirmed(MotionEvent e) {
|
||||||
case MotionEvent.ACTION_DOWN:
|
// Download Button
|
||||||
case MotionEvent.ACTION_POINTER_DOWN: {
|
if ((delTiles > 0 || rd5Tiles >= 0) && e.getX() > imgwOrig - btnw * scaleOrig && e.getY() > imghOrig - btnh * scaleOrig) {
|
||||||
lastDownX = event.getX();
|
if (mOnClickListener != null) {
|
||||||
lastDownY = event.getY();
|
mOnClickListener.onClick(null);
|
||||||
|
}
|
||||||
break;
|
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();
|
Matrix imat = new Matrix();
|
||||||
if (mat.invert(imat)) {
|
if (mat.invert(imat)) {
|
||||||
float[] touchpoint = new float[2];
|
float[] touchpoint = {e.getX(), e.getY()};
|
||||||
touchpoint[0] = event.getX();
|
|
||||||
touchpoint[1] = event.getY();
|
|
||||||
imat.mapPoints(touchpoint);
|
imat.mapPoints(touchpoint);
|
||||||
|
|
||||||
int tidx = tileIndex(touchpoint[0], touchpoint[1]);
|
int tidx = tileIndex(touchpoint[0], touchpoint[1]);
|
||||||
|
@ -389,23 +342,52 @@ public class BInstallerView extends View {
|
||||||
tileStatus[tidx] ^= MASK_SELECTED_RD5;
|
tileStatus[tidx] ^= MASK_SELECTED_RD5;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tx = touchpoint[0];
|
|
||||||
ty = touchpoint[1];
|
|
||||||
}
|
}
|
||||||
|
invalidate();
|
||||||
|
|
||||||
break;
|
|
||||||
case MotionEvent.ACTION_POINTER_UP:
|
|
||||||
case MotionEvent.ACTION_CANCEL: {
|
|
||||||
// TODO use data
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
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