java - Android: Double-Tap zooms out bitmap image when it's not supposed to...? -
i'm building app generate circles on bitmap when user double taps screen. when user pinches in or pinches out, image zooms in , zooms out, , when use 1 finger image can dragged around.
i wrote code draw circle on bitmap when user double-taps, , works except image gets zoomed way out after draws circle...is wrong gesturedetector class wrote (the class @ bottom of following code:)
public class zoominzoomout extends imageview { private static final string tag = "zoomableimageview"; private bitmap imgbitmap = null; private int containerwidth; private int containerheight; paint background; //matrices used move , zoom image matrix matrix = new matrix(); matrix savedmatrix = new matrix(); pointf start = new pointf(); float currentscale; float curx; float cury; //we can in 1 of these 3 states static final int none = 0; static final int drag = 1; static final int zoom = 2; int mode = none; //for animating stuff float targetx; float targety; float targetscale; float targetscalex; float targetscaley; float scalechange; float targetratio; float transitionalratio; float easing = 0.2f; boolean isanimating = false; float scaledampingfactor = 0.5f; //for pinch , zoom float olddist = 1f; pointf mid = new pointf(); private handler mhandler = new handler(); float minscale; float maxscale = 8.0f; float wpradius = 25.0f; float wpinnerradius = 20.0f; float screendensity; context context; private gesturedetector gesturedetector; public static final int default_scale_fit_inside = 0; public static final int default_scale_original = 1; private int defaultscale; public int getdefaultscale() { return defaultscale; } public void setdefaultscale(int defaultscale) { this.defaultscale = defaultscale; } public zoominzoomout(context context) { super(context); setfocusable(true); setfocusableintouchmode(true); screendensity = context.getresources().getdisplaymetrics().density; initpaints(); gesturedetector = new gesturedetector(new mygesturedetector()); this.context=context; } public zoominzoomout(context context, attributeset attrs) { super(context, attrs); screendensity = context.getresources().getdisplaymetrics().density; initpaints(); gesturedetector = new gesturedetector(new mygesturedetector()); defaultscale = zoominzoomout.default_scale_fit_inside; } private void initpaints() { background = new paint(); } @override protected void onsizechanged(int width, int height, int oldwidth, int oldheight) { super.onsizechanged(width, height, oldwidth, oldheight); //reset width , height. draw bitmap , change containerwidth = width; containerheight = height; if(imgbitmap != null) { int imgheight = imgbitmap.getheight(); int imgwidth = imgbitmap.getwidth(); float scale; int initx = 0; int inity = 0; if(defaultscale == zoominzoomout.default_scale_fit_inside) { if(imgwidth > containerwidth) { scale = (float)containerwidth / imgwidth; float newheight = imgheight * scale; inity = (containerheight - (int)newheight)/2; matrix.setscale(scale, scale); matrix.posttranslate(0, inity); } else { scale = (float)containerheight / imgheight; float newwidth = imgwidth * scale; initx = (containerwidth - (int)newwidth)/2; matrix.setscale(scale, scale); matrix.posttranslate(initx, 0); } curx = initx; cury = inity; currentscale = scale; minscale = scale; } else { if(imgwidth > containerwidth) { inity = (containerheight - (int)imgheight)/2; matrix.posttranslate(0, inity); } else { initx = (containerwidth - (int)imgwidth)/2; matrix.posttranslate(initx, 0); } curx = initx; cury = inity; currentscale = 1.0f; minscale = 1.0f; } invalidate(); } } @override protected void ondraw(canvas canvas) { if(imgbitmap != null && canvas != null) { canvas.drawbitmap(imgbitmap, matrix, background); } } //checks , sets target image x , y co-ordinates if out of bounds private void checkimageconstraints() { if(imgbitmap == null) { return; } float[] mvals = new float[9]; matrix.getvalues(mvals); currentscale = mvals[0]; if(currentscale < minscale) { float deltascale = minscale / currentscale; float px = containerwidth/2; float py = containerheight/2; matrix.postscale(deltascale, deltascale, px, py); invalidate(); } matrix.getvalues(mvals); currentscale = mvals[0]; curx = mvals[2]; cury = mvals[5]; int rangelimitx = containerwidth - (int)(imgbitmap.getwidth() * currentscale); int rangelimity = containerheight - (int)(imgbitmap.getheight() * currentscale); boolean tomovex = false; boolean tomovey = false; if(rangelimitx < 0) { if(curx > 0) { targetx = 0; tomovex = true; } else if(curx < rangelimitx) { targetx = rangelimitx; tomovex = true; } } else { targetx = rangelimitx / 2; tomovex = true; } if(rangelimity < 0) { if(cury > 0) { targety = 0; tomovey = true; } else if(cury < rangelimity) { targety = rangelimity; tomovey = true; } } else { targety = rangelimity / 2; tomovey = true; } if(tomovex == true || tomovey == true) { if(tomovey == false) { targety = cury; } if(tomovex == false) { targetx = curx; } //disable touch event actions isanimating = true; //initialize timer mhandler.removecallbacks(mupdateimagepositiontask); mhandler.postdelayed(mupdateimagepositiontask, 100); } } @override public boolean ontouchevent(motionevent event) { float oldx = 0, newx = 0, sens = 5; if(gesturedetector.ontouchevent(event)) { return true; } if(isanimating == true) { return true; } //handle touch events here float[] mvals = new float[9]; switch(event.getaction() & motionevent.action_mask) { case motionevent.action_down: if(isanimating == false) { savedmatrix.set(matrix); oldx = event.getx(); start.set(event.getx(), event.gety()); mode = drag; } break; case motionevent.action_pointer_down: olddist = spacing(event); if(olddist > 10f) { savedmatrix.set(matrix); midpoint(mid, event); mode = zoom; } break; case motionevent.action_up: newx = event.getx(); if (math.abs(oldx - newx) < sens) { toast.maketext(context, "hello", toast.length_long).show(); return true; } oldx = 0; newx = 0; break; case motionevent.action_pointer_up: mode = none; matrix.getvalues(mvals); curx = mvals[2]; cury = mvals[5]; currentscale = mvals[0]; if(isanimating == false) { checkimageconstraints(); } break; case motionevent.action_move: if(mode == drag && isanimating == false) { matrix.set(savedmatrix); float diffx = event.getx() - start.x; float diffy = event.gety() - start.y; matrix.posttranslate(diffx, diffy); matrix.getvalues(mvals); curx = mvals[2]; cury = mvals[5]; currentscale = mvals[0]; } else if(mode == zoom && isanimating == false) { float newdist = spacing(event); if(newdist > 10f) { matrix.set(savedmatrix); float scale = newdist / olddist; matrix.getvalues(mvals); currentscale = mvals[0]; if(currentscale * scale <= minscale) { matrix.postscale(minscale/currentscale, minscale/currentscale, mid.x, mid.y); } else if(currentscale * scale >= maxscale) { matrix.postscale(maxscale/currentscale, maxscale/currentscale, mid.x, mid.y); } else { matrix.postscale(scale, scale, mid.x, mid.y); } matrix.getvalues(mvals); curx = mvals[2]; cury = mvals[5]; currentscale = mvals[0]; } } break; } //calculate transformations , invalidate invalidate(); return true; } private float spacing(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 void midpoint(pointf point, motionevent event) { float x = event.getx(0) + event.getx(1); float y = event.gety(0) + event.gety(1); point.set(x/2, y/2); } public void setimagebitmap(bitmap b) { if(b != null) { imgbitmap = b; containerwidth = getwidth(); containerheight = getheight(); int imgheight = imgbitmap.getheight(); int imgwidth = imgbitmap.getwidth(); float scale; int initx = 0; int inity = 0; matrix.reset(); if(defaultscale == zoominzoomout.default_scale_fit_inside) { if(imgwidth > containerwidth) { scale = (float)containerwidth / imgwidth; float newheight = imgheight * scale; inity = (containerheight - (int)newheight)/2; matrix.setscale(scale, scale); matrix.posttranslate(0, inity); } else { scale = (float)containerheight / imgheight; float newwidth = imgwidth * scale; initx = (containerwidth - (int)newwidth)/2; matrix.setscale(scale, scale); matrix.posttranslate(initx, 0); } curx = initx; cury = inity; currentscale = scale; minscale = scale; } else { if(imgwidth > containerwidth) { initx = 0; if(imgheight > containerheight) { inity = 0; } else { inity = (containerheight - (int)imgheight)/2; } matrix.posttranslate(0, inity); } else { initx = (containerwidth - (int)imgwidth)/2; if(imgheight > containerheight) { inity = 0; } else { inity = (containerheight - (int)imgheight)/2; } matrix.posttranslate(initx, 0); } curx = initx; cury = inity; currentscale = 1.0f; minscale = 1.0f; } invalidate(); } else { log.d(tag, "bitmap null"); } } public bitmap getphotobitmap() { return imgbitmap; } private runnable mupdateimagepositiontask = new runnable() { public void run() { float[] mvals; if(math.abs(targetx - curx) < 5 && math.abs(targety - cury) < 5) { isanimating = false; mhandler.removecallbacks(mupdateimagepositiontask); mvals = new float[9]; matrix.getvalues(mvals); currentscale = mvals[0]; curx = mvals[2]; cury = mvals[5]; //set image parameters , invalidate display float diffx = (targetx - curx); float diffy = (targety - cury); matrix.posttranslate(diffx, diffy); } else { isanimating = true; mvals = new float[9]; matrix.getvalues(mvals); currentscale = mvals[0]; curx = mvals[2]; cury = mvals[5]; //set image parameters , invalidate display float diffx = (targetx - curx) * 0.3f; float diffy = (targety - cury) * 0.3f; matrix.posttranslate(diffx, diffy); mhandler.postdelayed(this, 25); } invalidate(); } }; private runnable mupdateimagescale = new runnable() { public void run() { float transitionalratio = targetscale / currentscale; float dx; if(math.abs(transitionalratio - 1) > 0.05) { isanimating = true; if(targetscale > currentscale) { dx = transitionalratio - 1; scalechange = 1 + dx * 0.2f; currentscale *= scalechange; if(currentscale > targetscale) { currentscale = currentscale / scalechange; scalechange = 1; } } else { dx = 1 - transitionalratio; scalechange = 1 - dx * 0.5f; currentscale *= scalechange; if(currentscale < targetscale) { currentscale = currentscale / scalechange; scalechange = 1; } } if(scalechange != 1) { matrix.postscale(scalechange, scalechange, targetscalex, targetscaley); mhandler.postdelayed(mupdateimagescale, 15); invalidate(); } else { isanimating = false; scalechange = 1; matrix.postscale(targetscale/currentscale, targetscale/currentscale, targetscalex, targetscaley); currentscale = targetscale; mhandler.removecallbacks(mupdateimagescale); invalidate(); checkimageconstraints(); } } else { isanimating = false; scalechange = 1; matrix.postscale(targetscale/currentscale, targetscale/currentscale, targetscalex, targetscaley); currentscale = targetscale; mhandler.removecallbacks(mupdateimagescale); invalidate(); checkimageconstraints(); } } }; /** show event in logcat view, debugging */ private void dumpevent(motionevent event) { string names[] = { "down", "up", "move", "cancel", "outside", "pointer_down", "pointer_up", "7?", "8?", "9?" }; stringbuilder sb = new stringbuilder(); int action = event.getaction(); int actioncode = action & motionevent.action_mask; sb.append("event action_").append(names[actioncode]); if (actioncode == motionevent.action_pointer_down || actioncode == motionevent.action_pointer_up) { sb.append("(pid ").append(action >> motionevent.action_pointer_id_shift); sb.append(")"); } sb.append("["); (int = 0; < event.getpointercount(); i++) { sb.append("#").append(i); sb.append("(pid ").append(event.getpointerid(i)); sb.append(")=").append((int) event.getx(i)); sb.append(",").append((int) event.gety(i)); if (i + 1 < event.getpointercount()) sb.append(";"); } sb.append("]"); } class mygesturedetector extends simpleongesturelistener { @override public boolean ondoubletap(motionevent event) { bitmap bmoverlay = bitmap.createbitmap(imgbitmap.getwidth(), imgbitmap.getheight(), imgbitmap.getconfig()); canvas canvas = new canvas(bmoverlay); paint p = new paint(); p.setantialias(true); p.setcolor(color.red); p.setstrokewidth(2); p.setstyle(paint.style.stroke); canvas.drawbitmap(imgbitmap, matrix, null); canvas.drawcircle((int)event.getx(),(int)event.gety(), 100, p); setimagebitmap(bmoverlay); return true; } @override public boolean ondown(motionevent e) { return false; } }
}
you're setting image bitmap. setimagebitmap call matrix.reset. when that, you're losing zoom factor. need fiddle code/architecture prevent call.
Comments
Post a Comment