4

특히 만든 드래그 앤 드롭 상황에서 내가 만든 사용자 정의 ViewGroup에서 뷰 요소를 배치하는 데 문제가 있습니다. Android 2.2 이상을 타겟팅하므로 Android 3에 제공된 드래그 앤 드롭 API를 실제로 사용할 수 없습니다.Android : MotionEvent를 사용하여 사용자 정의 ViewGroup에서 뷰의 드래그 앤 드롭 위치 지정

내 사용자 정의 ViewGroup은 "NodeGrid"라고하며 "RelativeLayout"을 확장합니다. 그 onLayout 방법은 다음과 같습니다하도록 오버라이드 (override)한다 : "NodeGrid"의

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

아이들은 유형 (위의 코드에서 볼 수 있듯이) "NodeView"에 있습니다. NodeView는 내가 만든 사용자 정의 뷰 클래스입니다. 여기에는 NodeGrid의 NodeView 인스턴스에 대한 위치 정보가있는 getter/setter가 포함 된 뷰 모델 클래스 인 "DataContext"라는 멤버가 포함되어 있습니다.

내 "NodeView"클래스는 사용자가 터치 이벤트를 캡처하므로 사용자는 그리드의 아무 곳이나 노드를 드래그 앤 드롭 할 수 있습니다. 이벤트 핸들러는 다음과 같습니다

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

내 문제는 내가 내 "NodeGrid"에 그것을 기대하는 것처럼 끌고있는 뷰가 배치되지 않는 것입니다. 드래그하면 x 축의 위치는 정확하지만 y 축의 위치는 언제든지 일정한 픽셀만큼 오프셋됩니다. 이 문제의 원인은 무엇입니까? getRawX() 및 getRawY()보다는 getX() 및 getY() 메서드를 사용하여 시도했지만 더 나쁜 경우에만 발생합니다.

getRawX() 및 getRawY()가 px 단위 또는 dip 단위를 나에게 반환했는지 확신 할 수 없기 때문에 px 단위를 돌려 주었을 것으로 예상되어 새로운 x를 할당하기 전에 dip 단위로 변환하려고 시도했습니다. y 값을 노드에 전달했으나 오프셋 만 줄이면 제거되지 않았습니다.

내가 만지고있는 곳과 노드가있는 곳의 차이를 일으키는 원인은 무엇일까요? 분명히 다른 사람이 이런 상황을 발생하지 것을

답변

1

매우 놀랄 ...

몇 가지 조사 후, 나는 부분적으로 문제를 해결할 수 있었다.

getRawX() 및 getRawY()가 작동하지 않는 이유는 앱의 일부가 아닌 화면의 절대 화면 위치에서 작동하기 때문입니다 (예 : Android 메뉴 전체 화면 모드가 아니면 화면 상단). 이 좌표를 사용하는 것은, 특히 그들을 정당화하고 그들을 "내 애플 리케이션"좌표로 변환하는 명백한 방법이없는 것처럼, hackish처럼 보였다.

getX() 및 getY()는 내가 말할 수있는 한 터치 된 객체에 상대적 인 것처럼 보입니다.

float xPosition = event.getX(); 
float yPosition = event.getY(); 

DataContext.set_left(DataContext.get_left() + xPosition); 
DataContext.set_top(DataContext.get_top() + yPosition); 

this.requestLayout(); 

이 확실히 도움을 ...하지만 여전히 완벽한 솔루션이 될 것 같지 않습니다 계정이 점을 고려했을 때, 나는 onTouchEvent의 코드 읽기로 변경되었습니다. 일반적으로 뷰 객체는 마우스 커서/손가락과 함께 드래그되지만, 매우 불안해하며 화면에서 벗어나 화면을 벗어날 수있는 시간이 있습니다.

나는 아마도 "역사적인 좌표"를 메서드에 포함시키지 않았기 때문일 수도 있다고 생각했습니다.난 그냥 위에 표시된 코드 직전에이 코드를 넣어하는 방법으로 역사적 좌표를 통합하는 시도 :

int historySize = event.getHistorySize(); 
for (int i = 0; i < historySize; i++) 
{ 
    float xPosition = event.getHistoricalX(i); 
    float yPosition = event.getHistoricalY(i); 

    DataContext.set_left(DataContext.get_left() + xPosition); 
    DataContext.set_top(DataContext.get_top() + yPosition); 

    this.requestLayout(); 
} 

불행하게도 ...이 실제로 악화, 그래서 하나 내가 제대로 역사적 좌표를 사용하고 있지 않다거나 그들은 전혀 사용하지 않아야합니다. 나는 그 문제와 관련하여 또 다른 질문을 올릴 것이지만 이것은 위의 나의 질문에 대한 부분적인 대답으로 충분할 것이다.

+0

안녕하세요, 문제를 해결 했습니까? 전체 다운로드 코드를 가지고 있습니까? – Ricardo