Android GridView通过拖放来重新排列元素

我在我正在处理的应用程序中有一个GridView。 我希望能够通过拖放来重新sortingGridView中的项目。 我已经find了许多ListView的帮助,但没有在GridViews上。 我想实现这个启动器应用程序http://www.youtube.com/watch?v=u5LISE8BU_E&t=5m30s的行为。 有任何想法吗?

Solutions Collecting From Web of "Android GridView通过拖放来重新排列元素"

如果你不解决这个问题,我会提供我的代码。 但它适用于Android 3.0及更高版本,因为我使用Android拖放式框架

grid = (GridView) findViewById(R.id.grid); grid.setAdapter(new DragGridAdapter(items, getActivity())); .... grid.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { GridView parent = (GridView) v; int x = (int) event.getX(); int y = (int) event.getY(); int position = parent.pointToPosition(x, y); if (position > AdapterView.INVALID_POSITION) { int count = parent.getChildCount(); for (int i = 0; i < count; i++) { View curr = parent.getChildAt(i); curr.setOnDragListener(new View.OnDragListener() { @Override public boolean onDrag(View v, DragEvent event) { boolean result = true; int action = event.getAction(); switch (action) { case DragEvent.ACTION_DRAG_STARTED: break; case DragEvent.ACTION_DRAG_LOCATION: break; case DragEvent.ACTION_DRAG_ENTERED: v.setBackgroundResource(R.drawable.shape_image_view_small_gallery_selected); break; case DragEvent.ACTION_DRAG_EXITED: v.setBackgroundResource(R.drawable.shape_image_view_small_gallery_unselected); break; case DragEvent.ACTION_DROP: if (event.getLocalState() == v) { result = false; } else { View droped = (View) event.getLocalState(); GridItem dropItem = ((DragGridItemHolder) droped.getTag()).item; GridView parent = (GridView) droped.getParent(); DragGridAdapter adapter = (DragGridAdapter) parent.getAdapter(); List<GridItem> items = adapter.getItems(); View target = v; GridItem targetItem = ((DragGridItemHolder) target.getTag()).item; int index = items.indexOf(targetItem); items.remove(dropItem); items.add(index, dropItem); adapter.notifyDataSetChanged(); } break; case DragEvent.ACTION_DRAG_ENDED: v.setBackgroundResource(R.drawable.shape_image_view_small_gallery_unselected); break; default: result = false; break; } return result; } }); } int relativePosition = position - parent.getFirstVisiblePosition(); View target = (View) parent.getChildAt(relativePosition); DragGridItemHolder holder = (DragGridItemHolder) target.getTag(); GridItem currentItem = holder.item; String text = currentItem.getFile().getAbsolutePath(); ClipData data = ClipData.newPlainText("DragData", text); target.startDrag(data, new View.DragShadowBuilder(target), target, 0); } } return false; 

和DragGridAdapter

 public class DragGridAdapter extends BaseAdapter{ private Context context; private List<GridItem> items; public DragGridAdapter(List<GridItem> items, Context context){ this.context = context; this.items = items; } @Override public int getCount() { return items.size(); } @Override public Object getItem(int position) { return items.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { DragGridItemHolder holder; if (convertView == null) { holder = new DragGridItemHolder(); ImageView img = new ImageView(context); holder.image = img; convertView = img; convertView.setTag(holder); } else { holder = (DragGridItemHolder) convertView.getTag(); } holder.item = items.get(position); holder.image.setImageBitmap(items.get(position).getBitmap()); return convertView; } public List<GridItem> getItems() { return items; } 

我希望这对你有帮助

我的版本的拖放网格视图https://github.com/askerov/DynamicGrid
它扩展了原来的GridView,支持拖放重新sorting项目,自动滚动如果拖出屏幕。 它在3.0 + api上是完全可用的,但是支持2.2和2.3的限制(没有animation)。

看看thquinn的DraggableGridView ,这是针对Android 2.2(API级别8)开发的。 希望这可以帮助别人:)

使用drag-n-drop框架,而不是循环子节点和设置draglistener,我使用一个DragableLinearLayout作为网格项目布局容器,扩展LinearLayout并实现onDragEvent(DragEvent)方法。

所以你可以像往常一样使用适配器填充网格,大部分拖放代码位于DragableLinearLayout的onDragEvent上

 public class DragableLinearLayout extends LinearLayout { public DragableLinearLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } public DragableLinearLayout(Context context, AttributeSet attrs) { super(context, attrs); } public DragableLinearLayout(Context context) { super(context); } @Override public boolean onDragEvent(DragEvent event) { //in wich grid item am I? GridView parent = (GridView) getParent(); Object item = parent.getAdapter().getItem( parent.getPositionForView(this)); //if you need the database id of your item... Cursor cur = (Cursor) item; long l_id = cur.getLong(cur.getColumnIndex("youritemid")); switch (event.getAction()) { case DragEvent.ACTION_DRAG_STARTED: return true; case DragEvent.ACTION_DRAG_ENTERED: setBackgroundColor(Color.GREEN); invalidate(); return true; case DragEvent.ACTION_DRAG_EXITED: setBackgroundColor(Color.WHITE); invalidate(); return false; case DragEvent.ACTION_DROP: ClipData cd = event.getClipData(); long l_id_start = Long.valueOf(cd.getItemAt(0).getText() .toString()); // Toast.makeText(getContext(), "DROP FROM " + l_id_start + " TO " + l_id, Toast.LENGTH_LONG); //do your stuff ........ //the db requery will be on the onDragEvent.drop of the container //see the listener return false; case DragEvent.ACTION_DRAG_ENDED: setBackgroundColor(Color.WHITE); invalidate(); // return false; } return true; } } private View.OnDragListener listenerOnDragEvent = new View.OnDragListener() { public boolean onDrag(View v, DragEvent event) { // Defines a variable to store the action type for the incoming // event final int action = event.getAction(); switch (action) { case DragEvent.ACTION_DROP: // REQUERY updateDbView(); return false; // break; } return true; } }; 

不容易提供一个简短的答案,因为涉及到数百行代码:您需要拦截开始的拖动动作,通常在onLongClick上,隐藏启动动作的视图,显示一个可以移动的叠加层而用户仍然在触摸行动,最后修改触摸。 最好的方法是在android.widget中扩展标准的GridView。 结果如下所示:

在这里输入图像说明

以下是您可能会觉得有用的YouTubevideo演示: http : //www.youtube.com/watch?v= m4yktX3SWSs&feature=youtu.be

我也在博客的一篇文章中提供了一个更详细的答案,您可能会发现它很有用,因为它提供了一个完整的源代码示例。 链接是: http : //www.pocketmagic.net/2013/11/complex-android-gridview-with-drag-and-drop-functionality/

可能PagedDragDropGrid项目是你所需要的: https : //github.com/mrKlar/PagedDragDropGrid

它提供了自定义的ViewGroup (类似于GridView),具有顺畅的重新sortingfunction(就像在video中一样)。 可能需要一些定制,但这是值得的。

希望它会有所帮助。

这里有一个来自h6ah4i的库 ,它利用Recycler Views来提供一个拖放GridView的重新sortingfunction。