Android ListView Drag and Drop for Honeycomb and ICS "Error: Reporting drop result: false"



我一直在尝试创建一个可以使用拖放进行排序的列表视图。

我试图遵循这里的Android指南和这里Git上提供的一些源代码。另外,我不想使用音乐应用程序示例,因为我正在尝试使用Honeycomb及更高版本中提供的新工具。

到目前为止,我已经成功地创建了列表,我可以拖动项目。不幸的是,当我将该项目拖放到列表中时,出现以下错误:

"I/ViewRoot(22739):报告丢弃结果:假"。

我怀疑我的丢弃侦听器不是在正确的项目上创建的,因此永远不会调用丢弃。这里有一些源代码,非常感谢您的帮助。

列表的 XML:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/dropTarget"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
     android:layout_weight="1">
    <ListView
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:id="@android:id/list" >
    </ListView>
</LinearLayout>

我的列表视图:我还没有能够进入"ACTION_DROP"事件,因此代码没有测试。只是我正在做的事情。我的主要问题是我从不进入ACTION_DROP。

public class procedureListView extends ListActivity {
    private ListView mListView = null;
    private ArrayAdapter<String> mArrayAdapter = null;
    private View layoutDropArea = null;
    public void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.list);
          String[] countries = getResources().getStringArray(R.array.arrayOfStuff);
          mArrayAdapter = new ArrayAdapter<String>(this, R.layout.list_item, countries);
          setListAdapter(mArrayAdapter);
          mListView = getListView();
          mListView.setTextFilterEnabled(true);
          layoutDropArea = findViewById(R.id.dropTarget);
          setupDragDrop();
    }
    /**
     * Setup what to do when we drag list items
     */
    public void setupDragDrop(){
        mListView.setOnItemLongClickListener(new OnItemLongClickListener() {
            public boolean onItemLongClick(AdapterView<?> arg0, View v, int position, long arg3){
                String value = (String) ((TextView) v).getText();
                ClipData data = ClipData.newPlainText("procedure", value);
                v.startDrag(data, new mDragShadowBuilder(v), null, 0);          
                return true;
            }
        });
        myDragListener mDragListener = new myDragListener();
        //mListView.setOnDragListener(mDragListener);
        layoutDropArea.setOnDragListener(mDragListener);

    }
    protected class myDragListener implements OnDragListener{
        public boolean onDrag(View v, DragEvent event) {
            final int action = event.getAction();
            switch (action) {
                case DragEvent.ACTION_DRAG_ENTERED:
                    v.setBackgroundColor(Color.GRAY);
                    break;
                case DragEvent.ACTION_DRAG_EXITED:
                    v.setBackgroundColor(Color.TRANSPARENT);
                    break;
                case DragEvent.ACTION_DRAG_STARTED:
                    break;
                case DragEvent.ACTION_DRAG_LOCATION:
                    v.setVisibility(View.VISIBLE);
                // return processDragStarted(event);
                case DragEvent.ACTION_DROP:
                    v.setBackgroundColor(Color.TRANSPARENT);
                    int newPosition = mListView.getPositionForView(v);
                    if (newPosition != ListView.INVALID_POSITION)
                        return processDrop(event, newPosition);
                    else
                        return false;
            }
            return false;
        }
    }
    private boolean processDrop(DragEvent event, int newPosition) {
        ClipData data = event.getClipData();
        if (data != null) {
            if (data.getItemCount() > 0) {
                Item item = data.getItemAt(0);
                String value = item.toString();
                updateViewsAfterDropComplete(value, newPosition);
                return true;
            }
        }
        return false;
    }
    private void updateViewsAfterDropComplete(String listItem, int index) {
        Log.d("InsertItem", "Position: "+ index);
        mArrayAdapter.insert(listItem, index);
        mArrayAdapter.notifyDataSetChanged();
    }
    private boolean processDragStarted(DragEvent event) {
        ClipDescription clipDesc = event.getClipDescription();
        if (clipDesc != null) {
            return clipDesc.hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN);
        }
        return false;
    }
}

非常感谢您的帮助!

更新:

我不太清楚为什么。但是当我将开关大小写更改为此时,它似乎有效:

switch (action) {
                case DragEvent.ACTION_DRAG_ENTERED:
                    //v.setBackgroundColor(Color.GRAY);
                    return false;
                case DragEvent.ACTION_DRAG_EXITED:
                    //v.setBackgroundColor(Color.TRANSPARENT);
                    return true;
                case DragEvent.ACTION_DRAG_STARTED:
                    return true;
                case DragEvent.ACTION_DRAG_LOCATION:
                    //v.setVisibility(View.VISIBLE);
                    return false;
                // return processDragStarted(event);
                case DragEvent.ACTION_DROP:
                    v.setBackgroundColor(Color.TRANSPARENT);
                    int newPosition = mListView.pointToPosition((int)(event.getX()),(int) event.getY());
                    Log.d("Position", Integer.toString(newPosition));
                    if (newPosition != ListView.INVALID_POSITION)
                        return processDrop(event, newPosition);
                    else
                        return false;
                default:
                    return true;
            }

您的更新解决了这个问题,因为您必须在DragEvent.ACTION_DRAG_STARTED时从onDrag返回true,以便继续接收该侦听器的拖动事件。在更新中,对于这种情况,您将返回true,因此您继续收到拖动事件并且删除逻辑正常工作。

如果不返回DragEvent.ACTION_DRAG_STARTED事例的true,则侦听器将不会获得除DragEvent.ACTION_DRAG_ENDED 之外的任何其他事件。

最新更新