ItemTouchHelper主要是作用在RecyclerView上。本文仍在android 5.0新特性 RecyclerView使用初级基础上。可以看到实现的列表右边的ImageView的样式是一般常见的编辑图片 即提示用户可以进行 列表的移行操作。不知道各位看官是否看个我的这篇文章:自定义View(三) switch开关按钮 ViewDragHelper的使用初级 。其实ViewDragHelper很容易实现表格的滑动删除功能。但其更加普遍适用于所有View。而ItemTouchHelper是Android Design 库中专门针对RecyclerView的移动和滑动操作。好了。看看本文的具体实现。由于布局文件与android 5.0新特性 RecyclerView使用初级本文不在给出。
实现上述功能主要依赖一下辅助类ItemTouchHelperViewHolder、ItemTouchHelperAdapter、OnStartDragListener。(本文主要参考github上开源项目点击打开链接)
1.ItemTouchHelperViewHolder 提供选中和(移行、滑动)手势完成后回调
public interface ItemTouchHelperViewHolder {
/**
* Called when the {@link ItemTouchHelper} first registers an item as being moved or swiped.
* Implementations should update the item view to indicate it's active state.
*/
void onItemSelected();
/**
* Called when the {@link ItemTouchHelper} has completed the move or swipe, and the active item
* state should be cleared.
*/
void onItemClear();
}
2 ItemTouchHelperAdapter.java 提供move和dimiss删除接口
public interface ItemTouchHelperAdapter {
/**
* Called when an item has been dragged far enough to trigger a move. This is called every time
* an item is shifted, and <strong>not</strong> at the end of a "drop" event.<br/>
* <br/>
* Implementations should call {@link RecyclerView.Adapter#notifyItemMoved(int, int)} after
* adjusting the underlying data to reflect this move.
*
* @param fromPosition The start position of the moved item.
* @param toPosition Then resolved position of the moved item.
* @return True if the item was moved to the new adapter position.
*
* @see RecyclerView#getAdapterPositionFor(RecyclerView.ViewHolder)
* @see RecyclerView.ViewHolder#getAdapterPosition()
*/
boolean onItemMove(int fromPosition, int toPosition);
/**
* Called when an item has been dismissed by a swipe.<br/>
* <br/>
* Implementations should call {@link RecyclerView.Adapter#notifyItemRemoved(int)} after
* adjusting the underlying data to reflect this removal.
*
* @param position The position of the item dismissed.
*
* @see RecyclerView#getAdapterPositionFor(RecyclerView.ViewHolder)
* @see RecyclerView.ViewHolder#getAdapterPosition()
*/
void onItemDismiss(int position);
}
3 初始化Drag回调 OnStartDragListener
public interface OnStartDragListener {
/**
* Called when a view is requesting a start of a drag.
*
* @param viewHolder The holder of the view to drag.
*/
void onStartDrag(RecyclerView.ViewHolder viewHolder);
}
4 具体的ItemTouchHelper(callback)初始化需要传递一个callback参数。
/*
* Copyright (C) 2015 Paul Burke
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.gzlanhengwu.touchhelperdemo;
import android.annotation.TargetApi;
import android.graphics.Canvas;
import android.os.Build;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
/**
* An implementation of {@link ItemTouchHelper.Callback} that enables basic drag & drop and
* swipe-to-dismiss. Drag events are automatically started by an item long-press.<br/>
* </br/>
* Expects the <code>RecyclerView.Adapter</code> to listen for {@link
* ItemTouchHelperAdapter} callbacks and the <code>RecyclerView.ViewHolder</code> to implement
* {@link ItemTouchHelperViewHolder}.
*
* @author Paul Burke (ipaulpro)
*/
public class SimpleItemTouchHelperCallback extends ItemTouchHelper.Callback {
public static final float ALPHA_FULL = 1.0f;
private final ItemTouchHelperAdapter mAdapter;
public SimpleItemTouchHelperCallback(ItemTouchHelperAdapter adapter) {
mAdapter = adapter;
}
//support longpress and swipe gesture
@Override
public boolean isLongPressDragEnabled() {
return true;
}
@Override
public boolean isItemViewSwipeEnabled() {
return true;
}
//
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
// Set movement flags based on the layout manager
if (recyclerView.getLayoutManager() instanceof GridLayoutManager) {
final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
final int swipeFlags = 0;
return makeMovementFlags(dragFlags, swipeFlags);
} else {
final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
final int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END;
return makeMovementFlags(dragFlags, swipeFlags);
}
}
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder source, RecyclerView.ViewHolder target) {
if (source.getItemViewType() != target.getItemViewType()) {
return false;
}
// Notify the adapter of the move
mAdapter.onItemMove(source.getAdapterPosition(), target.getAdapterPosition());
return true;
}
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int i) {
// Notify the adapter of the dismissal
mAdapter.onItemDismiss(viewHolder.getAdapterPosition());
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
@Override
public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) {
// Fade out the view as it is swiped out of the parent's bounds
final float alpha = ALPHA_FULL - Math.abs(dX) / (float) viewHolder.itemView.getWidth();
viewHolder.itemView.setAlpha(alpha);
viewHolder.itemView.setTranslationX(dX);
} else {
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
}
}
@Override
public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
// We only want the active item to change
if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) {
if (viewHolder instanceof ItemTouchHelperViewHolder) {
// Let the view holder know that this item is being moved or dragged
ItemTouchHelperViewHolder itemViewHolder = (ItemTouchHelperViewHolder) viewHolder;
itemViewHolder.onItemSelected();
}
}
super.onSelectedChanged(viewHolder, actionState);
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
@Override
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
super.clearView(recyclerView, viewHolder);
viewHolder.itemView.setAlpha(ALPHA_FULL);
if (viewHolder instanceof ItemTouchHelperViewHolder) {
// Tell the view holder it's time to restore the idle state
ItemTouchHelperViewHolder itemViewHolder = (ItemTouchHelperViewHolder) viewHolder;
itemViewHolder.onItemClear();
}
}
}
主要的复写的方法有:
(1)支持手势的(长按和swipe)
public boolean isLongPressDragEnabled()
public boolean isItemViewSwipeEnabled()
(2)public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) 由于本文采用列表 LinearLayoutManager
返回的是:
final int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
final int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END;
return makeMovementFlags(dragFlags, swipeFlags);
即支持 上下drag移动和左右swipe
(3)public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder source, RecyclerView.ViewHolder target) 对移行操作响应。具体丢给回调处理在RecyclerView.Adapter实现类中处理。
(4)public void onSwiped(RecyclerView.ViewHolder viewHolder, int i) 滑动操作处理 同上。
以下函数省略。注:这里的动画为属性动画 需要在 3.0以上才支持。可以使用nineoldandroids兼容较低版本。
5 又见MyRecycleViewAdapter类
public class MyRecycleViewAdapter extends RecyclerView.Adapter<MyRecycleViewAdapter.MyViewHolder>implements ItemTouchHelperAdapter {
private List<String>mData;
private Context mContext;
private final OnStartDragListener mDragStartListener;
public MyRecycleViewAdapter(List<String> mData, Context context, OnStartDragListener mDragStartListener) {
this.mData = mData;
mContext=context;
this.mDragStartListener = mDragStartListener;
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView= LayoutInflater.from(mContext).inflate(R.layout.item_main,parent,false);
return new MyViewHolder(itemView);
}
@Override
public void onBindViewHolder(final MyViewHolder holder, int position) {
holder.text.setText(mData.get(position));
holder.image.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (MotionEventCompat.getActionMasked(event) == MotionEvent.ACTION_DOWN) {
mDragStartListener.onStartDrag(holder);
}
return false;
}
});
// holder.itemView.setTag(mData.get(position));
}
@Override
public int getItemCount() {
return mData.size();
}
@Override
public boolean onItemMove(int fromPosition, int toPosition) {
Collections.swap(mData, fromPosition, toPosition);
notifyItemMoved(fromPosition, toPosition);
return true;
}
@Override
public void onItemDismiss(int position) {
mData.remove(position);
notifyItemRemoved(position);
}
public static class MyViewHolder extends RecyclerView.ViewHolder implements
ItemTouchHelperViewHolder{
public ImageView image;
public TextView text;
public MyViewHolder(View itemView) {
super(itemView);
image= (ImageView) itemView.findViewById(R.id.handle);
text= (TextView) itemView.findViewById(R.id.text);
}
@Override
public void onItemSelected() {
itemView.setBackgroundColor(Color.LTGRAY);
}
@Override
public void onItemClear() {
itemView.setBackgroundColor(0);
}
}
}本类中实现了ViewHolder事件绑定。
public boolean onItemMove(int fromPosition, int toPosition)
public void onItemDismiss(int position)
具体实现了移行和删行功能。
6 使用 MainActivity类中
public class MainActivity extends ActionBarActivity implements OnStartDragListener{
private RecyclerView mRecyclerView;
private RecyclerView.Adapter mAdapter;
private RecyclerView.LayoutManager mLayoutManager;
private List<String> mData;
private ItemTouchHelper mItemTouchHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
// setlayoutManager
mLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);
//setAdapter
mData = new ArrayList<>();
for (int i = 0; i < 100; i++) {
mData.add("this is position:" + i);
}
mAdapter = new MyRecycleViewAdapter(mData, this, this);
mRecyclerView.setAdapter(mAdapter);
ItemTouchHelper.Callback callback = new SimpleItemTouchHelperCallback((ItemTouchHelperAdapter) mAdapter);
mItemTouchHelper = new ItemTouchHelper(callback);
mItemTouchHelper.attachToRecyclerView(mRecyclerView);
}
@Override
public void onStartDrag(RecyclerView.ViewHolder viewHolder) {
mItemTouchHelper.startDrag(viewHolder);
}
}
参考:https://medium.com/@ipaulpro/drag-and-swipe-with-recyclerview-6a6f0c422efd
本文介绍了如何利用Android Design库中的ItemTouchHelper实现RecyclerView列表的移行和滑动删除功能。通过ItemTouchHelperViewHolder、ItemTouchHelperAdapter和OnStartDragListener等关键组件,实现长按拖动和左右滑动操作。文章详细讲解了isLongPressDragEnabled、getMovementFlags、onMove和onSwiped等方法的应用,并提供了MyRecycleViewAdapter的实现细节。

1064

被折叠的 条评论
为什么被折叠?



