Android 個人相簿圖片拖拽排序
阿新 • • 發佈:2018-11-22
效果圖如下:
具體核心程式碼:
private ItemTouchHelper helper = new ItemTouchHelper(new ItemTouchHelper.Callback() { @Override public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { //設定監聽拖拽的方向 int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT; int swipeFlags = 0; return makeMovementFlags(dragFlags, swipeFlags); } @Override public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) { int fromPosition = viewHolder.getAdapterPosition();//得到item原來的position int toPosition = target.getAdapterPosition();//得到目標position if ((toPosition == listImgData.size() - 1 || listImgData.size() - 1 == fromPosition) && TextUtils.equals(listImgData.get(listImgData.size() - 1), "add")) { return true; } //滑動事件 Collections.swap(listImgData, viewHolder.getAdapterPosition(), target.getAdapterPosition()); mAdapter.notifyItemMoved(viewHolder.getAdapterPosition(), target.getAdapterPosition()); return false; } @Override public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { } @Override public boolean isLongPressDragEnabled() { //是否可拖拽 return false; } @Override public void onSelectedChanged(@Nullable RecyclerView.ViewHolder viewHolder, int actionState) { super.onSelectedChanged(viewHolder, actionState); if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) { viewHolder.itemView.setScaleX(1.1f); viewHolder.itemView.setScaleY(1.1f); } } @Override public void clearView(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) { super.clearView(recyclerView, viewHolder); if (!recyclerView.isComputingLayout()) { //拖拽結束後恢復view的狀態 viewHolder.itemView.setScaleX(1.0f); viewHolder.itemView.setScaleY(1.0f); } } });
這裡是否可以拖拽都是靠 isLongPressDragEnabled 這個回撥設定的,如果設定fase是不能拖拽的,由於我這裡最後一個是不能進行拖拽的,但是設定false就全部不能進行拖拽了,我們的需要的效果就是其他可以拖拽,最後一個或者特定字元的不需要拖拽
先檢視原始碼,發現這裡使用了isLongPressDragEnabled
private class ItemTouchHelperGestureListener extends GestureDetector.SimpleOnGestureListener { ItemTouchHelperGestureListener() { } @Override public boolean onDown(MotionEvent e) { return true; } @Override public void onLongPress(MotionEvent e) { View child = findChildView(e); if (child != null) { ViewHolder vh = mRecyclerView.getChildViewHolder(child); if (vh != null) { if (!mCallback.hasDragFlag(mRecyclerView, vh)) { return; } int pointerId = e.getPointerId(0); // Long press is deferred. // Check w/ active pointer id to avoid selecting after motion // event is canceled. if (pointerId == mActivePointerId) { final int index = e.findPointerIndex(mActivePointerId); final float x = e.getX(index); final float y = e.getY(index); mInitialTouchX = x; mInitialTouchY = y; mDx = mDy = 0f; if (DEBUG) { Log.d(TAG, "onlong press: x:" + mInitialTouchX + ",y:" + mInitialTouchY); } if (mCallback.isLongPressDragEnabled()) { select(vh, ACTION_STATE_DRAG); } } } } } }
上面原始碼ItemTouchHelperGestureListener是手指拖拽的一個監聽
如果長按的時候isLongPressDragEnabled 返回false ,控制元件就不會出現拖拽
上面程式碼用於監聽觸控手勢
觸控手勢的觸控監聽又由下面程式碼傳入觸控事件
最開始的觸控事件監聽是RecyclerView的
由此可見,重新自定義一個觸控手勢長按事件可滿足我們的需求
想法:需要拖拽執行就必須執行 select(vh, ACTION_STATE_DRAG);
看了看原始碼,尷尬,這個方法不能外部呼叫的,反正這個方法就是長按的時候可以讓你拖拽
繼續檢視剛剛的按個是否可以長按拖拽,發現旁邊有個 startDrag 的方法,
/**
* Returns whether ItemTouchHelper should start a drag and drop operation if an item is
* long pressed.
* <p>
* Default value returns true but you may want to disable this if you want to start
* dragging on a custom view touch using {@link #startDrag(ViewHolder)}.
*
* @return True if ItemTouchHelper should start dragging an item when it is long pressed,
* false otherwise. Default value is <code>true</code>.
* @see #startDrag(ViewHolder)
*/
public boolean isLongPressDragEnabled() {
return true;
}
發現startDrag 裡面也是執行了 select(vh, ACTION_STATE_DRAG); 這個進行開始拖拽的
自定義手勢觸控程式碼:
public abstract class OnRecyclerItemClickListener implements RecyclerView.OnItemTouchListener {
private GestureDetectorCompat mGestureDetector;
private RecyclerView recyclerView;
public OnRecyclerItemClickListener(RecyclerView recyclerView) {
this.recyclerView = recyclerView;
mGestureDetector = new GestureDetectorCompat(recyclerView.getContext(), new ItemTouchHelperGestureListener());
}
@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
mGestureDetector.onTouchEvent(e);
return false;
}
@Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
mGestureDetector.onTouchEvent(e);
}
@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
private class ItemTouchHelperGestureListener extends GestureDetector.SimpleOnGestureListener {
@Override
public boolean onSingleTapUp(MotionEvent e) {
View child = recyclerView.findChildViewUnder(e.getX(), e.getY());
if (child != null) {
RecyclerView.ViewHolder vh = recyclerView.getChildViewHolder(child);
onItemClick(vh);
}
return true;
}
@Override
public void onLongPress(MotionEvent e) {
View child = recyclerView.findChildViewUnder(e.getX(), e.getY());
if (child != null) {
RecyclerView.ViewHolder vh = recyclerView.getChildViewHolder(child);
onItemLongClick(vh);
}
}
}
public abstract void onItemClick(RecyclerView.ViewHolder vh);
public abstract void onItemLongClick(RecyclerView.ViewHolder vh);
}
設定監聽:
mRecyclerView.addOnItemTouchListener(new OnRecyclerItemClickListener(mRecyclerView) {
@Override
public void onItemClick(RecyclerView.ViewHolder vh) {
}
@Override
public void onItemLongClick(RecyclerView.ViewHolder vh) {
//如果item不是最後一個,則執行拖拽
if (vh.getLayoutPosition() != listImgData.size() - 1) {
helper.startDrag(vh);
} else if (!TextUtils.equals(listImgData.get(listImgData.size() - 1), "add")) {
helper.startDrag(vh);
}
}
});
上面就是大體程式碼了