Android Multitouch - ACTION_MOVE with multiple pointers - java

Hi in my app i have a where i want a finger on the top half to control something on the top and a finger on the bottom half to control something on the bottom simultaniously. So i attempted implementing multitouch but i cant seem to get the ACTION_MOVE correct. When i move 2 fingers on the screen it only moves the object on the side that touched the screen first. I was wondering why this is the case? Heres my code:
public boolean onTouch(View v, MotionEvent event){
//needs multitouch
if(checkInGame()){
int pointerIndex = 0;
if(event.getY() < this.getMeasuredHeight() / 2){
pointerId1 = event.getPointerId(event.getActionIndex());
pointerIndex = event.findPointerIndex(pointerId1);
}else{
pointerId2 = event.getPointerId(event.getActionIndex());
pointerIndex = event.findPointerIndex(pointerId2);
}
switch(event.getAction() & MotionEvent.ACTION_MASK){
case MotionEvent.ACTION_MOVE:{
int numPointers = event.getPointerCount();
for (int i = 0; i < numPointers; i++){
if(event.getY(i) < this.getMeasuredHeight() /2){
Log.d("Touch","Move1");
int moveX = 0;
int moveY = 0;
moveX = (int) event.getX(i) - sX;
moveY = (int) event.getY(i) - sY;
ship1.setLoc(moveX, moveY);
sX = sX + moveX;
sY = sY + moveY;
}else{
Log.d("Touch","Move2");
int moveX = 0;
int moveY = 0;
moveX = (int) event.getX(i) - sX2;
moveY = (int) event.getY(i) - sY2;
ship2.setLoc(moveX, moveY);
sX2 = sX2 + moveX;
sY2 = sY2 + moveY;
}
return true;
}
}
case MotionEvent.ACTION_DOWN: {
if(event.getY(pointerIndex) < this.getMeasuredHeight() /2){
Log.d("Touch","Top1");
sX = (int) event.getX(pointerIndex);
sY = (int) event.getY(pointerIndex);
}else{
Log.d("Touch","Bottom1");
sX2 = (int) event.getX(pointerIndex);
sY2 = (int) event.getY(pointerIndex);
}
return true;
}
case MotionEvent.ACTION_POINTER_DOWN:{
if(event.getY(pointerIndex) < this.getMeasuredHeight() /2){
Log.d("Touch","Top2");
sX = (int) event.getX(pointerIndex);
sY = (int) event.getY(pointerIndex);
}else{
Log.d("Touch","Bottom2");
sX2 = (int) event.getX(pointerIndex);
sY2 = (int) event.getY(pointerIndex);
}
return true;
}
}

Your return statement is inside the for-loop, so it only ever iterates once.

Related

Array Index Error while swiping on the game

I have this match 3 game, but if I swiping outside the game board this error showed to me and crush the app:
java.lang.ArrayIndexOutOfBoundsException: length=9; index=11
I tried to fix this error but I don't know how to make it work when I touch outside the game board, is that way to make touch only inside the game board game or just a way to ignore this error when it's happing?
public void swap()
{
if(swapIndex > 0)
{
switch (direction){
case "right":
board[poseI][poseJ + 1].poseX -= cellWidth/ 8;
board[poseI][poseJ].poseX += cellWidth/ 8;
break;
case "left":
board[poseI][poseJ - 1].poseX += cellWidth/ 8;
board[poseI][poseJ].poseX -= cellWidth/ 8;
break;
case "up":
board[poseI - 1][poseJ].poseY += cellWidth/ 8;
board[poseI][poseJ].poseY -= cellWidth/ 8;
break;
case "down":
board[poseI + 1][poseJ].poseY -= cellWidth/ 8;
board[poseI][poseJ].poseY += cellWidth/ 8;
break;
}
swapIndex--;
}else {
Candies candies;
candies = board[poseI][poseJ];
board[poseI][poseJ] = board[newPoseI][newPoseJ];
board[newPoseI][newPoseJ] = candies;
board[poseI][poseJ].poseX = (int) (poseJ * cellWidth + drawX);
board[poseI][poseJ].poseY = (int) (poseI * cellWidth + drawY);
board[newPoseI][newPoseJ].poseX = (int) (newPoseJ * cellWidth + drawX);
board[newPoseI][newPoseJ].poseY = (int) (newPoseI * cellWidth + drawY);
swapIndex = 8;
if (gameState == GameState.swapping)
{
gameState = GameState.checkSwapping;
// count user moves
increaseUserMove();
}else {
gameState = GameState.nothing;
}
}
}
#Override
public void draw(Canvas canvas) {
super.draw(canvas);
canvas.drawColor(Color.WHITE); // Background Color
// Create Game top Background
canvas.drawBitmap(spriteSheet.topBG , 0, - cellWidth * 2, null);
// Create Game bottom Background
canvas.drawBitmap(spriteSheet.bottomBG , 0, drawY + cellWidth * 9, null);
// Create Game middle Background
canvas.drawBitmap(spriteSheet.bg_middle , 0, drawY, null);
// Create Game Cells
Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
p.setColor(Color.BLACK); // cells color
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 9; j++)
{
canvas.drawLine(0, drawY + (i * cellWidth), cellWidth * 10, drawY + (i * cellWidth), p);
canvas.drawLine(j * cellWidth , drawY, j * cellWidth, drawY + cellWidth * 9, p);
}
}
for (Candies[] candie: board)
{
for (Candies candies: candie)
{
candies.drawCandies(canvas, spriteSheet);
}
}
for(int i = 0; i < board.length; i++)
{
for(int j = 0; j < board[0].length; j++)
{
candies.drawCandies(canvas, spriteSheet);
}
}
//canvas.drawBitmap(spriteSheet.candiesBMP, candies.poseX, candies.poseY, null);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
final int action = event.getAction();
switch (action)
{
case MotionEvent.ACTION_DOWN:
oldX = event.getX();
oldY = event.getY();
poseI = (int) (oldY - drawY) / cellWidth;
poseJ = (int) (oldX - drawX) / cellWidth;
move = true;
break;
case MotionEvent.ACTION_MOVE:
if(gameState == GameState.nothing)
{
float newX = event.getX();
float newY = event.getY();
float deltaX = Math.abs(newX - oldX);
float deltaY = Math.abs(newY - oldY);
if(move && deltaX > 30 || deltaY > 30)
{
// check how many pixels our fingers moved
// if we moved our finger more than 30 pixels we start checking in which direction
move = false;
if (Math.abs(oldX- newX) > Math.abs(oldY - newY))
{
// if the first X touch - the end of the X touch is bigger than the
// first Y touch - the end of the touch Y so the direction is in the X direction
// now we will check which is bigger the oldX or newX for know if its left or right
if(newX > oldX)
{
direction = "right";
newPoseJ = (poseJ + 1);
}else {
direction = "left";
newPoseJ = (poseJ - 1);
}
newPoseI = poseI;
}
if (Math.abs(oldY - newY) > Math.abs(oldX - newX))
{
if(newY > oldY)
{
direction = "down";
newPoseI = (poseI + 1);
}else {
direction = "up";
newPoseI = (poseI - 1);
}
newPoseJ = poseJ;
}
gameState = GameState.swapping;
}
}
break;
}
return true;
}

