2

GridViews에 대한 드래그 앤 드롭 라이브러리를 코딩하는 과정에 있습니다. 나는 거의 완료 ... 그러나, 나는 지금 ACTION_DROP에 성가신 NullPointerException을 얻고있다. ViewGroup 소스 코드 인 1147과 1153 줄을 가리키며 드래그 이벤트를 재생하려고 할 때 null 포인터를 얻는다 고합니다.ViewGroup 던지고 dispatchDragEvent에 NullPointerException

내 처리의 배경 : 기본적으로 GridView의 사용자 지정 어댑터에 OnDragListener를 포함하고 있습니다. GridView 어댑터를 설정할 때 사용자 (프로그래머)가 GridView 어댑터를 설정할 때 확장 할 뷰, 포함 할 이미지 등을 선택할 수 있습니다. 그런 다음 DragViewerAdapter (GridView의 어댑터)에서 getView가 호출 될 때 , 지정된 OnGetViewListener를 호출하여 사용자가 원하는보기를 가져옵니다. 드래그 앤 드롭을위한 컨테이너로 서기 위해 빈 LinearLayout을 생성합니다. 사용자의보기가 컨테이너에 추가되고 끌기 수신기가 컨테이너로 설정되고 컨테이너의 태그가 GridView의 해당 데이터 수집으로 설정된 다음 컨테이너가 getView()에 대해 반환 된보기입니다.

끌어서 놓기 GridView 항목의 전체 프로세스는 컨테이너와 해당 태그를 기반으로합니다. 사용자가 항목을 드래그 할 때 두 GridView 항목이 바뀌면 기본적으로 마우스를 올려 놓은 셀에서보기가 제거되고 끌어온보기가 바로 왼쪽에있는 셀에 추가됩니다. 이렇게하면 항목을 시각적으로 "교환"할 수 있습니다.

public class DragDropAdapter extends BaseAdapter { 
... 
    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
     LinearLayout containerView = new LinearLayout(mContext); 
     containerView.setLayoutParams(new GridView.LayoutParams(
       GridView.LayoutParams.MATCH_PARENT, 
       GridView.LayoutParams.MATCH_PARENT)); 
     View itemView = mGetViewListener.getView(position, convertView, parent); 

     itemView.setTag(mItems.get(position)); 
     containerView.setTag(mItems.get(position)); 
     containerView.addView(itemView); 
     containerView.setOnDragListener(new ItemDragListener()); 

     return containerView; 
    } 

    ... 

    View mExitedView = null; 

    public class ItemDragListener implements OnDragListener { 

     public ItemDragListener() { 

     } 

     private void swapCards(int startPosition, View viewToSwap) { 
      if (mExitedView == null) { 
       mExitedView = mGridView.getChildAt(startPosition); 
      } 

      ViewGroup viewToSwapContainer = (ViewGroup) viewToSwap; 
      ViewGroup exitedViewContainer = (ViewGroup) mExitedView; 

      View childViewToSwap = viewToSwapContainer.getChildAt(0); 
      View childViewExited = exitedViewContainer.getChildAt(0); 

      int enteredPosition = ItemCoordinatesHelper 
        .getGridPosition(viewToSwap); 
      int exitedPosition = ItemCoordinatesHelper 
        .getGridPosition(mExitedView); 

      Object itemToSwap = viewToSwap.getTag(); 
      Object exitedItem = mExitedView.getTag(); 

      viewToSwapContainer.setVisibility(View.INVISIBLE); 
      viewToSwapContainer.setTag(exitedItem); 
      viewToSwapContainer.removeAllViews(); 
      if (childViewExited.getParent() != null) 
       ((ViewGroup) childViewExited.getParent()).removeAllViews(); 
      viewToSwapContainer.addView(childViewExited); 

      exitedViewContainer.setTag(itemToSwap); 
      exitedViewContainer.removeAllViews(); 
      if (childViewToSwap.getParent() != null) 
       ((ViewGroup) childViewToSwap.getParent()).removeAllViews(); 
      exitedViewContainer.addView(childViewToSwap); 
      exitedViewContainer.setVisibility(View.VISIBLE); 
     } 

      ... 

     @Override 
     public boolean onDrag(View v, DragEvent event) { 
      // TODO Auto-generated method stub 

      View heldView = (View) event.getLocalState(); 
      int startPosition = ItemCoordinatesHelper.getGridPosition(heldView); 

      switch (event.getAction()) { 
      case DragEvent.ACTION_DRAG_STARTED: 
       break; 
      case DragEvent.ACTION_DRAG_ENTERED: 
       swapCards(startPosition, v); 
       break; 
      case DragEvent.ACTION_DRAG_EXITED: 
       mExitedView = v; 
       break; 
      case DragEvent.ACTION_DROP: 
       View view = (View) event.getLocalState(); 
       v.setVisibility(View.VISIBLE); 
       view.setVisibility(View.VISIBLE); 
       break; 
      case DragEvent.ACTION_DRAG_ENDED: 
       commitChangesToAdapter(); 
       mExitedView = null; 
       break; 
      default: 
       break; 
      } 

      return true; 
     } 
    } 
} 

