Android列表视图拖放排序

时间:2010-05-25 23:51:02

标签: android listview

我在列表视图中有一个记录列表,我希望用户能够使用拖放方法重新排序。我已经看到这在其他应用程序中实现,但我还没有找到它的教程。它必须是其他人需要的东西。有人能指点我做一些代码吗?

7 个答案:

答案 0 :(得分:85)

我已经有一段时间了。很难做到正确,而且我没有声称我这样做,但到目前为止我对它很满意。我的代码和几个演示可以在

找到

它的使用非常类似于TouchInterceptor(代码所基于的),尽管已经进行了重要的实现更改。

DragEortListView在拖动和随机播放项目时具有平滑且可预测的滚动功能。项目随机播放与拖动/浮动项目的位置更加一致。支持异构高度列表项。拖动是可自定义的(我演示了快速拖动滚动浏览长列表 - 而不是想到应用程序)。页眉/页脚受到尊重。等等。??看一看。

答案 1 :(得分:18)

为了谷歌的目的,我们添加了这个答案..

最近有一集DevBytes(ListView Cell Dragging and Rearranging)解释了如何做到这一点

您可以找到here示例代码here

此代码基本上做的是它通过dynamic listview的扩展名创建listview,支持单元格拖放和交换。因此,您可以使用DynamicListView代替基本ListView,这就是您使用拖放实现了ListView。

答案 2 :(得分:15)

现在使用ItemTouchHelper实现RecyclerView非常简单。只需覆盖onMove的<{1}}方法:

ItemTouchHelper.Callback

可以在medium.com上找到相当不错的教程:Drag and Swipe with RecyclerView

答案 3 :(得分:5)

我发现DragSortListView效果很好,虽然开始使用它可能会更容易。以下是在Android Studio中使用内存列表的简要教程:

  1. 将此添加到您应用的build.gradle依赖项:

    compile 'asia.ivity.android:drag-sort-listview:1.0' // Corresponds to release 0.6.1
    
  2. 通过创建或添加到values/ids.xml

    为拖动句柄ID创建资源
    <resources>
        ... possibly other resources ...
        <item type="id" name="drag_handle" />
    </resources>
    
  3. 为包含您最喜欢的拖动句柄图像的列表项创建布局,并将其ID分配给您在步骤2中创建的ID(例如drag_handle)。

  4. 创建一个DragSortListView布局,如下所示:

    <com.mobeta.android.dslv.DragSortListView
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:dslv="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        dslv:drag_handle_id="@id/drag_handle"
        dslv:float_background_color="@android:color/background_light"/>
    
  5. 使用ArrayAdapter覆盖设置getView衍生产品,以呈现列表项目视图。

        final ArrayAdapter<MyItem> itemAdapter = new ArrayAdapter<MyItem>(this, R.layout.my_item, R.id.my_item_name, items) { // The third parameter works around ugly Android legacy. http://stackoverflow.com/a/18529511/145173
            @Override public View getView(int position, View convertView, ViewGroup parent) {
                View view = super.getView(position, convertView, parent);
                MyItem item = getItem(position);
                ((TextView) view.findViewById(R.id.my_item_name)).setText(item.getName());
                // ... Fill in other views ...
                return view;
            }
        };
    
        dragSortListView.setAdapter(itemAdapter);
    
  6. 设置一个drop listener,在项目被删除时重新排列项目。

        dragSortListView.setDropListener(new DragSortListView.DropListener() {
            @Override public void drop(int from, int to) {
                MyItem movedItem = items.get(from);
                items.remove(from);
                if (from > to) --from;
                items.add(to, movedItem);
                itemAdapter.notifyDataSetChanged();
            }
        });
    

答案 4 :(得分:5)

DragListView lib非常干净,非常支持自定义动画,例如高程动画。它仍然定期维护和更新。

以下是您使用它的方式:

1:首先将lib添加到gradle