processing FrameBuffer Error

I am trying to make a processing program, but if I use P2D, P3D, or OPENGL mode I get an error:
com.sun.jdi.VMDisconnectedException
at com.sun.tools.jdi.TargetVM.waitForReply(TargetVM.java:285)
at com.sun.tools.jdi.VirtualMachineImpl.waitForTargetReply(VirtualMachineImpl.java:1015)
at com.sun.tools.jdi.PacketStream.waitForReply(PacketStream.java:51)
at com.sun.tools.jdi.JDWP$ObjectReference$InvokeMethod.waitForReply(JDWP.java:4589)
at com.sun.tools.jdi.ObjectReferenceImpl.invokeMethod(ObjectReferenceImpl.java:374)
at processing.mode.java.runner.Runner.findException(Runner.java:701)
at processing.mode.java.runner.Runner.reportException(Runner.java:652)
at processing.mode.java.runner.Runner.exception(Runner.java:595)
at processing.mode.java.runner.EventThread.exceptionEvent(EventThread.java:367)
at processing.mode.java.runner.EventThread.handleEvent(EventThread.java:255)
at processing.mode.java.runner.EventThread.run(EventThread.java:89)
the error message itself varies between P2D and P3D, but they both get a no framebuffer objects available error. I am using processing 2.0b7, please help and let me know if you need more info.
Note: I don't know if this is a separate issue or not, but I am also getting GLSL shader errors to.
Now, here is my code:
Cell[][] Cells = new Cell[50][50];
byte Direction = 1;
byte Times = 1;
int oldwidth = 500;
int oldheight = 500;
void setup() {
size(oldwidth, oldheight, OPENGL);
background(255);
colorMode(HSB,250);
for (int x = 0; x < 50; x++) {
for (int y = 0; y < 50; y++) {
Cells[x][y] = new Cell(x * 5, y * 5, 255, x * (width / 50), y * (height / 50), width / 50, height / 50);
}
}
}
void draw() {
for (int x = 0; x < 50; x++) {
for (int y = 0; y < 50; y++) {
if (width == oldwidth) Cells[x][y].Width = width / 50;
if (height == oldheight) Cells[x][y].Height = height / 50;
if (Direction == 1){
Cells[x][y].Hue += 5;
if (Cells[x][y].Hue > 250) Cells[x][y].Hue -= 250;
}
if (Direction == 2){
Cells[x][y].Saturation -= 5;
if (Cells[x][y].Saturation < 0) Cells[x][y].Saturation += 500;
}
if (Direction == 3){
Cells[x][y].Hue -= 5;
if (Cells[x][y].Hue < 0) Cells[x][y].Hue += 250;
}
if (Direction == 4){
Cells[x][y].Saturation += 5;
if (Cells[x][y].Saturation > 500) Cells[x][y].Saturation -= 500;
}
Cells[x][y].Draw();
}
}
if (Times == 50){
Times = 1;
if (Direction == 4) Direction = 1; else Direction += 1;
} else Times += 1;
delay(10);
}
class Cell {
int X;
int Y;
int Width;
int Height;
float Hue;
float Saturation;
float Brightness;
Cell(color parC, int parX, int parY, int parWidth, int parHeight) {
Hue = hue(parC);
Saturation = saturation(parC);
Brightness = brightness(parC);
X = parX;
Y = parY;
Width = parWidth;
Height = parHeight;
}
Cell(float parHue, float parSaturation, float parBrightness, int parX, int parY, int parWidth, int parHeight) {
Hue = parHue;
Saturation = parSaturation;
Brightness = parBrightness;
X = parX;
Y = parY;
Width = parWidth;
Height = parHeight;
}
void Draw() {
if (Saturation > 250) if (Saturation > 500) stroke(color(Hue,0,Brightness)); else stroke(color(Hue,Saturation - (Saturation - 250) * 2,Brightness)); else stroke(color(Hue,Saturation,Brightness));
if (Saturation > 250) if (Saturation > 500) fill(color(Hue,0,Brightness)); else fill(color(Hue,Saturation - (Saturation - 250) * 2,Brightness)); else fill(color(Hue,Saturation,Brightness));
rect(X, Y, Width, Height);
}
}
I just realized that it is just that my graphics card does not support OPENGL 2.0

