ItemTouchHelper类
之前我们实现了滑动列表的一些基本功能,为了实现更多的效果,我们来仔细看一下ItemTouchHelper中的类:
ItemTouchHelper.SimpleCallback
这个主要是帮你写好了getMovementFlags,你只要直接传一些参数即可,看一下怎么用:
ItemTouchHelper mIth = new ItemTouchHelper( new ItemTouchHelper.SimpleCallback(ItemTouchHelper.UP | ItemTouchHelper.DOWN, ItemTouchHelper.LEFT) { public abstract boolean onMove(RecyclerView recyclerView, ViewHolder viewHolder, ViewHolder target) { final int fromPos = viewHolder.getAdapterPosition(); final int toPos = target.getAdapterPosition(); // move item in `fromPos` to `toPos` in adapter. return true;// true if moved, false otherwise } public void onSwiped(ViewHolder viewHolder, int direction) { // remove from adapter } });
ItemTouchHelper.ViewDropHandler
An interface which can be implemented by LayoutManager for better integration with ItemTouchHelper
.
getItemOffsets
void getItemOffsets (Rect outRect, View view, RecyclerView parent, RecyclerView.State state)
Retrieve any offsets for the given item. Each field of outRect
specifies the number of pixels that the item view should be inset by, similar to padding or margin. The default implementation sets the bounds of outRect to 0 and returns.
If this ItemDecoration does not affect the positioning of item views, it should set all four fields of outRect
(left, top, right, bottom) to zero before returning.
If you need to access Adapter for additional data, you can call getChildAdapterPosition(View)
to get the adapter position of the View.
类似于itemDecoration里的getItemOffsets,也是用于给view设置padding的: outRect.set(l,t,r,b)
onDraw
void onDraw (Canvas c, RecyclerView parent, RecyclerView.State state)
Draw any appropriate decorations into the Canvas supplied to the RecyclerView. Any content drawn by this method will be drawn before the item views are drawn, and will thus appear underneath the views.
还有个onDrawOver方法,不过是用于之后的
startDrag | startSwipe
void startDrag (RecyclerView.ViewHolder viewHolder)
Starts dragging the provided ViewHolder. By default, ItemTouchHelper starts a drag when a View is long pressed. You can disable that behavior by overriding isLongPressDragEnabled()
.
For this method to work:
- The provided ViewHolder must be a child of the RecyclerView to which this ItemTouchHelper is attached.
ItemTouchHelper.Callback
must have dragging enabled.- There must be a previous touch event that was reported to the ItemTouchHelper through RecyclerView's ItemTouchListener mechanism. As long as no other ItemTouchListener grabs previous events, this should work as expected.
For example, if you would like to let your user to be able to drag an Item by touching one of its descendants, you may implement it as follows:
viewHolder.dragButton.setOnTouchListener(new View.OnTouchListener() { public boolean onTouch(View v, MotionEvent event) { if (MotionEvent.getActionMasked(event) == MotionEvent.ACTION_DOWN) { mItemTouchHelper.startDrag(viewHolder); } return false; } });
用于开始拖动的一些时间
ItemTouchHelper.Callback
canDropOver
boolean canDropOver (RecyclerView recyclerView, RecyclerView.ViewHolder current, RecyclerView.ViewHolder target)
Return true if the current ViewHolder can be dropped over the the target ViewHolder.
This method is used when selecting drop target for the dragged View. After Views are eliminated either via bounds check or via this method, resulting set of views will be passed to chooseDropTarget(ViewHolder, java.util.List, int, int)
.
Default implementation returns true.
用于判断某些target是否能拖过去
chooseDropTarget
RecyclerView.ViewHolder chooseDropTarget (RecyclerView.ViewHolder selected, List<RecyclerView.ViewHolder> dropTargets, int curX, int curY)
Called by ItemTouchHelper to select a drop target from the list of ViewHolders that are under the dragged View.
Default implementation filters the View with which dragged item have changed position in the drag direction. For instance, if the view is dragged UP, it compares the view.getTop()
of the two views before and after drag started. If that value is different, the target view passes the filter.
Among these Views which pass the test, the one closest to the dragged view is chosen.
This method is called on the main thread every time user moves the View. If you want to override it, make sure it does not do any expensive operations.
clearView
void clearView (RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder)
Called by the ItemTouchHelper when the user interaction with an element is over and it also completed its animation.
This is a good place to clear all changes on the View that was done inonSelectedChanged(RecyclerView.ViewHolder, int)
, onChildDraw(Canvas, RecyclerView, ViewHolder, float, float, int, boolean)
or onChildDrawOver(Canvas, RecyclerView, ViewHolder, float, float, int, boolean)
.
convertToAbsoluteDirection | convertToRelativeDirection
int convertToAbsoluteDirection (int flags, int layoutDirection)
Converts a given set of flags to absolution direction which means START
and END
are replaced with LEFT
and RIGHT
depending on the layout direction.
onSelectedChanged
void onSelectedChanged (RecyclerView.ViewHolder viewHolder, int actionState)
Called when the ViewHolder swiped or dragged by the ItemTouchHelper is changed.
If you override this method, you should call super.
实例
实现拖拽时改变颜色
@Override public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) { super.onSelectedChanged(viewHolder, actionState); if (actionState == ItemTouchHelper.ACTION_STATE_DRAG) { originColor=((ColorDrawable)viewHolder.itemView.getBackground()).getColor(); viewHolder.itemView.setBackgroundColor(Color.BLUE); } } @Override public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { super.clearView(recyclerView, viewHolder); viewHolder.itemView.setBackgroundColor(originColor); }