android - Drag and move a circle drawn on canvas -
i working on android application should allow user draw circle on canvas , drag . have been able draw lines , circles on it.but cant seem able drag it.
is possible drag object drawn on canvas in android?.for example if detect touch within circle, how delete circle previous position , move current position? have tried invalidate()
.but wont work if user has drawn multiple circle , wants move of them.
it seems might have issues handling of multi-touch / drawing. there's usefull tutorials on android developer site , on android blog.
based on able create example think quite similar you're trying achieve (without complete circle drawing - circles generated single touch):
public class circlesdrawingview extends view { private static final string tag = "circlesdrawingview"; /** main bitmap */ private bitmap mbitmap = null; private rect mmeasuredrect; /** stores data single circle */ private static class circlearea { int radius; int centerx; int centery; circlearea(int centerx, int centery, int radius) { this.radius = radius; this.centerx = centerx; this.centery = centery; } @override public string tostring() { return "circle[" + centerx + ", " + centery + ", " + radius + "]"; } } /** paint draw circles */ private paint mcirclepaint; private final random mradiusgenerator = new random(); // radius limit in pixels private final static int radius_limit = 100; private static final int circles_limit = 3; /** available circles */ private hashset<circlearea> mcircles = new hashset<circlearea>(circles_limit); private sparsearray<circlearea> mcirclepointer = new sparsearray<circlearea>(circles_limit); /** * default constructor * * @param ct {@link android.content.context} */ public circlesdrawingview(final context ct) { super(ct); init(ct); } public circlesdrawingview(final context ct, final attributeset attrs) { super(ct, attrs); init(ct); } public circlesdrawingview(final context ct, final attributeset attrs, final int defstyle) { super(ct, attrs, defstyle); init(ct); } private void init(final context ct) { // generate bitmap used background mbitmap = bitmapfactory.decoderesource(ct.getresources(), r.drawable.up_image); mcirclepaint = new paint(); mcirclepaint.setcolor(color.blue); mcirclepaint.setstrokewidth(40); mcirclepaint.setstyle(paint.style.fill); } @override public void ondraw(final canvas canv) { // background bitmap cover area canv.drawbitmap(mbitmap, null, mmeasuredrect, null); (circlearea circle : mcircles) { canv.drawcircle(circle.centerx, circle.centery, circle.radius, mcirclepaint); } } @override public boolean ontouchevent(final motionevent event) { boolean handled = false; circlearea touchedcircle; int xtouch; int ytouch; int pointerid; int actionindex = event.getactionindex(); // touch event coordinates , make transparent circle switch (event.getactionmasked()) { case motionevent.action_down: // it's first pointer, clear existing pointers data clearcirclepointer(); xtouch = (int) event.getx(0); ytouch = (int) event.gety(0); // check if we've touched inside circle touchedcircle = obtaintouchedcircle(xtouch, ytouch); touchedcircle.centerx = xtouch; touchedcircle.centery = ytouch; mcirclepointer.put(event.getpointerid(0), touchedcircle); invalidate(); handled = true; break; case motionevent.action_pointer_down: log.w(tag, "pointer down"); // secondary pointers, obtain ids , check circles pointerid = event.getpointerid(actionindex); xtouch = (int) event.getx(actionindex); ytouch = (int) event.gety(actionindex); // check if we've touched inside circle touchedcircle = obtaintouchedcircle(xtouch, ytouch); mcirclepointer.put(pointerid, touchedcircle); touchedcircle.centerx = xtouch; touchedcircle.centery = ytouch; invalidate(); handled = true; break; case motionevent.action_move: final int pointercount = event.getpointercount(); log.w(tag, "move"); (actionindex = 0; actionindex < pointercount; actionindex++) { // pointer has moved, search pointer id pointerid = event.getpointerid(actionindex); xtouch = (int) event.getx(actionindex); ytouch = (int) event.gety(actionindex); touchedcircle = mcirclepointer.get(pointerid); if (null != touchedcircle) { touchedcircle.centerx = xtouch; touchedcircle.centery = ytouch; } } invalidate(); handled = true; break; case motionevent.action_up: clearcirclepointer(); invalidate(); handled = true; break; case motionevent.action_pointer_up: // not general pointer pointerid = event.getpointerid(actionindex); mcirclepointer.remove(pointerid); invalidate(); handled = true; break; case motionevent.action_cancel: handled = true; break; default: // nothing break; } return super.ontouchevent(event) || handled; } /** * clears circlearea - pointer id relations */ private void clearcirclepointer() { log.w(tag, "clearcirclepointer"); mcirclepointer.clear(); } /** * search , creates new (if needed) circle based on touch area * * @param xtouch int x of touch * @param ytouch int y of touch * * @return obtained {@link circlearea} */ private circlearea obtaintouchedcircle(final int xtouch, final int ytouch) { circlearea touchedcircle = gettouchedcircle(xtouch, ytouch); if (null == touchedcircle) { touchedcircle = new circlearea(xtouch, ytouch, mradiusgenerator.nextint(radius_limit) + radius_limit); if (mcircles.size() == circles_limit) { log.w(tag, "clear circles, size " + mcircles.size()); // remove first circle mcircles.clear(); } log.w(tag, "added circle " + touchedcircle); mcircles.add(touchedcircle); } return touchedcircle; } /** * determines touched circle * * @param xtouch int x touch coordinate * @param ytouch int y touch coordinate * * @return {@link circlearea} touched circle or null if no circle has been touched */ private circlearea gettouchedcircle(final int xtouch, final int ytouch) { circlearea touched = null; (circlearea circle : mcircles) { if ((circle.centerx - xtouch) * (circle.centerx - xtouch) + (circle.centery - ytouch) * (circle.centery - ytouch) <= circle.radius * circle.radius) { touched = circle; break; } } return touched; } @override protected void onmeasure(final int widthmeasurespec, final int heightmeasurespec) { super.onmeasure(widthmeasurespec, heightmeasurespec); mmeasuredrect = new rect(0, 0, getmeasuredwidth(), getmeasuredheight()); } }
activity contains setcontentview(r.layout.main)
there main.xml following:
<relativelayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_height="match_parent" android:layout_width="match_parent" android:id="@+id/scroller"> <com.example.testapp.circlesdrawingview android:layout_width="match_parent" android:layout_height="match_parent" /> </relativelayout>
Comments
Post a Comment