how to add a pin marker on image view in android

i am working on a project where i need to add pins on image view as shown in below image.
how could we do this.
i successfully created a zoomable image view using
TouchImageview.java
class TouchImageView extends ImageView {
Matrix matrix = new Matrix();
// We can be in one of these 3 states
static final int NONE = 0;
static final int DRAG = 1;
static final int ZOOM = 2;
int mode = NONE;
// Remember some things for zooming
PointF last = new PointF();
PointF start = new PointF();
float minScale = 1f;
float maxScale = 3f;
float[] m;
float redundantXSpace, redundantYSpace;
float width, height;
static final int CLICK = 3;
float saveScale = 1f;
float right, bottom, origWidth, origHeight, bmWidth, bmHeight;
ScaleGestureDetector mScaleDetector;
Context context;
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
}
public TouchImageView(Context context) {
super(context);
super.setClickable(true);
this.context = context;
mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
matrix.setTranslate(1f, 1f);
m = new float[9];
setImageMatrix(matrix);
setScaleType(ScaleType.MATRIX);
setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
mScaleDetector.onTouchEvent(event);
Log.e("Deepak", "X" + event.getRawX());
Log.e("Deepak", "Y" + event.getRawY());
matrix.getValues(m);
float x = m[Matrix.MTRANS_X];
float y = m[Matrix.MTRANS_Y];
PointF curr = new PointF(event.getX(), event.getY());
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
last.set(event.getX(), event.getY());
start.set(last);
mode = DRAG;
break;
case MotionEvent.ACTION_MOVE:
if (mode == DRAG) {
float deltaX = curr.x - last.x;
float deltaY = curr.y - last.y;
float scaleWidth = Math.round(origWidth * saveScale);
float scaleHeight = Math.round(origHeight * saveScale);
if (scaleWidth < width) {
deltaX = 0;
if (y + deltaY > 0)
deltaY = -y;
else if (y + deltaY < -bottom)
deltaY = -(y + bottom);
} else if (scaleHeight < height) {
deltaY = 0;
if (x + deltaX > 0)
deltaX = -x;
else if (x + deltaX < -right)
deltaX = -(x + right);
} else {
if (x + deltaX > 0)
deltaX = -x;
else if (x + deltaX < -right)
deltaX = -(x + right);
if (y + deltaY > 0)
deltaY = -y;
else if (y + deltaY < -bottom)
deltaY = -(y + bottom);
}
matrix.postTranslate(deltaX, deltaY);
last.set(curr.x, curr.y);
}
break;
case MotionEvent.ACTION_UP:
mode = NONE;
int xDiff = (int) Math.abs(curr.x - start.x);
int yDiff = (int) Math.abs(curr.y - start.y);
if (xDiff < CLICK && yDiff < CLICK)
performClick();
break;
case MotionEvent.ACTION_POINTER_UP:
mode = NONE;
break;
}
setImageMatrix(matrix);
invalidate();
return true; // indicate event was handled
}
});
}
#Override
public void setImageBitmap(Bitmap bm) {
super.setImageBitmap(bm);
bmWidth = bm.getWidth();
bmHeight = bm.getHeight();
}
public void setMaxZoom(float x)
{
maxScale = x;
}
private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
#Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
mode = ZOOM;
return true;
}
#Override
public boolean onScale(ScaleGestureDetector detector) {
float mScaleFactor = (float)Math.min(Math.max(.95f, detector.getScaleFactor()), 1.05);
float origScale = saveScale;
saveScale *= mScaleFactor;
if (saveScale > maxScale) {
saveScale = maxScale;
mScaleFactor = maxScale / origScale;
} else if (saveScale < minScale) {
saveScale = minScale;
mScaleFactor = minScale / origScale;
}
right = width * saveScale - width - (2 * redundantXSpace * saveScale);
bottom = height * saveScale - height - (2 * redundantYSpace * saveScale);
if (origWidth * saveScale <= width || origHeight * saveScale <= height) {
matrix.postScale(mScaleFactor, mScaleFactor, width / 2, height / 2);
if (mScaleFactor < 1) {
matrix.getValues(m);
float x = m[Matrix.MTRANS_X];
float y = m[Matrix.MTRANS_Y];
if (mScaleFactor < 1) {
if (Math.round(origWidth * saveScale) < width) {
if (y < -bottom)
matrix.postTranslate(0, -(y + bottom));
else if (y > 0)
matrix.postTranslate(0, -y);
} else {
if (x < -right)
matrix.postTranslate(-(x + right), 0);
else if (x > 0)
matrix.postTranslate(-x, 0);
}
}
}
} else {
matrix.postScale(mScaleFactor, mScaleFactor, detector.getFocusX(), detector.getFocusY());
matrix.getValues(m);
float x = m[Matrix.MTRANS_X];
float y = m[Matrix.MTRANS_Y];
if (mScaleFactor < 1) {
if (x < -right)
matrix.postTranslate(-(x + right), 0);
else if (x > 0)
matrix.postTranslate(-x, 0);
if (y < -bottom)
matrix.postTranslate(0, -(y + bottom));
else if (y > 0)
matrix.postTranslate(0, -y);
}
}
return true;
}
}
#Override
protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec)
{
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
width = MeasureSpec.getSize(widthMeasureSpec);
height = MeasureSpec.getSize(heightMeasureSpec);
//Fit to screen.
float scale;
float scaleX = (float)width / (float)bmWidth;
float scaleY = (float)height / (float)bmHeight;
scale = Math.min(scaleX, scaleY);
matrix.setScale(scale, scale);
setImageMatrix(matrix);
saveScale = 1f;
// Center the image
redundantYSpace = (float)height - (scale * (float)bmHeight) ;
redundantXSpace = (float)width - (scale * (float)bmWidth);
redundantYSpace /= (float)2;
redundantXSpace /= (float)2;
matrix.postTranslate(redundantXSpace, redundantYSpace);
origWidth = width - 2 * redundantXSpace;
origHeight = height - 2 * redundantYSpace;
right = width * saveScale - width - (2 * redundantXSpace * saveScale);
bottom = height * saveScale - height - (2 * redundantYSpace * saveScale);
setImageMatrix(matrix);
}
}
now i need to add markers on it.
any help for it.
i found my answer here https://github.com/catchthecows/AndroidImageMap
An implementation of an HTML map like element in an Android View:
Supports images as drawable or bitmap in layout
Allows for a list of area tags in xml
Enables use of cut and paste HTML area tags to a resource xml (ie, the ability to take an HTML map - and image and use it with minimal editing)
Supports panning if the image is larger than the device screen
Supports pinch-zoom
Supports callbacks when an area is tapped.
Supports showing annotations as bubble text and provide callback if the bubble is tapped
I have used AndroidImageMap but i don't like how it zooms the image, and you don't have facilities to add custom views as clickable areas.
Checkout this example project https://github.com/jzafrilla/AndroidImageHostpot I have used https://github.com/chrisbanes/PhotoView/ to get Zoom and Pan functionality.
Hope this helps...(to me, absolutely yes)

