I am having trouble positioning view elements on a custom ViewGroup that I have created, specifically in drag-and-drop situations. I am targeting Android 2.2 and up, so I can't really use the drag-and-drop API that came into existence in Android 3.
My custom ViewGroup is called "NodeGrid" and it extends "RelativeLayout". Its onLayout method is overriden such that it looks like this:
@Override
protected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int arg4)
{
//pxConversion is a multiplier to convert 1 dip to x pixels.
//We will use it to convert dip units into px units.
Resources r = getResources();
float pxConversion = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1, r.getDisplayMetrics());
//Layout the children of this viewgroup
int childCount = this.getChildCount();
for (int i = 0; i < childCount; i++)
{
NodeView view = (NodeView) this.getChildAt(i);
if (view.DataContext != null)
{
int left = (int) (view.DataContext.get_left() * pxConversion);
int top = (int) (view.DataContext.get_top() * pxConversion);
int right = left + (int) (view.DataContext.get_width() * pxConversion);
int bottom = top + (int) (view.DataContext.get_height() * pxConversion);
view.layout(left, top, right, bottom);
}
}
}
The children of "NodeGrid" are of type "NodeView" (as you can see in the above code). NodeView is simply a custom View class that I have created. It contains a member called "DataContext" which is a view-model class that contains some getters/setters with position information about the NodeView instance on the NodeGrid.
My "NodeView" class captures touch events by the user, so the user can simply drag-and-drop a node anywhere on the grid. The event handler looks like this:
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN)
{
isBeingDragged = true;
}
else if (event.getAction() == MotionEvent.ACTION_UP)
{
isBeingDragged = false;
}
else if (event.getAction() == MotionEvent.ACTION_MOVE)
{
if (DataContext != null && isBeingDragged)
{
float xPosition = event.getRawX();
float yPosition = event.getRawY();
DataContext.set_left(xPosition);
DataContext.set_top(yPosition);
this.requestLayout();
}
}
return true;
}
My problem is that the view that is being dragged isn't positioned as I would expect it on my "NodeGrid". It seems that the x-axis position is correct as I drag it, but the y-axis position is offset by some constant amount of pixels at any time. What would be causing this? I have tried using the getX() and getY() methods rather than getRawX() and getRawY(), but that only causes it to be worse.
I wasn't sure whether getRawX() and getRawY() were returning px units or dip units to me, so expecting that it was giving me back px units, I tried converting them to dip units before assigning the new x and y values to the node, but that only decreased the offset, it did not eliminate it.
What could be causing the difference in where I am touching and where the node is being positioned?