RecyclerView ItemTouchHelper 拖动排序

RecyclerView ItemTouchHelper 踩坑之旅


要实现的功能:

  • recyclerview item适配器不同类型的Item addHeaderView
  • item headerview 不可以拖动交换位置

动手操作前先过一边原理 :站在大神的肩膀上看世界

谷歌大大这么说:

This is a utility class to add swipe to dismiss and drag & drop support to RecyclerView.

It works with a RecyclerView and a Callback class, which configures what type of interactions are enabled and also receives events when user performs these actions.
This class is designed to work with any LayoutManager but for certain situations, it can be optimized for your custom LayoutManager by extending methods in the ItemTouchHelper.Callback class or implementing ItemTouchHelper.ViewDropHandler interface in your LayoutManager.
  • RecylcerView Item拖动排序 滑动删除 依靠android.support.v7.widget.helper.ItemTouchHelper类
  • 自定义ItemTouchHelper.callBack 继承 getMoventFlags\onMove\onSwiped 方法

谷歌大大这么说

This class is the contract between ItemTouchHelper and your application. It lets you control which touch behaviors are enabled per each ViewHolder and also receive callbacks when user performs these actions.
To control which actions user can take on each view, you should override getMovementFlags(RecyclerView, ViewHolder) and return appropriate set of direction flags. (LEFT, RIGHT, START, END, UP, DOWN). You can use makeMovementFlags(int, int) to easily construct it. Alternatively, you can use ItemTouchHelper.SimpleCallback.
If user drags an item, ItemTouchHelper will call onMove(recyclerView, dragged, target). Upon receiving this callback, you should move the item from the old position (dragged.getAdapterPosition()) to new position (target.getAdapterPosition()) in your adapter and also call notifyItemMoved(int, int). To control where a View can be dropped, you can override canDropOver(RecyclerView, ViewHolder, ViewHolder). When a dragging View overlaps multiple other views, Callback chooses the closest View with which dragged View might have changed positions. Although this approach works for many use cases, if you have a custom LayoutManager, you can override chooseDropTarget(ViewHolder, java.util.List, int, int) to select a custom drop target.
When a View is swiped, ItemTouchHelper animates it until it goes out of bounds, then calls onSwiped(ViewHolder, int). At this point, you should update your adapter (e.g. remove the item) and call related Adapter#notify event.


public class MyRecyclerViewTouchCallBack extends ItemTouchHelper.Callback {
private ItemTouchListencer mListencer;

public MyRecyclerViewTouchCallBack(ItemTouchListencer listencer) {
    mListencer = listencer;
}

@Override
public boolean isLongPressDragEnabled() {
    return super.isLongPressDragEnabled();
}

@Override
public boolean isItemViewSwipeEnabled() {
    return super.isItemViewSwipeEnabled();
}

@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
    RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
    /*dragFlags--拖动标志*/
    /*swipeFlags--滑动标志 GridLayoutManager滑动删除关闭*/
    if (layoutManager instanceof GridLayoutManager) {
        final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
        final int swipeFlags = 0;
        return makeMovementFlags(dragFlags, swipeFlags);
    } else if (layoutManager instanceof LinearLayoutManager) {
        final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
        final int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END;
        return makeMovementFlags(dragFlags, swipeFlags);
    } else {
        final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
        final int swipeFlags = 0;
        return makeMovementFlags(dragFlags, swipeFlags);
    }
}


@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
    int startIndex = viewHolder.getAdapterPosition();
    int endIndex = target.getAdapterPosition();
    if (mListencer != null) {
        mListencer.itemMove(startIndex, endIndex);
    }
    return true;
}

@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
    if (mListencer != null) {
        mListencer.itemSwipe(direction);
    }
}

}

控制器 RecylerViewAdapter