Moving through a tilemap; gets stuck vertically when it hit the middle of the map

So I'm making a simple game where I have a tilemap (or cellmap depending on your terminology). The problem is: if I have a map over about 100 tiles if I move about halfway down the map the app will move me to the last row(meaning the bottom row on screen is the last row) and I can no longer move up but have no trouble moving horizontally. I would really appreciate it if someone could tell me what I'm doing wrong and why what I'm doing doesn't work for anything above ~100 tilesThe code for moving.
Here's the code showing how I handle the touch events. If you think you need more code be sure to tell me.
#Override
public boolean onTouchEvent(MotionEvent event) {
// touch down
if (event.getAction() == MotionEvent.ACTION_DOWN) {
// new event
_isMoving = false;
// store coordinates
_xTouch = (int) event.getX();
_yTouch = (int) event.getY();
} else if (event.getAction() == MotionEvent.ACTION_MOVE) {
_isMoving = true;
// new offset
_xOffSet += _xTouch - (int) event.getX();
_yOffSet += _yTouch - (int) event.getY();
// make sure it never goes out of bounds
if (_xOffSet < 0) {
_xOffSet = 0;
} else if (_xOffSet > _mapSize * _cellSize - getWidth()) {
_xOffSet = _mapSize * _cellSize - getWidth();
}
if (_yOffSet < 0) {
_yOffSet = 0;
} else if (_yOffSet > getHeight()) {
_yOffSet = _mapSize * _cellSize - getHeight();
}
_xTouch = (int) event.getX();
_yTouch = (int) event.getY();
findMapEnds();
} else if (event.getAction() == MotionEvent.ACTION_UP) {
// touch released
if (!_isMoving) {
int column = (int) FloatMath.ceil((_xOffSet + event.getX())
/ _cellSize) - 1;
int row = (int) FloatMath.ceil((_yOffSet + event.getY())
/ _cellSize) - 1;
Cell cell = _mapCells.get(row).get(column);
Toast.makeText(getContext(), "Cell id #" + cell.get_id(),
Toast.LENGTH_SHORT).show();
}
}
return true;
}
private void findMapEnds() {
// finds the map end.
_StartRow = _yOffSet / _cellSize;
_MaxRow = (int) Math.min(_mapSize, _StartRow + Math.floor(getHeight())
/ _cellSize + 2);
_StartCol = _xOffSet / _cellSize;
_MaxCol = (int) Math.min(_mapSize, _StartCol + Math.floor(getWidth())
/ _cellSize + 2);
_XScrollOffset = (int) (((_xOffSet / (float) _cellSize) - (_xOffSet / _cellSize)) * _cellSize);
_YScrollOffset = (int) (((_yOffSet / (float) _cellSize) - (_yOffSet / _cellSize)) * _cellSize);
}

