public abstract static class ItemTouchHelper.Callback
extends java.lang.Object
#getMovementFlags(RecyclerView, ViewHolder)
and return appropriate set
of direction flags. (ItemTouchHelper.LEFT
, ItemTouchHelper.RIGHT
, ItemTouchHelper.START
, ItemTouchHelper.END
,
ItemTouchHelper.UP
, ItemTouchHelper.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 RecyclerView.Adapter#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.Modifier and Type | Field and Description |
---|---|
static int |
DEFAULT_DRAG_ANIMATION_DURATION |
static int |
DEFAULT_SWIPE_ANIMATION_DURATION |
Constructor and Description |
---|
Callback() |
Modifier and Type | Method and Description |
---|---|
boolean |
canDropOver(android.support.v7.widget.RecyclerView recyclerView,
android.support.v7.widget.RecyclerView.ViewHolder current,
android.support.v7.widget.RecyclerView.ViewHolder target)
Return true if the current RowViewHolder can be dropped over the the target
RowViewHolder.
|
android.support.v7.widget.RecyclerView.ViewHolder |
chooseDropTarget(android.support.v7.widget.RecyclerView.ViewHolder selected,
java.util.List<android.support.v7.widget.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.
|
void |
clearView(android.support.v7.widget.RecyclerView recyclerView,
android.support.v7.widget.RecyclerView.ViewHolder viewHolder)
Called by the ItemTouchHelper when the user interaction with an element is over and it
also completed its animation.
|
int |
convertToAbsoluteDirection(int flags,
int layoutDirection)
Converts a given set of flags to absolution direction which means
ItemTouchHelper.START and
ItemTouchHelper.END are replaced with ItemTouchHelper.LEFT and ItemTouchHelper.RIGHT depending on the layout
direction. |
static int |
convertToRelativeDirection(int flags,
int layoutDirection)
Replaces a movement direction with its relative version by taking layout direction into
account.
|
long |
getAnimationDuration(android.support.v7.widget.RecyclerView recyclerView,
int animationType,
float animateDx,
float animateDy)
Called by the ItemTouchHelper when user action finished on a RowViewHolder and now the
View will be animated to its final position.
|
int |
getBoundingBoxMargin()
When finding views under a dragged view, by default, ItemTouchHelper searches for views
that overlap with the dragged View.
|
static android.support.v7.widget.helper.ItemTouchUIUtil |
getDefaultUIUtil()
Returns the
ItemTouchUIUtil that is used by the ItemTouchHelper.Callback class for visual
changes on Views in response to user interactions. |
abstract int |
getMovementFlags(android.support.v7.widget.RecyclerView recyclerView,
android.support.v7.widget.RecyclerView.ViewHolder viewHolder)
Should return a composite flag which defines the enabled move directions in each state
(idle, swiping, dragging).
|
float |
getMoveThreshold(android.support.v7.widget.RecyclerView.ViewHolder viewHolder)
Returns the fraction that the user should move the View to be considered as it is
dragged.
|
float |
getSwipeEscapeVelocity(float defaultValue)
Defines the minimum velocity which will be considered as a swipe action by the user.
|
float |
getSwipeThreshold(android.support.v7.widget.RecyclerView.ViewHolder viewHolder)
Returns the fraction that the user should move the View to be considered as swiped.
|
float |
getSwipeVelocityThreshold(float defaultValue)
Defines the maximum velocity ItemTouchHelper will ever calculate for pointer movements.
|
int |
interpolateOutOfBoundsScroll(android.support.v7.widget.RecyclerView recyclerView,
int viewSize,
int viewSizeOutOfBounds,
int totalSize,
long msSinceStartScroll)
Called by the ItemTouchHelper when user is dragging a view out of bounds.
|
boolean |
isItemViewSwipeEnabled()
Returns whether ItemTouchHelper should start a swipe operation if a pointer is swiped
over the View.
|
boolean |
isLongPressDragEnabled()
Returns whether ItemTouchHelper should start a drag and drop operation if an item is
long pressed.
|
static int |
makeFlag(int actionState,
int directions)
Shifts the given direction flags to the offset of the given action state.
|
static int |
makeMovementFlags(int dragFlags,
int swipeFlags)
Convenience method to create movement flags.
|
void |
onChildDraw(android.graphics.Canvas c,
android.support.v7.widget.RecyclerView recyclerView,
android.support.v7.widget.RecyclerView.ViewHolder viewHolder,
float dX,
float dY,
int actionState,
boolean isCurrentlyActive)
Called by ItemTouchHelper on RecyclerView's onDraw callback.
|
void |
onChildDrawOver(android.graphics.Canvas c,
android.support.v7.widget.RecyclerView recyclerView,
android.support.v7.widget.RecyclerView.ViewHolder viewHolder,
float dX,
float dY,
int actionState,
boolean isCurrentlyActive)
Called by ItemTouchHelper on RecyclerView's onDraw callback.
|
abstract boolean |
onMove(android.support.v7.widget.RecyclerView recyclerView,
android.support.v7.widget.RecyclerView.ViewHolder viewHolder,
android.support.v7.widget.RecyclerView.ViewHolder target)
Called when ItemTouchHelper wants to move the dragged item from its old position to
the new position.
|
void |
onMoved(android.support.v7.widget.RecyclerView recyclerView,
android.support.v7.widget.RecyclerView.ViewHolder viewHolder,
int fromPos,
android.support.v7.widget.RecyclerView.ViewHolder target,
int toPos,
int x,
int y)
Called when
#onMove(RecyclerView, ViewHolder, ViewHolder) returns true. |
void |
onSelectedChanged(android.support.v7.widget.RecyclerView.ViewHolder viewHolder,
int actionState)
Called when the RowViewHolder swiped or dragged by the ItemTouchHelper is changed.
|
abstract void |
onSwiped(android.support.v7.widget.RecyclerView.ViewHolder viewHolder,
int direction)
Called when a RowViewHolder is swiped by the user.
|
public static final int DEFAULT_DRAG_ANIMATION_DURATION
public static final int DEFAULT_SWIPE_ANIMATION_DURATION
public static android.support.v7.widget.helper.ItemTouchUIUtil getDefaultUIUtil()
ItemTouchUIUtil
that is used by the ItemTouchHelper.Callback
class for visual
changes on Views in response to user interactions. ItemTouchUIUtil
has different
implementations for different platform versions.
By default, ItemTouchHelper.Callback
applies these changes on RecyclerView.ViewHolder#itemView
.
For example, if you have a use case where you only want the text to move when user swipes
over the view, you can do the following:
public void clearView(RecyclerView recyclerView, RecyclerView.RowViewHolder viewHolder){ getDefaultUIUtil().clearView(((ItemTouchViewHolder) viewHolder).textView); } public void onSelectedChanged(RecyclerView.RowViewHolder viewHolder, int actionState) { if (viewHolder != null){ getDefaultUIUtil().onSelected(((ItemTouchViewHolder) viewHolder).textView); } } public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.RowViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) { getDefaultUIUtil().onDraw(c, recyclerView, ((ItemTouchViewHolder) viewHolder).textView, dX, dY, actionState, isCurrentlyActive); return true; } public void onChildDrawOver(Canvas c, RecyclerView recyclerView, RecyclerView.RowViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) { getDefaultUIUtil().onDrawOver(c, recyclerView, ((ItemTouchViewHolder) viewHolder).textView, dX, dY, actionState, isCurrentlyActive); return true; }
ItemTouchUIUtil
instance that is used by the ItemTouchHelper.Callback
public static int convertToRelativeDirection(int flags, int layoutDirection)
flags
- The flag value that include any number of movement flags.layoutDirection
- The layout direction of the View. Can be obtained from ViewCompat.getLayoutDirection(android.view.View)
.ItemTouchHelper.START
, ItemTouchHelper.END
) instead of
ItemTouchHelper.LEFT
, ItemTouchHelper.RIGHT
.convertToAbsoluteDirection(int, int)
public static int makeMovementFlags(int dragFlags, int swipeFlags)
makeMovementFlags(UP | DOWN, LEFT);
dragFlags
- The directions in which the item can be dragged.swipeFlags
- The directions in which the item can be swiped.public static int makeFlag(int actionState, int directions)
actionState
- The action state you want to get flags in. Should be one of ItemTouchHelper.ACTION_STATE_IDLE
, ItemTouchHelper.ACTION_STATE_SWIPE
or ItemTouchHelper.ACTION_STATE_DRAG
.directions
- The direction flags. Can be composed from ItemTouchHelper.UP
, ItemTouchHelper.DOWN
,
ItemTouchHelper.RIGHT
, ItemTouchHelper.LEFT
ItemTouchHelper.START
and ItemTouchHelper.END
.public abstract int getMovementFlags(android.support.v7.widget.RecyclerView recyclerView, android.support.v7.widget.RecyclerView.ViewHolder viewHolder)
makeMovementFlags(int,
int)
or makeFlag(int, int)
.
This flag is composed of 3 sets of 8 bits, where first 8 bits are for IDLE state, next
8 bits are for SWIPE state and third 8 bits are for DRAG state.
Each 8 bit sections can be constructed by simply OR'ing direction flags defined in
ItemTouchHelper
.
For example, if you want it to allow swiping LEFT and RIGHT but only allow starting to
swipe by swiping RIGHT, you can return:
makeFlag(ACTION_STATE_IDLE, RIGHT) | makeFlag(ACTION_STATE_SWIPE, LEFT | RIGHT);This means, allow right movement while IDLE and allow right and left movement while swiping.
recyclerView
- The RecyclerView to which ItemTouchHelper is attached.viewHolder
- The RowViewHolder for which the movement information is necessary.makeMovementFlags(int, int)
,
makeFlag(int, int)
public int convertToAbsoluteDirection(int flags, int layoutDirection)
ItemTouchHelper.START
and
ItemTouchHelper.END
are replaced with ItemTouchHelper.LEFT
and ItemTouchHelper.RIGHT
depending on the layout
direction.flags
- The flag value that include any number of movement flags.layoutDirection
- The layout direction of the RecyclerView.public boolean canDropOver(android.support.v7.widget.RecyclerView recyclerView, android.support.v7.widget.RecyclerView.ViewHolder current, android.support.v7.widget.RecyclerView.ViewHolder target)
#chooseDropTarget(ViewHolder, java.util.List, int, int)
.
Default implementation returns true.recyclerView
- The RecyclerView to which ItemTouchHelper is attached to.current
- The RowViewHolder that user is dragging.target
- The RowViewHolder which is below the dragged RowViewHolder.public abstract boolean onMove(android.support.v7.widget.RecyclerView recyclerView, android.support.v7.widget.RecyclerView.ViewHolder viewHolder, android.support.v7.widget.RecyclerView.ViewHolder target)
viewHolder
has been moved
to the adapter position of target
RowViewHolder
(RowViewHolder#getAdapterPosition()
).
If you don't support drag & drop, this method will never be called.recyclerView
- The RecyclerView to which ItemTouchHelper is attached to.viewHolder
- The RowViewHolder which is being dragged by the user.target
- The RowViewHolder over which the currently active item is being
dragged.viewHolder
has been moved to the adapter position of target
.#onMoved(RecyclerView, ViewHolder, int, ViewHolder, int, int, int)
public boolean isLongPressDragEnabled()
#startDrag(ViewHolder)
.true
.#startDrag(ViewHolder)
public boolean isItemViewSwipeEnabled()
#startSwipe(ViewHolder)
.true
.#startSwipe(ViewHolder)
public int getBoundingBoxMargin()
public float getSwipeThreshold(android.support.v7.widget.RecyclerView.ViewHolder viewHolder)
viewHolder
- The RowViewHolder that is being dragged.public float getMoveThreshold(android.support.v7.widget.RecyclerView.ViewHolder viewHolder)
viewHolder
- The RowViewHolder that is being dragged.public float getSwipeEscapeVelocity(float defaultValue)
getSwipeVelocityThreshold(float)
.
The velocity is calculated in pixels per second.
The default framework value is passed as a parameter so that you can modify it with a
multiplier.defaultValue
- The default value (in pixels per second) used by the
ItemTouchHelper.defaultValue
parameter.getSwipeVelocityThreshold(float)
,
#getSwipeThreshold(ViewHolder)
public float getSwipeVelocityThreshold(float defaultValue)
defaultValue
- The default value(in pixels per second) used by the ItemTouchHelper.defaultValue
parameter.getSwipeEscapeVelocity(float)
public android.support.v7.widget.RecyclerView.ViewHolder chooseDropTarget(android.support.v7.widget.RecyclerView.ViewHolder selected, java.util.List<android.support.v7.widget.RecyclerView.ViewHolder> dropTargets, int curX, int curY)
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.selected
- The RowViewHolder being dragged by the user.dropTargets
- The list of RowViewHolder that are under the dragged View and
candidate as a drop.curX
- The updated left value of the dragged View after drag translations are
applied. This value does not include margins added by RecyclerView.ItemDecoration
s.curY
- The updated top value of the dragged View after drag translations are
applied. This value does not include margins added by RecyclerView.ItemDecoration
s.public abstract void onSwiped(android.support.v7.widget.RecyclerView.ViewHolder viewHolder, int direction)
ItemTouchHelper.START
, ItemTouchHelper.END
) from the
#getMovementFlags(RecyclerView, ViewHolder)
method, this method
will also use relative directions. Otherwise, it will use absolute directions.
If you don't support swiping, this method will never be called.
ItemTouchHelper will keep a reference to the View until it is detached from
RecyclerView.
As soon as it is detached, ItemTouchHelper will call
#clearView(RecyclerView, ViewHolder)
.viewHolder
- The RowViewHolder which has been swiped by the user.direction
- The direction to which the RowViewHolder is swiped. It is one of ItemTouchHelper.UP
, ItemTouchHelper.DOWN
, ItemTouchHelper.LEFT
or ItemTouchHelper.RIGHT
. If your #getMovementFlags(RecyclerView, ViewHolder)
method returned relative
flags instead of ItemTouchHelper.LEFT
/ ItemTouchHelper.RIGHT
; `direction` will be
relative as well. (ItemTouchHelper.START
or ItemTouchHelper.END
).public void onSelectedChanged(android.support.v7.widget.RecyclerView.ViewHolder viewHolder, int actionState)
viewHolder
- The new RowViewHolder that is being swiped or dragged. Might be null
if it is cleared.actionState
- One of ItemTouchHelper.ACTION_STATE_IDLE
, ItemTouchHelper.ACTION_STATE_SWIPE
or ItemTouchHelper.ACTION_STATE_DRAG
.clearView(RecyclerView, RecyclerView.ViewHolder)
public void onMoved(android.support.v7.widget.RecyclerView recyclerView, android.support.v7.widget.RecyclerView.ViewHolder viewHolder, int fromPos, android.support.v7.widget.RecyclerView.ViewHolder target, int toPos, int x, int y)
#onMove(RecyclerView, ViewHolder, ViewHolder)
returns true.
ItemTouchHelper does not create an extra Bitmap or View while dragging, instead, it
modifies the existing View. Because of this reason, it is important that the View is
still part of the layout after it is moved. This may not work as intended when swapped
Views are close to RecyclerView bounds or there are gaps between them (e.g. other Views
which were not eligible for dropping over).
This method is responsible to give necessary hint to the LayoutManager so that it will
keep the View in visible area. For example, for LinearLayoutManager, this is as simple
as calling LinearLayoutManager.scrollToPositionWithOffset(int, int)
.
Default implementation calls RecyclerView.scrollToPosition(int)
if the View's
new position is likely to be out of bounds.
It is important to ensure the RowViewHolder will stay visible as otherwise, it might be
removed by the LayoutManager if the move causes the View to go out of bounds. In that
case, drag will end prematurely.recyclerView
- The RecyclerView controlled by the ItemTouchHelper.viewHolder
- The RowViewHolder under user's control.fromPos
- The previous adapter position of the dragged item (before it was
moved).target
- The RowViewHolder on which the currently active item has been
dropped.toPos
- The new adapter position of the dragged item.x
- The updated left value of the dragged View after drag translations
are applied. This value does not include margins added by RecyclerView.ItemDecoration
s.y
- The updated top value of the dragged View after drag translations are
applied. This value does not include margins added by RecyclerView.ItemDecoration
s.public void clearView(android.support.v7.widget.RecyclerView recyclerView, android.support.v7.widget.RecyclerView.ViewHolder viewHolder)
onSelectedChanged(RecyclerView.ViewHolder, int)
,
#onChildDraw(Canvas, RecyclerView, ViewHolder, float, float, int,
boolean)
or
#onChildDrawOver(Canvas, RecyclerView, ViewHolder, float, float, int, boolean)
.recyclerView
- The RecyclerView which is controlled by the ItemTouchHelper.viewHolder
- The View that was interacted by the user.public void onChildDraw(android.graphics.Canvas c, android.support.v7.widget.RecyclerView recyclerView, android.support.v7.widget.RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive)
dX
,
dY
.
ItemTouchHelper also takes care of drawing the child after other children if it is being
dragged. This is done using child re-ordering mechanism. On platforms prior to L, this
is
achieved via ViewGroup.getChildDrawingOrder(int, int)
and on L
and after, it changes View's elevation value to be greater than all other children.)c
- The canvas which RecyclerView is drawing its childrenrecyclerView
- The RecyclerView to which ItemTouchHelper is attached toviewHolder
- The RowViewHolder which is being interacted by the User or it
was interacted and simply animating to its original positiondX
- The amount of horizontal displacement caused by user's actiondY
- The amount of vertical displacement caused by user's actionactionState
- The type of interaction on the View. Is either ItemTouchHelper.ACTION_STATE_DRAG
or ItemTouchHelper.ACTION_STATE_SWIPE
.isCurrentlyActive
- True if this view is currently being controlled by the user or
false it is simply animating back to its original state.#onChildDrawOver(Canvas, RecyclerView, ViewHolder, float, float, int, boolean)
public void onChildDrawOver(android.graphics.Canvas c, android.support.v7.widget.RecyclerView recyclerView, android.support.v7.widget.RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive)
dX
,
dY
.
ItemTouchHelper also takes care of drawing the child after other children if it is being
dragged. This is done using child re-ordering mechanism. On platforms prior to L, this
is
achieved via ViewGroup.getChildDrawingOrder(int, int)
and on L
and after, it changes View's elevation value to be greater than all other children.)c
- The canvas which RecyclerView is drawing its childrenrecyclerView
- The RecyclerView to which ItemTouchHelper is attached toviewHolder
- The RowViewHolder which is being interacted by the User or it
was interacted and simply animating to its original positiondX
- The amount of horizontal displacement caused by user's actiondY
- The amount of vertical displacement caused by user's actionactionState
- The type of interaction on the View. Is either ItemTouchHelper.ACTION_STATE_DRAG
or ItemTouchHelper.ACTION_STATE_SWIPE
.isCurrentlyActive
- True if this view is currently being controlled by the user or
false it is simply animating back to its original state.#onChildDrawOver(Canvas, RecyclerView, ViewHolder, float, float, int, boolean)
public long getAnimationDuration(android.support.v7.widget.RecyclerView recyclerView, int animationType, float animateDx, float animateDy)
animationType
is ItemTouchHelper.ANIMATION_TYPE_DRAG
, it returns RecyclerView.ItemAnimator#getMoveDuration()
,
otherwise, it returns RecyclerView.ItemAnimator#getRemoveDuration()
. If
RecyclerView does not have any RecyclerView.ItemAnimator
attached, this method
returns DEFAULT_DRAG_ANIMATION_DURATION
or DEFAULT_SWIPE_ANIMATION_DURATION
depending on the animation type.recyclerView
- The RecyclerView to which the ItemTouchHelper is attached to.animationType
- The type of animation. Is one of ItemTouchHelper.ANIMATION_TYPE_DRAG
,
ItemTouchHelper.ANIMATION_TYPE_SWIPE_CANCEL
or ItemTouchHelper.ANIMATION_TYPE_SWIPE_SUCCESS
.animateDx
- The horizontal distance that the animation will offsetanimateDy
- The vertical distance that the animation will offsetpublic int interpolateOutOfBoundsScroll(android.support.v7.widget.RecyclerView recyclerView, int viewSize, int viewSizeOutOfBounds, int totalSize, long msSinceStartScroll)
recyclerView
- The RecyclerView instance to which ItemTouchHelper is attached
to.viewSize
- The total size of the View in scroll direction, excluding item
decorations.viewSizeOutOfBounds
- The total size of the View that is out of bounds. This value
is negative if the View is dragged towards left or top edge.totalSize
- The total size of RecyclerView in the scroll direction.msSinceStartScroll
- The time passed since View is kept out of bounds.RecyclerView.scrollBy(int, int)
method.