dependencies {
    compile 'com.github.woxthebox:draglistview:1.2.1'
}

2:从xml添加列表

<com.woxthebox.draglistview.DragListView
    android:id="@+id/draglistview"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

3:设置拖动侦听器

mDragListView.setDragListListener(new DragListView.DragListListener() {
    @Override
    public void onItemDragStarted(int position) {
    }

    @Override
    public void onItemDragEnded(int fromPosition, int toPosition) {
    }
});

4:创建从DragItemAdapter重写的适配器

public class ItemAdapter extends DragItemAdapter<Pair<Long, String>, ItemAdapter.ViewHolder>
    public ItemAdapter(ArrayList<Pair<Long, String>> list, int layoutId, int grabHandleId, boolean dragOnLongPress) {
        super(dragOnLongPress);
        mLayoutId = layoutId;
        mGrabHandleId = grabHandleId;
        setHasStableIds(true);
        setItemList(list);
}

5:实现从DragItemAdapter.ViewHolder

扩展的视图
public class ViewHolder extends DragItemAdapter.ViewHolder {
    public TextView mText;

    public ViewHolder(final View itemView) {
        super(itemView, mGrabHandleId);
        mText = (TextView) itemView.findViewById(R.id.text);
    }

    @Override
    public void onItemClicked(View view) {
    }

    @Override
    public boolean onItemLongClicked(View view) {
        return true;
    }
}

有关详细信息,请转至https://github.com/woxblom/DragListView

答案 5 :(得分:2)

我最近偶然发现了这个很棒的Gist,它提供了一个拖拽排序ListView的工作实现,不需要外部依赖。

基本上,它包括创建自定义适配器,将ArrayAdapter扩展为包含ListView的活动的内部类。在此适配器上,然后将onTouchListener设置为列表项,以指示拖动的开始。

在该Gist中,他们将侦听器设置为List Item的布局的特定部分(项目的“句柄”),因此不会通过按下它的任何部分而意外移动它。就个人而言,我更愿意选择onLongClickListener,但这取决于您自己决定。这是该部分的摘录:

public class MyArrayAdapter extends ArrayAdapter<String> {

    private ArrayList<String> mStrings = new ArrayList<String>();
    private LayoutInflater mInflater;
    private int mLayout;

    //constructor, clear, remove, add, insert...

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        ViewHolder holder;

        View view = convertView;
        //inflate, etc...

        final String string = mStrings.get(position);
        holder.title.setText(string);

        // Here the listener is set specifically to the handle of the layout
        holder.handle.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent motionEvent) {
                if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
                    startDrag(string);
                    return true;
                }
                return false;
            }
        });

        // change color on dragging item and other things...         

        return view;
    }
}

这还涉及向onTouchListener添加ListViewmListView.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View view, MotionEvent event) { if (!mSortable) { return false; } switch (event.getAction()) { case MotionEvent.ACTION_DOWN: { break; } case MotionEvent.ACTION_MOVE: { // get positions int position = mListView.pointToPosition((int) event.getX(), (int) event.getY()); if (position < 0) { break; } // check if it's time to swap if (position != mPosition) { mPosition = position; mAdapter.remove(mDragString); mAdapter.insert(mDragString, mPosition); } return true; } case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_OUTSIDE: { //stop drag state stopDrag(); return true; } } return false; } }); 检查项目是否被拖动,处理交换和失效,并停止拖动状态。该部分的摘录:

stopDrag

最后,这里是startDragpublic void startDrag(String string) { mPosition = -1; mSortable = true; mDragString = string; mAdapter.notifyDataSetChanged(); } public void stopDrag() { mPosition = -1; mSortable = false; mDragString = null; mAdapter.notifyDataSetChanged(); } 方法的样子,它们处理启用和禁用拖动过程:

catch

答案 6 :(得分:0)

我基于 RecyclerView 构建了一个新库,请查看

为此任务签出我的新库 https://github.com/ueen/SortView/