How does TouchImageView works?

I have good working TouchImageView and i want to know how does it work in a code :
What i just want to do is be able to pinch to zoom, or use double tap to zoom on any imageview i choose, and when i zoom back i return to the original size of the image.
TouchImageView.java :
public class TouchImageView extends ImageView {
Matrix matrix = new Matrix();
static final int NONE = 0;
static final int DRAG = 1;
static final int ZOOM = 2;
int mode = NONE;
PointF last = new PointF();
PointF start = new PointF();
float minScale = 1f;
float maxScale = 3f;
float[] m;
float redundantXSpace, redundantYSpace;
float width, height;
static final int CLICK = 3;
float saveScale = 1f;
float right, bottom, origWidth, origHeight, bmWidth, bmHeight;
ScaleGestureDetector mScaleDetector;
Context context;
public TouchImageView(Context context) {
super(context);
super.setClickable(true);
this.context = context;
mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
matrix.setTranslate(1f, 1f);
m = new float[9];
setImageMatrix(matrix);
setScaleType(ScaleType.MATRIX);
setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
mScaleDetector.onTouchEvent(event);
matrix.getValues(m);
float x = m[Matrix.MTRANS_X];
float y = m[Matrix.MTRANS_Y];
PointF curr = new PointF(event.getX(), event.getY());
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
last.set(event.getX(), event.getY());
start.set(last);
mode = DRAG;
break;
case MotionEvent.ACTION_MOVE:
if (mode == DRAG) {
float deltaX = curr.x - last.x;
float deltaY = curr.y - last.y;
float scaleWidth = Math.round(origWidth * saveScale);
float scaleHeight = Math.round(origHeight * saveScale);
if (scaleWidth < width) {
deltaX = 0;
if (y + deltaY > 0)
deltaY = -y;
else if (y + deltaY < -bottom)
deltaY = -(y + bottom);
} else if (scaleHeight < height) {
deltaY = 0;
if (x + deltaX > 0)
deltaX = -x;
else if (x + deltaX < -right)
deltaX = -(x + right);
} else {
if (x + deltaX > 0)
deltaX = -x;
else if (x + deltaX < -right)
deltaX = -(x + right);
if (y + deltaY > 0)
deltaY = -y;
else if (y + deltaY < -bottom)
deltaY = -(y + bottom);
}
matrix.postTranslate(deltaX, deltaY);
last.set(curr.x, curr.y);
}
break;
case MotionEvent.ACTION_UP:
mode = NONE;
int xDiff = (int) Math.abs(curr.x - start.x);
int yDiff = (int) Math.abs(curr.y - start.y);
if (xDiff < CLICK && yDiff < CLICK)
performClick();
break;
case MotionEvent.ACTION_POINTER_UP:
mode = NONE;
break;
}
setImageMatrix(matrix);
invalidate();
return true; // indicate event was handled
}
});
}
#Override
public void setImageBitmap(Bitmap bm) {
super.setImageBitmap(bm);
bmWidth = bm.getWidth();
bmHeight = bm.getHeight();
}
public void setMaxZoom(float x)
{
maxScale = x;
}
private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
#Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
mode = ZOOM;
return true;
}
#Override
public boolean onScale(ScaleGestureDetector detector) {
float mScaleFactor = (float)Math.min(Math.max(.95f, detector.getScaleFactor()), 1.05);
float origScale = saveScale;
saveScale *= mScaleFactor;
if (saveScale > maxScale) {
saveScale = maxScale;
mScaleFactor = maxScale / origScale;
} else if (saveScale < minScale) {
saveScale = minScale;
mScaleFactor = minScale / origScale;
}
right = width * saveScale - width - (2 * redundantXSpace * saveScale);
bottom = height * saveScale - height - (2 * redundantYSpace * saveScale);
if (origWidth * saveScale <= width || origHeight * saveScale <= height) {
matrix.postScale(mScaleFactor, mScaleFactor, width / 2, height / 2);
if (mScaleFactor < 1) {
matrix.getValues(m);
float x = m[Matrix.MTRANS_X];
float y = m[Matrix.MTRANS_Y];
if (mScaleFactor < 1) {
if (Math.round(origWidth * saveScale) < width) {
if (y < -bottom)
matrix.postTranslate(0, -(y + bottom));
else if (y > 0)
matrix.postTranslate(0, -y);
} else {
if (x < -right)
matrix.postTranslate(-(x + right), 0);
else if (x > 0)
matrix.postTranslate(-x, 0);
}
}
}
} else {
matrix.postScale(mScaleFactor, mScaleFactor, detector.getFocusX(), detector.getFocusY());
matrix.getValues(m);
float x = m[Matrix.MTRANS_X];
float y = m[Matrix.MTRANS_Y];
if (mScaleFactor < 1) {
if (x < -right)
matrix.postTranslate(-(x + right), 0);
else if (x > 0)
matrix.postTranslate(-x, 0);
if (y < -bottom)
matrix.postTranslate(0, -(y + bottom));
else if (y > 0)
matrix.postTranslate(0, -y);
}
}
return true;
}
}
#Override
protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec)
{
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
width = MeasureSpec.getSize(widthMeasureSpec);
height = MeasureSpec.getSize(heightMeasureSpec);
//Fit to screen.
float scale;
float scaleX = (float)width / (float)bmWidth;
float scaleY = (float)height / (float)bmHeight;
scale = Math.min(scaleX, scaleY);
matrix.setScale(scale, scale);
setImageMatrix(matrix);
saveScale = 1f;
// Center the image
redundantYSpace = (float)height - (scale * (float)bmHeight) ;
redundantXSpace = (float)width - (scale * (float)bmWidth);
redundantYSpace /= (float)2;
redundantXSpace /= (float)2;
matrix.postTranslate(redundantXSpace, redundantYSpace);
origWidth = width - 2 * redundantXSpace;
origHeight = height - 2 * redundantYSpace;
right = width * saveScale - width - (2 * redundantXSpace * saveScale);
bottom = height * saveScale - height - (2 * redundantYSpace * saveScale);
setImageMatrix(matrix);
}
}
To use is i created a private class :
private class CreateImage extends AsyncTask<String, Void, Drawable> {
protected void onPreExecute() {
}
protected Drawable doInBackground(String... urls) {
InputStream is;
Drawable d = null ;
try {
is = (InputStream)new URL(urls[0]).getContent();
d = Drawable.createFromStream(is, "Image");
return d;
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return d;
}
protected void onPostExecute(Drawable d) {
touch.setMaxZoom(4f);
touch.setImageDrawable(d);
setContentView(touch);
}
}
public void createUrlImage(String url){
new CreateImage().execute(url);
}
and in the onCreate() i put createUrlImage(url).
I modified TouchImageView by adding :
public void setImageDrawable(Drawable dr) {
super.setImageDrawable(dr);
bmWidth = dr.getIntrinsicWidth();
bmHeight = dr.getIntrinsicHeight();
}
EDIT: Double Tap Zoom, Fling and other features have been added to TouchImageView since I originally answered this question. You can check it out on github here.
I added some usage details to the original post here. The code already has pinch zoom and panning, along with boundaries. Also, zooming out will return you to the original sized image.
Adding double tap zoom will take more work. You'll have to use a GestureDetector and override onDoubleTap and onSingleTapConfirmed. You'll then want to make sure you pass your touch events to gestureDetector, without interfering with the rest of the code (see how events are passed to mScaleDetector at the beginning of onTouch). You'll want to get rid of the call to performClick() in ACTION_UP and instead place it in onSingleTapConfirmed. You can check this answer for some skeletal code to get you started in implementing GestureDetector.
Let me know if you manage to get double tap zoom solid and I'll add your changes to the original post and the Github repo.

Categories