canvas - Android translate MotionEvent coordinates when drawing -
hello try make drawing after user zooms view , have issue. ive got zoomview (custom view) contains subview imageview image (custom view), zoomview working good, im able zoom/pan/drag , imageview (custom) responds gesture, when try draw on imageview after zoomed/dragged/panned zoomview drawn on touch gets little messed.
first top line drawn when zoomview not zoomed, line looks good. second line drawn when zoomview @ middle zoom. third drawn @ full zoom.
the issue when zoomed , touching finger, line draws faster normal, , cant line, add other line in case (second line: line going top , , third line: line going bottom) while try draw line.
im asking help: how can translate touch point zoomview when zoomed imageview touch points draw canvas.
here classes:
public class ownzoom extends framelayout { /** * zooming view listener interface. * * @author karooolek * */ public interface ownzoomlistener { void onzoomstarted(float zoom, float zoomx, float zoomy); void onzooming(float zoom, float zoomx, float zoomy); void onzoomended(float zoom, float zoomx, float zoomy); } boolean modedown=false; // zooming float zoom = 1.0f; float maxzoom = 2.0f; float smoothzoom = 1.0f; float zoomx, zoomy; float smoothzoomx, smoothzoomy; private boolean scrolling; // nopmd karooolek on 29.06.11 11:45 // minimap variables private boolean showminimap = false; private int minimapcolor = color.black; private int minimapheight = -1; private string minimapcaption; private float minimapcaptionsize = 10.0f; private int minimapcaptioncolor = color.white; // touching variables private long lasttaptime; private float touchstartx, touchstarty; private float touchlastx, touchlasty; private float startd; private boolean pinching; private float lastd; private float lastdx1, lastdy1; private float lastdx2, lastdy2; // drawing private final matrix m = new matrix(); private final paint p = new paint(); // listener ownzoomlistener listener; private bitmap ch; public void setzommmode(boolean zoomed){ this.modedown=zoomed; } public ownzoom(final context context) { super(context); } public float getzoom() { return zoom; } public float getmaxzoom() { return maxzoom; } public void setmaxzoom(final float maxzoom) { if (maxzoom < 1.0f) { return; } this.maxzoom = maxzoom; } public void setminimapenabled(final boolean showminimap) { this.showminimap = showminimap; } public boolean isminimapenabled() { return showminimap; } public void setminimapheight(final int minimapheight) { if (minimapheight < 0) { return; } this.minimapheight = minimapheight; } public int getminimapheight() { return minimapheight; } public void setminimapcolor(final int color) { minimapcolor = color; } public int getminimapcolor() { return minimapcolor; } public string getminimapcaption() { return minimapcaption; } public void setminimapcaption(final string minimapcaption) { this.minimapcaption = minimapcaption; } public float getminimapcaptionsize() { return minimapcaptionsize; } public void setminimapcaptionsize(final float size) { minimapcaptionsize = size; } public int getminimapcaptioncolor() { return minimapcaptioncolor; } public void setminimapcaptioncolor(final int color) { minimapcaptioncolor = color; } public void zoomto(final float zoom, final float x, final float y) { this.zoom = math.min(zoom, maxzoom); zoomx = x; zoomy = y; smoothzoomto(this.zoom, x, y); } public void smoothzoomto(final float zoom, final float x, final float y) { smoothzoom = clamp(1.0f, zoom, maxzoom); smoothzoomx = x; smoothzoomy = y; if (listener != null) { listener.onzoomstarted(smoothzoom, x, y); } } public ownzoomlistener getlistener() { return listener; } public void setlistner(final ownzoomlistener listener) { this.listener = listener; } public float getzoomfocusx() { return zoomx * zoom; } public float getzoomfocusy() { return zoomy * zoom; } @override public boolean dispatchtouchevent(final motionevent ev) { // single touch if (ev.getpointercount() == 1) { processsingletouchevent(ev); } // // double touch if (ev.getpointercount() == 2) { processdoubletouchevent(ev); } // redraw getrootview().invalidate(); invalidate(); return true; } private void processsingletouchevent(final motionevent ev) { //if(!modedown){ final float x = ev.getx(); final float y = ev.gety(); final float w = minimapheight * (float) getwidth() / getheight(); final float h = minimapheight; final boolean touchingminimap = x >= 10.0f && x <= 10.0f + w && y >= 10.0f && y <= 10.0f + h; if (showminimap && smoothzoom > 1.0f && touchingminimap) { processsingletouchonminimap(ev); } else { processsingletouchoutsideminimap(ev); } //}else if(modedown){ // log.i("moded own ", "is false"); // } } private void processsingletouchonminimap(final motionevent ev) { final float x = ev.getx(); final float y = ev.gety(); final float w = minimapheight * (float) getwidth() / getheight(); final float h = minimapheight; final float zx = (x - 10.0f) / w * getwidth(); final float zy = (y - 10.0f) / h * getheight(); smoothzoomto(smoothzoom, zx, zy); } private void processsingletouchoutsideminimap(final motionevent ev) { final float x = ev.getx(); final float y = ev.gety(); float lx = x - touchstartx; float ly = y - touchstarty; final float l = (float) math.hypot(lx, ly); float dx = x - touchlastx; float dy = y - touchlasty; touchlastx = x; touchlasty = y; switch (ev.getaction()) { case motionevent.action_down: touchstartx = x; touchstarty = y; touchlastx = x; touchlasty = y; dx = 0; dy = 0; lx = 0; ly = 0; scrolling = false; break; case motionevent.action_move: if(modedown){ if (scrolling || (smoothzoom > 1.0f && l > 30.0f)) { if (!scrolling) { scrolling = true; ev.setaction(motionevent.action_cancel); super.dispatchtouchevent(ev); } smoothzoomx -= dx / zoom; smoothzoomy -= dy / zoom; return; } }else if(!modedown){ ev.setaction(motionevent.action_move); super.dispatchtouchevent(ev); return; } break; case motionevent.action_outside: case motionevent.action_up: // tap if (l < 30.0f) { // check double tap if (system.currenttimemillis() - lasttaptime < 500) { if (smoothzoom == 1.0f) { smoothzoomto(maxzoom, x, y); } else { smoothzoomto(1.0f, getwidth() / 2.0f, getheight() / 2.0f); } lasttaptime = 0; ev.setaction(motionevent.action_cancel); super.dispatchtouchevent(ev); return; } lasttaptime = system.currenttimemillis(); performclick(); } break; default: break; } ev.setlocation(zoomx + (x - 0.5f * getwidth()) / zoom, zoomy + (y - 0.5f * getheight()) / zoom); ev.getx(); ev.gety(); super.dispatchtouchevent(ev); } private void processdoubletouchevent(final motionevent ev) { final float x1 = ev.getx(0); final float dx1 = x1 - lastdx1; lastdx1 = x1; final float y1 = ev.gety(0); final float dy1 = y1 - lastdy1; lastdy1 = y1; final float x2 = ev.getx(1); final float dx2 = x2 - lastdx2; lastdx2 = x2; final float y2 = ev.gety(1); final float dy2 = y2 - lastdy2; lastdy2 = y2; // pointers distance final float d = (float) math.hypot(x2 - x1, y2 - y1); final float dd = d - lastd; lastd = d; final float ld = math.abs(d - startd); math.atan2(y2 - y1, x2 - x1); switch (ev.getaction()) { case motionevent.action_down: startd = d; pinching = false; break; case motionevent.action_move: if (pinching || ld > 30.0f) { pinching = true; final float dxk = 0.5f * (dx1 + dx2); final float dyk = 0.5f * (dy1 + dy2); smoothzoomto(math.max(1.0f, zoom * d / (d - dd)), zoomx - dxk / zoom, zoomy - dyk / zoom); } break; case motionevent.action_up: default: pinching = false; break; } ev.setaction(motionevent.action_cancel); super.dispatchtouchevent(ev); } private float clamp(final float min, final float value, final float max) { return math.max(min, math.min(value, max)); } private float lerp(final float a, final float b, final float k) { return + (b - a) * k; } private float bias(final float a, final float b, final float k) { return math.abs(b - a) >= k ? + k * math.signum(b - a) : b; } @override protected void dispatchdraw(final canvas canvas) { // zoom zoom = lerp(bias(zoom, smoothzoom, 0.05f), smoothzoom, 0.2f); smoothzoomx = clamp(0.5f * getwidth() / smoothzoom, smoothzoomx, getwidth() - 0.5f * getwidth() / smoothzoom); smoothzoomy = clamp(0.5f * getheight() / smoothzoom, smoothzoomy, getheight() - 0.5f * getheight() / smoothzoom); zoomx = lerp(bias(zoomx, smoothzoomx, 0.1f), smoothzoomx, 0.35f); zoomy = lerp(bias(zoomy, smoothzoomy, 0.1f), smoothzoomy, 0.35f); if (zoom != smoothzoom && listener != null) { listener.onzooming(zoom, zoomx, zoomy); } final boolean animating = math.abs(zoom - smoothzoom) > 0.0000001f || math.abs(zoomx - smoothzoomx) > 0.0000001f || math.abs(zoomy - smoothzoomy) > 0.0000001f; // nothing draw if (getchildcount() == 0) { return; } // prepare matrix m.settranslate(0.5f * getwidth(), 0.5f * getheight()); m.prescale(zoom, zoom); m.pretranslate(-clamp(0.5f * getwidth() / zoom, zoomx, getwidth() - 0.5f * getwidth() / zoom), -clamp(0.5f * getheight() / zoom, zoomy, getheight() - 0.5f * getheight() / zoom)); // view final view v = getchildat(0); m.pretranslate(v.getleft(), v.gettop()); // drawing cache if available if (animating && ch == null && isanimationcacheenabled()) { v.setdrawingcacheenabled(true); ch = v.getdrawingcache(); } // draw using cache while animating if (animating && isanimationcacheenabled() && ch != null) { p.setcolor(0xffffffff); canvas.drawbitmap(ch, m, p); } else { // zoomed or cache unavailable ch = null; canvas.save(); canvas.concat(m); v.draw(canvas); canvas.restore(); } // draw minimap if (showminimap) { if (minimapheight < 0) { minimapheight = getheight() / 4; } canvas.translate(10.0f, 10.0f); p.setcolor(0x80000000 | 0x00ffffff & minimapcolor); final float w = minimapheight * (float) getwidth() / getheight(); final float h = minimapheight; canvas.drawrect(0.0f, 0.0f, w, h, p); if (minimapcaption != null && minimapcaption.length() > 0) { p.settextsize(minimapcaptionsize); p.setcolor(minimapcaptioncolor); p.setantialias(true); canvas.drawtext(minimapcaption, 10.0f, 10.0f + minimapcaptionsize, p); p.setantialias(false); } p.setcolor(0x80000000 | 0x00ffffff & minimapcolor); final float dx = w * zoomx / getwidth(); final float dy = h * zoomy / getheight(); canvas.drawrect(dx - 0.5f * w / zoom, dy - 0.5f * h / zoom, dx + 0.5f * w / zoom, dy + 0.5f * h / zoom, p); canvas.translate(-10.0f, -10.0f); } // redraw // if (animating) { getrootview().invalidate(); invalidate(); // } }
}
public class drawingview extends imageview { //drawing path private path drawpath; //drawing , canvas paint private paint drawpaint, canvaspaint; //initial color private int paintcolor = 0xff660000; //canvas private canvas drawcanvas; //canvas bitmap private bitmap canvasbitmap; private float brushsize, lastbrushsize; private boolean erase=false; private boolean moded=false; public drawingview(context context, attributeset attrs){ super(context, attrs); setupdrawing(); } private void setupdrawing(){ //get drawing area setup interaction drawpath = new path(); drawpaint = new paint(); drawpaint.setcolor(paintcolor); drawpaint.setantialias(true); drawpaint.setstrokewidth(brushsize); drawpaint.setstyle(paint.style.stroke); drawpaint.setstrokejoin(paint.join.round); drawpaint.setstrokecap(paint.cap.round); canvaspaint = new paint(paint.dither_flag); brushsize = getresources().getinteger(r.integer.medium_size); lastbrushsize = brushsize; } @override protected void onsizechanged(int w, int h, int oldw, int oldh) { super.onsizechanged(w, h, oldw, oldh); //view given size canvasbitmap = bitmap.createbitmap(w, h, bitmap.config.argb_8888); drawcanvas = new canvas(canvasbitmap); } @override protected void ondraw(canvas canvas) { //draw view canvas.drawbitmap(canvasbitmap, 0, 0, canvaspaint); canvas.drawpath(drawpath, drawpaint); } @override public boolean ontouchevent(motionevent event) { //detect user touch //check if editing or touching if(moded){ float touchx = event.getx(); float touchy = event.gety(); switch (event.getaction()) { case motionevent.action_down: drawpath.moveto(touchx, touchy); break; case motionevent.action_move: drawpath.lineto(touchx, touchy); break; case motionevent.action_up: drawcanvas.drawpath(drawpath, drawpaint); drawpath.reset(); break; default: // return true; } invalidate(); } return true; } public void setcolor(string newcolor){ //set color invalidate(); paintcolor = color.parsecolor(newcolor); drawpaint.setcolor(paintcolor); } public void setbrushsize(float newsize){ //update size float pixelamount = typedvalue.applydimension(typedvalue.complex_unit_dip, newsize, getresources().getdisplaymetrics()); brushsize=pixelamount; drawpaint.setstrokewidth(brushsize); } public void setlastbrushsize(float lastsize){ lastbrushsize=lastsize; } public float getlastbrushsize(){ return lastbrushsize; } public void seterase(boolean iserase){ //set erase true or false erase=iserase; if(erase) drawpaint.setxfermode(new porterduffxfermode(porterduff.mode.clear)); else drawpaint.setxfermode(null); } public void setmode(boolean ismoded){ moded=ismoded; } @suppresswarnings("deprecation") public void setbitmap(bitmap bitmap){ setbackgrounddrawable(new bitmapdrawable(bitmap)); }
}
Comments
Post a Comment