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 출처는?
더 많은 코드를 게시 할 수 있습니까? 특히 mContext가 정의되고 설정되는 방법은 무엇입니까? – nmw
mContext는 어댑터를 설정하는 활동에서 어댑터의 생성자로 전달됩니다. – dennisdrew