public class ItemTouchRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> implements ItemTouchListencer {

private static final int TYPE_HEADER_VIEW = 0;
private static final int TYPE_CONTENT = 1;
private ArrayList<String> mStrings;
private View mHeaderView;

public ItemTouchRecyclerViewAdapter(ArrayList<String> strings) {
    mStrings = strings;
}

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    if (viewType == TYPE_HEADER_VIEW) {
        View view = View.inflate(parent.getContext(), R.layout.heander_view_item, null);
        return new HeaderViewHolder(view);
    } else if (viewType == TYPE_CONTENT) {
        View view = View.inflate(parent.getContext(), R.layout.gridview_item, null);
        return new GridViewHolder(view);
    }
    return null;
}

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
    if (holder instanceof GridViewHolder) {
        GridViewHolder gridViewHolder = (GridViewHolder) holder;
        String str = mStrings.get(position - 1);
        gridViewHolder.mTxt.setText(str);
    }else if(holder instanceof HeaderViewHolder){
        HeaderViewHolder headerViewHolder = (HeaderViewHolder) holder;
    }
}

@Override
public int getItemCount() {
//        return mHeaderView != null ? mStrings.size() + 1 : mStrings.size();
    return mStrings.size();

}


@Override
public int getItemViewType(int position) {
    if (position == 0) {
        return TYPE_HEADER_VIEW;
    } else {
        return TYPE_CONTENT;
    }
}

/**
 * 拖动回调接口
 *
 * @param startIndex --开始位置
 * @param endIndex   --交换结束位置
 */
@Override
public void itemMove(int startIndex, int endIndex) {
    if (startIndex == 0 || endIndex == 0) {
        return;
    }
    Collections.swap(mStrings, startIndex, endIndex);
    notifyItemMoved(startIndex, endIndex);
}

/**
 * 滑动删除
 *
 * @param delIndex
 */
@Override
public void itemSwipe(int delIndex) {

}

}

调用初始化

public class MainActivity extends AppCompatActivity {

    private RecyclerView mRecyclerView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mRecyclerView = (RecyclerView) findViewById(R.id.recyclerview);
        mRecyclerView.setHasFixedSize(true);
        mRecyclerView.addItemDecoration(new RecyclerView.ItemDecoration() {
            @Override
            public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
                super.getItemOffsets(outRect, view, parent, state);
                outRect.left = 2;
                outRect.top = 2;
                outRect.bottom = 2;
            }
        });

        final GridLayoutManager gridLayoutManager = new GridLayoutManager(this, 3);
        gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
            @Override
            public int getSpanSize(int position) {
                return position == 0 ? gridLayoutManager.getSpanCount() : 1;
            }
        });
        mRecyclerView.setLayoutManager(gridLayoutManager);
        ArrayList<String> mStrings = new ArrayList<>();
        for (int i = 0; i < 18; i++) {
            mStrings.add("item  "+i);
        }
        ItemTouchRecyclerViewAdapter adapter = new ItemTouchRecyclerViewAdapter(mStrings);
        mRecyclerView.setAdapter(adapter);
        MyRecyclerViewTouchCallBack callBack= new MyRecyclerViewTouchCallBack(adapter);
        ItemTouchHelper touchHelper = new ItemTouchHelper(callBack);
        touchHelper.attachToRecyclerView(mRecyclerView);
    }
}
Screenshot_1495950511.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 173,928评论 25 709
  • afinalAfinal是一个android的ioc,orm框架 https://github.com/yangf...
    passiontim阅读 15,601评论 2 45
  • 简介: 提供一个让有限的窗口变成一个大数据集的灵活视图。 术语表: Adapter:RecyclerView的子类...
    酷泡泡阅读 5,239评论 0 16
  • 这篇文章分三个部分,简单跟大家讲一下 RecyclerView 的常用方法与奇葩用法;工作原理与ListView比...
    LucasAdam阅读 4,446评论 0 27
  • 偶然的机会,一位未见面却感觉很亲切的姐姐,闲聊中提及到简书,立马很欢喜的加入进来。 原本我便十分喜爱写些摘文,从读...
    幽蓝_星空阅读 234评论 1 0