Android: usando o MotionEvent para arrastar e soltar o posicionamento de Views em um ViewGroup personalizado

Estou com problemas para posicionar elementos de exibição em um ViewGroup personalizado que criei, especificamente em situações de arrastar e soltar. Como estou segmentando o Android 2.2 e superior, não posso realmente usar a API de arrastar e soltar que surgiu no Android 3.

Meu ViewGroup personalizado é chamado "NodeGrid" e estende "RelativeLayout". Está onLayout método @ é substituído de maneira que fique assim:

@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);
        }
    }   
}

Os filhos de "NodeGrid" são do tipo "NodeView" (como você pode ver no código acima). O NodeView é simplesmente uma classe View personalizada que eu criei. Ele contém um membro chamado "DataContext", que é uma classe de modelo de exibição que contém alguns getters / setters com informações de posição sobre a instância do NodeView no NodeGrid.

Minha classe "NodeView" captura eventos de toque do usuário, para que ele possa simplesmente arrastar e soltar um nó em qualquer lugar da grade. O manipulador de eventos fica assim:

@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;
}

Meu problema é que a exibição que está sendo arrastada não está posicionada como seria de esperar no meu "NodeGrid". Parece que a posição do eixo x está correta quando eu a arrasto, mas a posição do eixo y é deslocada por uma quantidade constante de pixels a qualquer momento. O que estaria causando isso? Tentei usar os métodos getX () e getY () em vez de getRawX () e getRawY (), mas isso só faz com que seja pior.

Eu não tinha certeza se getRawX () e getRawY () estavam retornando unidades de px ou unidades de dip para mim, então, esperando que ele estivesse me devolvendo unidades de px, tentei convertê-las em unidades de dip antes de atribuir os novos valores x e y para o nó, mas que apenas diminuiu o deslocamento, não o eliminou.

O que pode estar causando a diferença de onde estou tocando e onde o nó está sendo posicionado?

questionAnswers(1)

yourAnswerToTheQuestion