은 이제 ACTION_DRAG_ENDED에서 NullPointerException이 때문에 내가 제대로 소스 코드를 이해하고있어 경우는, 드래그 이벤트를 재활용 할 수없는 몇 가지 이유로 발생되고있다.

업데이트 :

@Override 
1100 public boolean dispatchDragEvent(DragEvent event) { 
1101  boolean retval = false; 
1102  final float tx = event.mX; 
1103  final float ty = event.mY; 
1104 
1105  ViewRootImpl root = getViewRootImpl(); 
1106 
1107  // Dispatch down the view hierarchy 
1108  switch (event.mAction) { 
1109  case DragEvent.ACTION_DRAG_STARTED: { 
1110   // clear state to recalculate which views we drag over 
1111   mCurrentDragView = null; 
1112 
1113   // Set up our tracking of drag-started notifications 
1114   mCurrentDrag = DragEvent.obtain(event); 
1115   if (mDragNotifiedChildren == null) { 
1116    mDragNotifiedChildren = new HashSet<View>(); 
1117   } else { 
1118    mDragNotifiedChildren.clear(); 
1119   } 
1120 
1121   // Now dispatch down to our children, caching the responses 
1122   mChildAcceptsDrag = false; 
1123   final int count = mChildrenCount; 
1124   final View[] children = mChildren; 
1125   for (int i = 0; i < count; i++) { 
1126    final View child = children[i]; 
1127    child.mPrivateFlags2 &= ~View.DRAG_MASK; 
1128    if (child.getVisibility() == VISIBLE) { 
1129     final boolean handled = notifyChildOfDrag(children[i]); 
1130     if (handled) { 
1131      mChildAcceptsDrag = true; 
1132     } 
1133    } 
1134   } 
1135 
1136   // Return HANDLED if one of our children can accept the drag 
1137   if (mChildAcceptsDrag) { 
1138    retval = true; 
1139   } 
1140  } break; 
1141 
1142  case DragEvent.ACTION_DRAG_ENDED: { 
1143   // Release the bookkeeping now that the drag lifecycle has ended 
1144   if (mDragNotifiedChildren != null) { 
1145    for (View child : mDragNotifiedChildren) { 
1146     // If a child was notified about an ongoing drag, it's told that it's over 
1147     child.dispatchDragEvent(event); //<-- NULL POINTER HERE 
1148     child.mPrivateFlags2 &= ~View.DRAG_MASK; 
1149     child.refreshDrawableState(); 
1150    } 
1151 
1152    mDragNotifiedChildren.clear(); 
1153    mCurrentDrag.recycle(); //<-- NULL POINTER HERE 
1154    mCurrentDrag = null; 
1155   } 

거기에 어떤 전문가들은 어떤 아이디어가 : 여기가 예외를 throw 출처는?

+0

더 많은 코드를 게시 할 수 있습니까? 특히 mContext가 정의되고 설정되는 방법은 무엇입니까? – nmw

+0

mContext는 어댑터를 설정하는 활동에서 어댑터의 생성자로 전달됩니다. – dennisdrew

답변

3

케이스 DragEvent.ACTION_DRAG_ENDED을 처리 할 때 드래그 가능한보기를 포함하는 ViewGroup을 제거 했으므로 동일한 예외가 있습니다.

내 솔루션 : post(runnable) 메서드를 사용하여 removeView 메서드 실행을 지연하십시오.

관련 문제