Retrieving precise drop position of Android View -


the target application allows user drag/drop views move them in framelayout or store them in linearlayout.

the overall mechanism works can't precision need on position when view dropped, "jumps" little further. how retrieve position of drag shadow put dropped view shadow was, in order avoid "jump" artefact?

for sake of example, layout pretty simple, here's overview 2 textview objects can moved around (i removed details):

<linearlayout xmlns:android="http://schemas.android.com/apk/res/android">     <linearlayout android:id="@+id/repository"/>     <framelayout android:id="@+id/frame">         <textview android:id="@+id/view1"/>         <textview android:id="@+id/view2"/>     </framelayout> </linearlayout> 

first, improve start position of drag shadow itself, i'm overriding onprovideshadowmetrics. that, view doesn't jump when user starts dragging it:

private class mydragshadowbuilder extends view.dragshadowbuilder {     private float x, y;      public mydragshadowbuilder(view view, float x, float y) {         super(view);         this.x = x;         this.y = y;     }      @override     public void onprovideshadowmetrics(point size, point touchpoint) {         super.onprovideshadowmetrics(size, touchpoint);         touchpoint.set((int) x, (int) y);     } } 

then implementation of ontouchlistener used start drag operation:

private class longclicklistener implements view.ontouchlistener {     @override     public boolean ontouch(view v, motionevent event) {         if (event.getaction() == motionevent.action_down) {             textview tv = (textview) v;             if (tv != null) {                 clipdata data = clipdata.newplaintext("", "");                 mydragshadowbuilder shadowbuilder = new mydragshadowbuilder(v, event.getx(), event.gety());                 v.startdrag(data, shadowbuilder, v, 0);                 v.setvisibility(view.invisible);                 return true;             }         }         return false;     } } 

the drop operation retrieve initial x, y position of "finger" in view, position view shadow.

private class draglistener implements view.ondraglistener {     private final class<?> framelayout_class = framelayout.class;     private final class<?> linearlayout_class = linearlayout.class;     private drawable entershape = getresources().getdrawable(r.drawable.shape_droptarget);     private drawable normalshape = getresources().getdrawable(r.drawable.shape);      @override     public boolean ondrag(view v, dragevent event) {         int action = event.getaction();         switch (action) {             case dragevent.action_drag_started:                 break;             case dragevent.action_drag_entered:                 v.setbackground(entershape);                 break;             case dragevent.action_drag_exited:                 v.setbackground(normalshape);                 break;             case dragevent.action_drop:                 view view = (view) event.getlocalstate();                 viewgroup owner = (viewgroup) view.getparent();                 viewgroup container = (viewgroup) v;                 if (container.getclass() == framelayout_class) {                     // if shadowbuilder here,                     // able retrieve initial (x,y) offset                     // or final (x,y) position, both work...                     view.setx(event.getx());                     view.sety(event.gety());                 } else if (container.getclass() == linearlayout_class) {                     // in linearlayout remove offset:                     view.setx(0);                     view.sety(0);                 } else                     return false;                 owner.removeview(view);                 container.addview(view);                 view.setvisibility(view.visible);                 break;             case dragevent.action_drag_ended:                 v.setbackground(normalshape);             default:                 break;         }         return true;     } } 

all set in oncreate method of activity:

@override public void oncreate(bundle savedinstancestate) {     super.oncreate(savedinstancestate);     setcontentview(r.layout.main);     view v = findviewbyid(r.id.view1);     v.setontouchlistener(new longclicklistener());     v = findviewbyid(r.id.view2);     v.setontouchlistener(new longclicklistener());     v = findviewbyid(r.id.frame);     v.setondraglistener(new draglistener());     v = findviewbyid(r.id.repository);     v.setondraglistener(new draglistener()); } 

thanks in advance tip on how should information!


edit: pass data in clipdata awkward (especially if need pass larger data sets in future, serialization overkill here):

clipdata data = clipdata.newplaintext(     "pos",      string.format("%d %d", (int)event.getx(), (int)event.gety())); v.startdrag(data, shadowbuilder, v, 0); 

...

if (container.getclass() == framelayout_class) {     clipdata data = event.getclipdata();     string[] pos = ((string)data.getitemat(0).gettext()).split(" ");     int x = integer.valueof(pos[0]);     int y = integer.valueof(pos[1]);     view.setx(event.getx() - x);     view.sety(event.gety() - y); 


Comments

Popular posts from this blog

linux - xterm copying to CLIPBOARD using copy-selection causes automatic updating of CLIPBOARD upon mouse selection -

c++ - qgraphicsview horizontal scrolling always has a vertical delta -